/*! * # Fomantic-UI 2.9.2 - Transition * https://github.com/fomantic/Fomantic-UI/ * * * Released under the MIT license * https://opensource.org/licenses/MIT * */ (function ($, window, document) { 'use strict'; function isFunction(obj) { return typeof obj === 'function' && typeof obj.nodeType !== 'number'; } window = window !== undefined && window.Math === Math ? window : globalThis; $.fn.transition = function () { var $allModules = $(this), moduleSelector = $allModules.selector || '', time = Date.now(), performance = [], moduleArguments = arguments, query = moduleArguments[0], queryArguments = [].slice.call(arguments, 1), methodInvoked = typeof query === 'string', returnedValue ; $allModules.each(function (index) { var $module = $(this), element = this, // set at run time settings, instance, error, className, metadata, moduleNamespace, eventNamespace, module ; module = { initialize: function () { // get full settings settings = module.get.settings.apply(element, moduleArguments); // shorthand className = settings.className; error = settings.error; metadata = settings.metadata; // define namespace eventNamespace = '.' + settings.namespace; moduleNamespace = 'module-' + settings.namespace; instance = $module.data(moduleNamespace) || module; if (methodInvoked) { methodInvoked = module.invoke(query); } // method not invoked, lets run an animation if (methodInvoked === false) { module.verbose('Converted arguments into settings object', settings); if (settings.interval) { module.delay(settings.interval); } else { module.animate(); } module.instantiate(); } }, instantiate: function () { module.verbose('Storing instance of module', module); instance = module; $module .data(moduleNamespace, instance) ; }, destroy: function () { module.verbose('Destroying previous module for', element); $module .removeData(moduleNamespace) ; }, refresh: function () { module.verbose('Refreshing display type on next animation'); delete module.displayType; }, forceRepaint: function () { module.verbose('Forcing element repaint'); var $parentElement = $module.parent(), $nextElement = $module.next() ; if ($nextElement.length === 0) { $module.detach().appendTo($parentElement); } else { $module.detach().insertBefore($nextElement); } }, repaint: function () { module.verbose('Repainting element'); var fakeAssignment = element.offsetWidth ; }, delay: function (interval) { var direction = module.get.animationDirection(), shouldReverse, delay ; if (!direction) { direction = module.can.transition() ? module.get.direction() : 'static'; } interval = interval !== undefined ? interval : settings.interval; shouldReverse = settings.reverse === 'auto' && direction === className.outward; delay = shouldReverse || settings.reverse === true ? ($allModules.length - index) * interval : index * interval; module.debug('Delaying animation by', delay); setTimeout(module.animate, delay); }, animate: function (overrideSettings) { settings = overrideSettings || settings; module.debug('Preparing animation', settings.animation); if (module.is.animating()) { if (settings.queue) { if (!settings.allowRepeats && module.has.direction() && module.is.occurring() && module.queuing !== true) { module.debug('Animation is currently occurring, preventing queueing same animation', settings.animation); } else { module.queue(settings.animation); } return false; } if (!settings.allowRepeats && module.is.occurring()) { module.debug('Animation is already occurring, will not execute repeated animation', settings.animation); return false; } module.debug('New animation started, completing previous early', settings.animation); instance.complete(); } if (module.can.animate()) { module.set.animating(settings.animation); } else { module.error(error.noAnimation, settings.animation, element); } }, reset: function () { module.debug('Resetting animation to beginning conditions'); module.remove.animationCallbacks(); module.restore.conditions(); module.remove.animating(); }, queue: function (animation) { module.debug('Queueing animation of', animation); module.queuing = true; $module .one('animationend.queue' + eventNamespace, function () { module.queuing = false; module.repaint(); module.animate.apply(this, settings); }) ; }, complete: function (event) { if (event && event.target === element) { event.stopPropagation(); } module.debug('Animation complete', settings.animation); module.remove.completeCallback(); module.remove.failSafe(); if (!module.is.looping()) { if (module.is.outward()) { module.verbose('Animation is outward, hiding element'); module.restore.conditions(); module.hide(); } else if (module.is.inward()) { module.verbose('Animation is inward, showing element'); module.restore.conditions(); module.show(); } else { module.verbose('Static animation completed'); module.restore.conditions(); settings.onComplete.call(element); } } }, force: { visible: function () { var style = $module.attr('style'), userStyle = module.get.userStyle(style), displayType = module.get.displayType(), overrideStyle = userStyle + 'display: ' + displayType + ' !important;', inlineDisplay = $module[0].style.display, mustStayHidden = !displayType || (inlineDisplay === 'none' && settings.skipInlineHidden) || $module[0].tagName.match(/(script|link|style)/i) ; if (mustStayHidden) { module.remove.transition(); return false; } module.verbose('Overriding default display to show element', displayType); $module .attr('style', overrideStyle) ; return true; }, hidden: function () { var style = $module.attr('style'), currentDisplay = $module.css('display'), emptyStyle = style === undefined || style === '' ; if (currentDisplay !== 'none' && !module.is.hidden()) { module.verbose('Overriding default display to hide element'); $module .css('display', 'none') ; } else if (emptyStyle) { $module .removeAttr('style') ; } }, }, has: { direction: function (animation) { var hasDirection = false ; animation = animation || settings.animation; if (typeof animation === 'string') { animation = animation.split(' '); $.each(animation, function (index, word) { if (word === className.inward || word === className.outward) { hasDirection = true; } }); } return hasDirection; }, inlineDisplay: function () { var style = $module.attr('style') || '' ; return Array.isArray(style.match(/display.*?;/, '')); }, }, set: { animating: function (animation) { // remove previous callbacks module.remove.completeCallback(); // determine exact animation animation = animation || settings.animation; var animationClass = module.get.animationClass(animation); // save animation class in cache to restore class names module.save.animation(animationClass); if (module.force.visible()) { module.remove.hidden(); module.remove.direction(); module.start.animation(animationClass); } }, duration: function (animationName, duration) { duration = duration || settings.duration; duration = typeof duration === 'number' ? duration + 'ms' : duration; if (duration || duration === 0) { module.verbose('Setting animation duration', duration); $module .css({ 'animation-duration': duration, }) ; } }, direction: function (direction) { direction = direction || module.get.direction(); if (direction === className.inward) { module.set.inward(); } else { module.set.outward(); } }, looping: function () { module.debug('Transition set to loop'); $module .addClass(className.looping) ; }, hidden: function () { $module .addClass(className.transition) .addClass(className.hidden) ; }, inward: function () { module.debug('Setting direction to inward'); $module .removeClass(className.outward) .addClass(className.inward) ; }, outward: function () { module.debug('Setting direction to outward'); $module .removeClass(className.inward) .addClass(className.outward) ; }, visible: function () { $module .addClass(className.transition) .addClass(className.visible) ; }, }, start: { animation: function (animationClass) { animationClass = animationClass || module.get.animationClass(); module.debug('Starting tween', animationClass); $module .addClass(animationClass) .one('animationend.complete' + eventNamespace, module.complete) ; if (settings.useFailSafe) { module.add.failSafe(); } module.set.duration(settings.duration); settings.onStart.call(element); }, }, save: { animation: function (animation) { if (!module.cache) { module.cache = {}; } module.cache.animation = animation; }, displayType: function (displayType) { if (displayType !== 'none') { $module.data(metadata.displayType, displayType); } }, transitionExists: function (animation, exists) { $.fn.transition.exists[animation] = exists; module.verbose('Saving existence of transition', animation, exists); }, }, restore: { conditions: function () { var animation = module.get.currentAnimation() ; if (animation) { $module .removeClass(animation) ; module.verbose('Removing animation class', module.cache); } module.remove.duration(); }, }, add: { failSafe: function () { var duration = module.get.duration() ; module.timer = setTimeout(function () { $module.triggerHandler('animationend'); }, duration + settings.failSafeDelay); module.verbose('Adding fail safe timer', module.timer); }, }, remove: { animating: function () { $module.removeClass(className.animating); }, animationCallbacks: function () { module.remove.queueCallback(); module.remove.completeCallback(); }, queueCallback: function () { $module.off('.queue' + eventNamespace); }, completeCallback: function () { $module.off('.complete' + eventNamespace); }, display: function () { $module.css('display', ''); }, direction: function () { $module .removeClass(className.inward) .removeClass(className.outward) ; }, duration: function () { $module .css('animation-duration', '') ; }, failSafe: function () { module.verbose('Removing fail safe timer', module.timer); if (module.timer) { clearTimeout(module.timer); } }, hidden: function () { $module.removeClass(className.hidden); }, visible: function () { $module.removeClass(className.visible); }, looping: function () { module.debug('Transitions are no longer looping'); if (module.is.looping()) { module.reset(); $module .removeClass(className.looping) ; } }, transition: function () { $module .removeClass(className.transition) .removeClass(className.visible) .removeClass(className.hidden) ; }, }, get: { settings: function (animation, duration, onComplete) { if (typeof animation === 'object') { // single settings object return $.extend(true, {}, $.fn.transition.settings, animation); } if (typeof onComplete === 'function') { // all arguments provided return $.extend({}, $.fn.transition.settings, { animation: animation, onComplete: onComplete, duration: duration, }); } if (typeof duration === 'string' || typeof duration === 'number') { // only duration provided return $.extend({}, $.fn.transition.settings, { animation: animation, duration: duration, }); } if (typeof duration === 'object') { // duration is actually settings object return $.extend({}, $.fn.transition.settings, duration, { animation: animation, }); } if (typeof duration === 'function') { // duration is actually callback return $.extend({}, $.fn.transition.settings, { animation: animation, onComplete: duration, }); } // only animation provided return $.extend({}, $.fn.transition.settings, { animation: animation, }); }, animationClass: function (animation) { var animationClass = animation || settings.animation, directionClass = module.can.transition() && !module.has.direction() ? module.get.direction() + ' ' : '' ; return className.animating + ' ' + className.transition + ' ' + directionClass + animationClass; }, currentAnimation: function () { return module.cache && module.cache.animation !== undefined ? module.cache.animation : false; }, currentDirection: function () { return module.is.inward() ? className.inward : className.outward; }, direction: function () { return module.is.hidden() || !module.is.visible() ? className.inward : className.outward; }, animationDirection: function (animation) { var direction ; animation = animation || settings.animation; if (typeof animation === 'string') { animation = animation.split(' '); // search animation name for out/in class $.each(animation, function (index, word) { if (word === className.inward) { direction = className.inward; } else if (word === className.outward) { direction = className.outward; } }); } // return found direction if (direction) { return direction; } return false; }, duration: function (duration) { duration = duration || settings.duration; if (duration === false) { duration = $module.css('animation-duration') || 0; } return typeof duration === 'string' ? (duration.indexOf('ms') > -1 ? parseFloat(duration) : parseFloat(duration) * 1000) : duration; }, displayType: function (shouldDetermine) { shouldDetermine = shouldDetermine !== undefined ? shouldDetermine : true; if (settings.displayType) { return settings.displayType; } if (shouldDetermine && $module.data(metadata.displayType) === undefined) { var currentDisplay = $module.css('display'); if (currentDisplay === '' || currentDisplay === 'none') { // create fake element to determine display state module.can.transition(true); } else { module.save.displayType(currentDisplay); } } return $module.data(metadata.displayType); }, userStyle: function (style) { style = style || $module.attr('style') || ''; return style.replace(/display.*?;/, ''); }, transitionExists: function (animation) { return $.fn.transition.exists[animation]; }, }, can: { transition: function (forced) { var animation = settings.animation, transitionExists = module.get.transitionExists(animation), displayType = module.get.displayType(false), elementClass, tagName, $clone, currentAnimation, inAnimation, directionExists ; if (transitionExists === undefined || forced) { module.verbose('Determining whether animation exists'); elementClass = $module.attr('class'); tagName = $module.prop('tagName'); $clone = $('<' + tagName + ' />').addClass(elementClass).insertAfter($module); currentAnimation = $clone .addClass(animation) .removeClass(className.inward) .removeClass(className.outward) .addClass(className.animating) .addClass(className.transition) .css('animationName') ; $clone.detach().insertAfter($module); inAnimation = $clone .addClass(className.inward) .css('animationName') ; if (!displayType) { $clone.detach().insertAfter($module); displayType = $clone .attr('class', elementClass) .removeAttr('style') .removeClass(className.hidden) .removeClass(className.visible) .show() .css('display') ; module.verbose('Determining final display state', displayType); module.save.displayType(displayType); } $clone.remove(); if (currentAnimation !== inAnimation) { module.debug('Direction exists for animation', animation); directionExists = true; } else if (currentAnimation === 'none' || !currentAnimation) { module.debug('No animation defined in css', animation); return; } else { module.debug('Static animation found', animation, displayType); directionExists = false; } module.save.transitionExists(animation, directionExists); } return transitionExists !== undefined ? transitionExists : directionExists; }, animate: function () { // can transition does not return a value if animation does not exist return module.can.transition() !== undefined; }, }, is: { animating: function () { return $module.hasClass(className.animating); }, inward: function () { return $module.hasClass(className.inward); }, outward: function () { return $module.hasClass(className.outward); }, looping: function () { return $module.hasClass(className.looping); }, occurring: function (animation) { animation = animation || settings.animation; animation = '.' + animation.replace(' ', '.'); return $module.filter(animation).length > 0; }, visible: function () { return $module.is(':visible'); }, hidden: function () { return $module.css('visibility') === 'hidden'; }, supported: function () { // keep method for backward compatibility until 2.10.0 return true; }, }, hide: function () { if (settings.onHide.call(element) === false) { module.verbose('Hide callback returned false cancelling hide'); return false; } module.verbose('Hiding element'); if (module.is.animating()) { module.reset(); } element.blur(); // IE will trigger focus change if element is not blurred before hiding module.remove.display(); module.remove.visible(); settings.onBeforeHide.call(element, module.hideNow); }, hideNow: function () { module.set.hidden(); module.force.hidden(); settings.onHidden.call(element); settings.onComplete.call(element); }, show: function (display) { if (module.force.visible() && settings.onShow.call(element) !== false) { module.verbose('Showing element', display); module.remove.hidden(); settings.onBeforeShow.call(element, module.showNow); } }, showNow: function () { module.set.visible(); settings.onVisible.call(element); settings.onComplete.call(element); }, toggle: function () { if (module.is.visible()) { module.hide(); } else { module.show(); } }, stop: function () { module.debug('Stopping current animation'); $module.triggerHandler('animationend'); }, stopAll: function () { module.debug('Stopping all animation'); module.remove.queueCallback(); $module.triggerHandler('animationend'); }, clear: { queue: function () { module.debug('Clearing animation queue'); module.remove.queueCallback(); }, }, enable: function () { module.verbose('Starting animation'); $module.removeClass(className.disabled); }, disable: function () { module.debug('Stopping animation'); $module.addClass(className.disabled); }, setting: function (name, value) { module.debug('Changing setting', name, value); if ($.isPlainObject(name)) { $.extend(true, settings, name); } else if (value !== undefined) { if ($.isPlainObject(settings[name])) { $.extend(true, settings[name], value); } else { settings[name] = value; } } else { return settings[name]; } }, internal: function (name, value) { if ($.isPlainObject(name)) { $.extend(true, module, name); } else if (value !== undefined) { module[name] = value; } else { return module[name]; } }, debug: function () { if (!settings.silent && settings.debug) { if (settings.performance) { module.performance.log(arguments); } else { module.debug = Function.prototype.bind.call(console.info, console, settings.name + ':'); module.debug.apply(console, arguments); } } }, verbose: function () { if (!settings.silent && settings.verbose && settings.debug) { if (settings.performance) { module.performance.log(arguments); } else { module.verbose = Function.prototype.bind.call(console.info, console, settings.name + ':'); module.verbose.apply(console, arguments); } } }, error: function () { if (!settings.silent) { module.error = Function.prototype.bind.call(console.error, console, settings.name + ':'); module.error.apply(console, arguments); } }, performance: { log: function (message) { var currentTime, executionTime, previousTime ; if (settings.performance) { currentTime = Date.now(); previousTime = time || currentTime; executionTime = currentTime - previousTime; time = currentTime; performance.push({ Name: message[0], Arguments: [].slice.call(message, 1) || '', Element: element, 'Execution Time': executionTime, }); } clearTimeout(module.performance.timer); module.performance.timer = setTimeout(module.performance.display, 500); }, display: function () { var title = settings.name + ':', totalTime = 0 ; time = false; clearTimeout(module.performance.timer); $.each(performance, function (index, data) { totalTime += data['Execution Time']; }); title += ' ' + totalTime + 'ms'; if (moduleSelector) { title += ' \'' + moduleSelector + '\''; } if ($allModules.length > 1) { title += ' (' + $allModules.length + ')'; } if (performance.length > 0) { console.groupCollapsed(title); if (console.table) { console.table(performance); } else { $.each(performance, function (index, data) { console.log(data.Name + ': ' + data['Execution Time'] + 'ms'); }); } console.groupEnd(); } performance = []; }, }, // modified for transition to return invoke success invoke: function (query, passedArguments, context) { var object = instance, maxDepth, found, response ; passedArguments = passedArguments || queryArguments; context = context || element; if (typeof query === 'string' && object !== undefined) { query = query.split(/[ .]/); maxDepth = query.length - 1; $.each(query, function (depth, value) { var camelCaseValue = depth !== maxDepth ? value + query[depth + 1].charAt(0).toUpperCase() + query[depth + 1].slice(1) : query; if ($.isPlainObject(object[camelCaseValue]) && (depth !== maxDepth)) { object = object[camelCaseValue]; } else if (object[camelCaseValue] !== undefined) { found = object[camelCaseValue]; return false; } else if ($.isPlainObject(object[value]) && (depth !== maxDepth)) { object = object[value]; } else if (object[value] !== undefined) { found = object[value]; return false; } else { return false; } }); } if (isFunction(found)) { response = found.apply(context, passedArguments); } else if (found !== undefined) { response = found; } if (Array.isArray(returnedValue)) { returnedValue.push(response); } else if (returnedValue !== undefined) { returnedValue = [returnedValue, response]; } else if (response !== undefined) { returnedValue = response; } return found !== undefined ? found : false; }, }; module.initialize(); }); return returnedValue !== undefined ? returnedValue : this; }; // Records if CSS transition is available $.fn.transition.exists = {}; $.fn.transition.settings = { // module info name: 'Transition', // hide all output from this component regardless of other settings silent: false, // debug content outputted to console debug: false, // verbose debug output verbose: false, // performance data output performance: true, // event namespace namespace: 'transition', // delay between animations in group interval: 0, // whether group animations should be reversed reverse: 'auto', // animation callback event onStart: function () {}, onComplete: function () {}, onShow: function () {}, onBeforeShow: function (callback) { callback.call(this); }, onVisible: function () {}, onHide: function () {}, onHidden: function () {}, onBeforeHide: function (callback) { callback.call(this); }, // whether timeout should be used to ensure callback fires in cases animationend does not useFailSafe: true, // delay in ms for fail safe failSafeDelay: 100, // whether EXACT animation can occur twice in a row allowRepeats: false, // Override final display type on visible displayType: false, // animation duration animation: 'fade', duration: false, // new animations will occur after previous ones queue: true, // whether initially inline hidden objects should be skipped for transition skipInlineHidden: false, metadata: { displayType: 'display', }, className: { animating: 'animating', disabled: 'disabled', hidden: 'hidden', inward: 'in', loading: 'loading', looping: 'looping', outward: 'out', transition: 'transition', visible: 'visible', }, // possible errors error: { noAnimation: 'Element is no longer attached to DOM. Unable to animate. Use silent setting to suppress this warning in production.', }, }; })(jQuery, window, document);