diff --git a/.gitignore b/.gitignore index c99260f..2f40f1c 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ .idea +.iml node_modules Gruntfile.js \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index 80b49cf..9f4d6b6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,10 +1,15 @@ CHANGELOG ========= -### 0.2.8 (xx-xx-2013) +### 0.2.9 (xx-xx-2014) ______________________ + n/a +### 0.2.8 (10-04-2014) +______________________ + + + Added ability for use in cjs + ### 0.2.7 (28-06-2013) ______________________ diff --git a/Gruntfile.coffee b/Gruntfile.coffee index 553b9e7..cb2da4f 100644 --- a/Gruntfile.coffee +++ b/Gruntfile.coffee @@ -2,14 +2,19 @@ module.exports = (grunt) -> grunt.initConfig pkg: grunt.file.readJSON "package.json" + # Clean task: + clean: + dist: ["./dist"] + # Concat task: concat: options: separator: "\n\n\n" banner: grunt.file.read "build/banner.txt" + footer: grunt.file.read "build/footer.txt" dist: src: ["src/core.js", "src/config.js", "src/algorithm/*.js", "src/effect/*.js"] - dest: "../gh-pages/build/<%= pkg.name.replace('-','.') %>.js" + dest: "./dist/<%= pkg.name.replace('-','.') %>.js" # Uglify task: uglify: @@ -17,8 +22,14 @@ module.exports = (grunt) -> banner: grunt.file.read "build/banner.min.txt" build: src: "<%= concat.dist.dest %>" - dest: "../gh-pages/build/<%= pkg.name.replace('-','.') %>.min.js" + dest: "./dist/<%= pkg.name.replace('-','.') %>.min.js" + # Copy task: + copy: + dist: + src: "./dist/*" + dest: "../gh-pages/build/" + # Jshint task: jshint: files: ["src/**/*.js"], @@ -33,8 +44,10 @@ module.exports = (grunt) -> latedef: true grunt.loadNpmTasks "grunt-contrib-concat" + grunt.loadNpmTasks "grunt-contrib-copy" + grunt.loadNpmTasks "grunt-contrib-clean" grunt.loadNpmTasks "grunt-contrib-uglify" grunt.loadNpmTasks "grunt-contrib-jshint" grunt.registerTask "test", ["jshint"] - grunt.registerTask "default", ["jshint", "concat", "uglify"] \ No newline at end of file + grunt.registerTask "default", ["clean", "jshint", "concat", "uglify", "copy"] \ No newline at end of file diff --git a/build/banner.txt b/build/banner.txt index ecdce27..55e03c9 100644 --- a/build/banner.txt +++ b/build/banner.txt @@ -28,3 +28,25 @@ */ + +!function(root, factory) { + + var isNode, isAMD, + jQuery; + + isNode = typeof module !== "undefined" && module.exports; + isAMD = typeof define === "function" && define.amd && typeof define.amd === "object"; + + if (isNode) { + jQuery = require("jquery"); + module.exports = factory(jQuery); + } else if (isAMD) { + define(['jquery'], function(jQuery) { + return factory(jQuery); + }); + } else { + factory(root.jQuery); + } + +}(this, function($) { + diff --git a/build/footer.txt b/build/footer.txt new file mode 100644 index 0000000..4fb9639 --- /dev/null +++ b/build/footer.txt @@ -0,0 +1,4 @@ + + + +}); \ No newline at end of file diff --git a/dist/jquery.loading.js b/dist/jquery.loading.js new file mode 100644 index 0000000..86870b4 --- /dev/null +++ b/dist/jquery.loading.js @@ -0,0 +1,890 @@ +/** + * jQuery Loading - Shows loading progress animation, flexible and pretty =). + * + * Version: 0.2.8 + * Date: 2014-04-17 20:56:07 + * + * Copyright 2014, Sergey Kamardin. + * + * Licensed under the MIT license. + * http://www.opensource.org/licenses/mit-license.php + * + * Location: Moscow, Russia. + * Contact: gobwas@gmail.com + * + * + * ___ ___ ___ ___ ___ + * /\ \ /\__\ /\ \ /\__\ /\__\ + * /::\ \ /:/ _/_ /::\ \ /:/ / /:/ _/_ + * /:/\:\__\ /:/ /\__\ /:/\:\ \ /:/ / /:/ /\__\ + * /:/ /:/ / /:/ /:/ _/_ /:/ /::\ \ /:/ / ___ /:/ /:/ _/_ + * /:/_/:/ / /:/_/:/ /\__\ /:/_/:/\:\__\ /:/__/ /\__\ /:/_/:/ /\__\ + * \:\/:/ / \:\/:/ /:/ / \:\/:/ \/__/ \:\ \ /:/ / \:\/:/ /:/ / + * \::/__/ \::/_/:/ / \::/__/ \:\ /:/ / \::/_/:/ / + * \:\ \ \:\/:/ / \:\ \ \:\/:/ / \:\/:/ / + * \:\__\ \::/ / \:\__\ \::/ / \::/ / + * \/__/ \/__/ \/__/ \/__/ \/__/ + * + */ + + + +!function(root, factory) { + + var isNode, isAMD, + jQuery; + + isNode = typeof module !== "undefined" && module.exports; + isAMD = typeof define === "function" && define.amd && typeof define.amd === "object"; + + if (isNode) { + jQuery = require("jquery"); + module.exports = factory(jQuery); + } else if (isAMD) { + define(['jquery'], function(jQuery) { + return factory(jQuery); + }); + } else { + factory(root.jQuery); + } + +}(this, function($) { + +(function($){ + "use strict"; + + /** + * Class definition. + * + * @param element + * @param options + * @constructor + */ + var Loading = function(element, options) { + /** + * Generate uniqueId for instance. + * Uses for non-conflict with DOM elements ID. + * + * @private + * @return {String} + */ + var uniqueId = (function() { + var chars = "abcdefghijklmnopqrstuvwxyz0123456789", + _length = 50; + + return function(length) + { + var max = chars.length - 1, + id = '', + symbol, + i; + + length || (length = _length); + + for (var x = 0; x < length; x++) { + i = parseInt(Math.floor(Math.random() * (max + 1)), 10); + + symbol = chars.charAt(i); + + Math.floor(Math.random() * 2) && (symbol = symbol.toUpperCase()); + + id+= symbol; + } + + return id; + }; + })(); + + /** + * Resolves which function to use as algorithm. + * + * @private + * @param config + * + * @throws {Error} + * + * @returns {Function} + */ + var algorithmResolver = function(config) { + var name, options; + + if (typeof config === 'function') { + return config; + } + + if (typeof config === 'string') { + name = config; + } else { + name = config.name; + config.options && (options = config.options); + } + + if (Loading.algorithm.hasOwnProperty(name)) { + var algorithm = Loading.algorithm[name]; + options && (algorithm.options = options); + + return algorithm; + } else { + throw new Error('Algorithm not found: "' + name + '"'); + } + }; + + /** + * Resolves which function to use as effect. + * + * @private + * + * @param config + * + * @throws {Error} + * + * @returns {Function} + */ + var effectResolver = function(config) { + var effect, name, options; + + if (typeof config == 'function') { + effect = config; + effect.count = 1; + return effect; + } + + if (config instanceof Array) { + var effects = []; + for (var x = 0; x < config.length; x++) { + effects.push(effectResolver(config[x])); + } + + effect = function() { + for (var x = 0; x < effects.length; x++) { + effects[x].apply(null, arguments); + } + }; + effect.count = effects.length; + + return effect; + + } else { + if (typeof config === 'string') { + name = config; + } else { + name = config.name; + config.options && (options = config.options); + } + + if (Loading.effect.hasOwnProperty(name)) { + effect = Loading.effect[name]; + effect.count = 1; + options && (effect.options = options); + return effect; + } else { + throw new Error('Effect not found: "' + name + '"'); + } + } + }; + + /** + * Normalizes given options. + * + * @private + * + * @param options + * @param dimensions + * + * @returns {*} + */ + var optionsNormalizer = function(options, dimensions) { + var spinner = options.spinner, + matrix = options.spinner.matrix, + pin = options.spinner.pin, + answer = $.extend({}, options); + + if (/^[0-9]{1,3}%$/.test(spinner.width)) { + spinner.width = (dimensions.width / 100) * spinner.width.substr(0, spinner.width.length - 1); + } + + if (/^[0-9]{1,3}%$/.test(spinner.height)) { + spinner.height = (dimensions.height / 100) * spinner.height.substr(0, spinner.height.length - 1); + } + + if (!matrix.x || !matrix.y) { + answer.spinner.matrix.x = Math.floor(spinner.width / (pin.width + pin.margin.left + pin.margin.right)); + answer.spinner.matrix.y = Math.floor(spinner.height / (pin.height + pin.margin.top + pin.margin.bottom)); + } else { + answer.spinner.pin.width = Math.floor((spinner.width - ((pin.margin.right + pin.margin.left) * matrix.x)) / matrix.x); + answer.spinner.pin.height = Math.floor((spinner.height - ((pin.margin.top + pin.margin.bottom) * matrix.y)) / matrix.y); + } + + answer.spinner.matrix.x-= 1; + answer.spinner.matrix.y-= 1; + + if (answer.spinner.pin.width <= 0 || answer.spinner.pin.height <= 0) { + throw new Error('There is not enough space for spinner.'); + } + + return answer; + }; + + /** + * Creates background element. + * + * @private + * + * @returns {HTMLElement} + */ + var createBackground = function(options, dimensions) { + var background = $('
'); + + var hardCss = { + position: 'absolute', + top: 0, + left: 0 + }; + + background.css($.extend({}, options.css, hardCss, dimensions)); + + return background; + }; + + /** + * Creates pin. + * + * @param {Object} options + * @param {Object} position + * + * @returns {HTMLElement} + */ + var createPin = function(options, position) { + var pin = $('
'); + + var hardCss = { + position: 'absolute', + width: options.width, + height: options.height, + top: position.y * (options.height +options.margin.top + options.margin.bottom), + left: position.x * (options.width +options.margin.left + options.margin.right) + }; + + pin + .css($.extend(options.css, hardCss)) + .attr({ + 'class': 'loading-pin' + }); + + return pin; + }; + + /** + * Creates matrix of pins. + * + * @param options + * @returns {Array} + */ + var createPins = function(options) { + var pins = []; + + for (var x = 0; x <= options.matrix.x; x++) { + pins[x] || (pins[x] = []); + for (var y = 0; y <= options.matrix.y; y++) { + pins[x][y] = createPin(options.pin, {x:x, y:y}); + } + } + + return pins; + }; + + /** + * Creates spinner element. + * + * @private + * + * @returns {HTMLElement} + */ + var createSpinner = function(options, dimensions, pins) { + var spinner = $('
'); + + spinner.css({ + position: 'absolute', + left: (dimensions.width - options.width) /2, + top: (dimensions.height - options.height) / 2, + width: options.width, + height: options.height + }); + + for (var x = 0; x < pins.length; x++) { + for (var y = 0; y < pins[x].length; y++) { + spinner.append(pins[x][y]); + } + } + + return spinner; + }; + + // Constructor + + options || (options = {}); + + this.target = element; + this.id = uniqueId(50); + + this.dimensions = { + width: this.target.outerWidth(), + height: this.target.outerHeight(), + top: this.target.offset().top, + left: this.target.offset().left + }; + + this.options = optionsNormalizer($.extend(true, {}, $.fn.loading.defaults, options), this.dimensions); + + this.runtime = { + progress: 0, + interval: null + }; + + this.pins = createPins(this.options.spinner); + + this.background = createBackground(this.options.background, this.dimensions); + this.spinner = createSpinner(this.options.spinner, this.dimensions, this.pins); + + this.algorithm = algorithmResolver(this.options.algorithm); + this.algorithmData = null; + + this.effect = effectResolver(this.options.effect); + + this.counter = 0; + + this.update(options.runtime); + }; + + Loading.prototype = (function() { + /** + * Checking runtime options. + * + * @private + * @static + */ + var _checkRuntime = function() { + if ((typeof this.runtime.progress == 'number' && this.runtime.progress >= 100)) { + _destruct.call(this); + return; + } + + if (typeof this.runtime.interval == 'number' && this.runtime.interval != this.actualInterval) { + this.pause(); + this.resume(this.runtime.interval); + } + }; + + /** + * Deletes Loading instance. + * + * @private + * @static + */ + var _destruct = function() { + clearInterval(this.intervalId); + + // maybe here must apply easeOut fx, then on fx ends, remove all divs + this.background.remove(); + + this.target.removeData('loading'); + }; + + return { + /** + * Save reference to the constructor. + */ + constructor: Loading, + + /** + * Initializes runtime parameters. + * + * @param options Runtime options + */ + update: function(options) { + options || (options = {}); + $.extend(true, this.runtime, options); + }, + + /** + * Shows loading element. + */ + show: function() { + this.background.append(this.spinner).appendTo(document.body);//.appendTo(this.target); + }, + + /** + * Starts animation. + */ + start: function(interval) + { + this.actualInterval = interval || this.options.spinner.interval; + + if (this.actualInterval > 0x7fffffff) this.actualInterval = 0x7fffffff; + + var loading = this, + matrix = {x: this.options.spinner.matrix.x, y: this.options.spinner.matrix.y}, + effectInterval = Math.round(this.actualInterval/this.effect.count); + + this.intervalId = setInterval(function() { + loading.algorithmData = loading.algorithm(matrix, loading.algorithmData); + loading.effect(loading.pins[loading.algorithmData.x][loading.algorithmData.y], effectInterval, loading.runtime); + loading.counter++; + + // call private method + _checkRuntime.call(loading); + }, this.actualInterval); + }, + + /** + * Pauses animation. + */ + pause: function() + { + clearInterval(this.intervalId); + }, + + /** + * Resumes animation. + * + * @param interval + */ + resume: function(interval) + { + this.start(interval); + } + }; + })(); + + /** + * Container for algorithm functions. + * @type {Object} + */ + Loading.algorithm = {}; + + /** + * Container for effect functions. + * @type {Object} + */ + Loading.effect = {}; + + /** + * jQuery plugin definition. + * @param options + */ + $.fn.loading = function(options) { + var loading; + + if (!this.data('loading')) { + loading = new Loading(this, options); + this.data({loading: loading}); + + loading.show(); + loading.start(); + } else { + loading = this.data('loading'); + + loading.update(options); + } + }; + + /** + * Gives an ability for adding custom algorithms. + * + * @param {String} name + * @param {Function} algorithm + * @param {Object} [options] + */ + $.fn.loading.algorithm = function(name, algorithm, options) { + Loading.algorithm[name] = algorithm; + if (options) { + Loading.algorithm[name].options = options; + } + }; + + /** + * Gives an ability for adding custom effects. + * + * @param {String} name + * @param {Function} effect + * @param {Object} [options] + */ + $.fn.loading.effect = function(name, effect, options) { + Loading.effect[name] = effect; + if (options) { + Loading.effect[name].options = options; + } + }; + + + return Loading; +})(jQuery); + + + +(function($) { + "use strict"; + + $.fn.loading.defaults = { + //opacity: 0.9, + + algorithm: { + name: 'snake', + options: { + reverse: false + } + }, + + effect: ['simple'], + + spinner: { + width: "50%", + height: "30%", + matrix: { + x: null, + y: null + }, + pin: { + width: 5, + height: 5, + margin: { + top: 1, + right: 1, + bottom: 0, + left: 0 + }, + css: { + background: "green", + opacity: 0 + } + }, + interval: 100 + }, + + background: { + //color: 'white', + //img: null, + //borderRadius: 1, + // raw css + css: { + opacity: 0.8, + "z-index": 9999, + overflow: "hidden" + } + } + }; +})(jQuery); + + + +(function($) { + "use strict"; + + $.fn.loading.algorithm('linear', function(matrix, _) { + + }); +}).call(this, jQuery); + + + + +(function($) { + "use strict"; + + $.fn.loading.algorithm('random', function(options, _) { + /*var inter = 0, + z = 0; + + while (z < options.matrix.y * options.matrix.x) { + setTimeout( + (function(y,x){ + return function() { + effect(pins[y][x]); + }; + })(parseInt(Math.floor(Math.random() * (options.matrix.y)), 10),parseInt(Math.floor(Math.random() * (options.matrix.x)), 10)), inter); + + inter+= options.interval; + z++; + }*/ + }); +}).call(this, jQuery); + + +(function($) { + "use strict"; + + var defaults = { + reverse: true + }; + + $.fn.loading.algorithm('snake', (function() + { + var axisReverse = function (axis) { + return axis == 'x' ? 'y' : 'x'; + }; + + var checkIsInMatrix = function(x, y, _) { + var okay = true; + + okay = okay && (_.matrix.x[0] <= x && x <= _.matrix.x[1]); + okay = okay && (_.matrix.y[0] <= y && y <= _.matrix.y[1]); + + return okay; + }; + + var Path = function(_, reverseAxis, reverseSign, zeroMove) { + this.x = _.x; + this.y = _.y; + this.axis = reverseAxis ? axisReverse(_.axis) : _.axis; + this.sign = reverseSign ? -1 * _.sign : _.sign; + + if (!zeroMove) { + this[this.axis]+= this.sign; + } + }; + + // todo refactor as hash + var resolvers = [ + function(_) { + var path = new Path(_, false, false); + return checkIsInMatrix(path.x, path.y, _) ? path : false; + }, + function(_) { + var path = new Path(_, true, true); + return checkIsInMatrix(path.x, path.y, _) ? path : false; + }, + function(_) { + var path = new Path(_, true, false); + return checkIsInMatrix(path.x, path.y, _) ? path : false; + }, + function(_) { + var path = new Path(_, false, true, true); + return checkIsInMatrix(path.x, path.y, _) ? path : false; + } + ]; + + var resolvePath = function(_) { + var path; + + for (var x = 0; x < resolvers.length; x++) { + path = resolvers[x](_); + if (path instanceof Path) { + return path; + } + } + + return false; + }; + + var likeStart = function(path, _) { + return path.x == _.start.x && path.y == _.start.y; + }; + + var moveMatrix = function(_, sign) { + var x = [_.matrix.x[0] - sign, _.matrix.x[1] + sign], + y = [_.matrix.y[0] - sign, _.matrix.y[1] + sign]; + + if ((0 <= x[0] && x[0] <= x[1]) && (0 <= y[0] && y[0] <= y[1])) { + _.matrix.x = x; + _.matrix.y = y; + + return true; + } + + return false; + }; + + var moveStart = function(_, sign) { + var x,y; + + if (sign) { + x = _.start.x - sign; + y = _.start.y - sign; + } else { + x= _.x; + y = _.y; + } + + if (checkIsInMatrix(x,y,_)) { + _.start.x = x; + _.start.y = y; + + return true; + } + + return false; + }; + + var countPath = function(_) { + var x = _.matrix.x[1] - _.matrix.x[0], + y = _.matrix.y[1] - _.matrix.y[0], + len; + + if (x === 0 && y === 0) { + return 1; + } else if (x === 0) { + len = y + 1; + } else if (y === 0) { + len = x + 1; + } else { + len = 2 * (x + y); + } + + return len; + }; + + var reverse = function(_) { + _.sign *= -1; + _.reversed *= -1; + }; + + var reset = function(matrix) { + var _ = { + x: 0, + y: 0, + + axis: 'x', + sign: 1, + matrix: { + x: [0, matrix.x], + y: [0, matrix.y] + }, + path: 0, + reversed: -1 + }; + + _.fullPath = countPath(_); + + return _; + }; + + function Snake(matrix, _) { + + if (!_) { + _ = reset(matrix); + + _.path++; + return _; + } + + if (_.path == _.fullPath) { + if (!moveMatrix(_, _.reversed)) { + + if (Snake.options.reverse) { + reverse(_); + _.path = 0; + } else { + _ = reset(matrix); + } + + _.path++; + + return _; + } + + _.path = 0; + _.fullPath = countPath(_); + } + + var resolved = resolvePath(_); + + if (resolved) { + _.x = resolved.x; + _.y = resolved.y; + _.axis = resolved.axis; + _.sign = resolved.sign; + + _.path++; + return _; + } else { + throw new Error('Cant resolve path'); + } + } + + return Snake; + + })(), defaults); + +}).call(this, jQuery); + + + +(function($) { + "use strict"; + + var defaults = { + + }; + + $.fn.loading.effect('fancy', function(pin, interval, runtime) { + pin + .css({ + background: "#"+((1<<24)*Math.random()|0).toString(16) + }) + .animate({width: '-=2', height: '-=2', top: '+=1', left: '+=1'}, interval/2) + .animate({width: '+=2', height: '+=2', top: '-=1', left: '-=1'}, interval/2); + }, defaults); +}).call(this, jQuery); + + +(function($) { + "use strict"; + + var defaults = { + + }; + + $.fn.loading.effect('jump', function(pin, interval, runtime) { + var rnd = Math.floor(Math.random() * 7 + 1); + pin + .animate({top: '-=' + rnd}, interval/3 * 2) + .animate({top: '+=' + rnd}, interval/3); + }, defaults); +}).call(this, jQuery); + + +(function($) { + "use strict"; + + var defaults = { + + }; + + $.fn.loading.effect('simple-progress', function(pin, interval, runtime) { + if (!pin.data('simple-progress-init')) { + pin + .css({ + background: 'green', + opacity: runtime.progress/100 + }) + .data('simple-progress-init', true); + } + + pin + .data('simple-progress-sign', pin.data('simple-progress-sign') ? false : true) + .animate({ + opacity: pin.data('simple-progress-sign') ? 1 : runtime.progress/100 + }, interval); + }, defaults); +}).call(this, jQuery); + + +(function($) { + "use strict"; + + var defaults = { + + }; + + $.fn.loading.effect('simple', function(pin, interval, runtime) { + pin + .data('simple-sign', pin.data('simple-sign') ? false : true) + .animate({ + opacity: pin.data('simple-sign') ? 1 : 0 + }, interval); + }, defaults); + +}).call(this, jQuery); + + +}); \ No newline at end of file diff --git a/dist/jquery.loading.min.js b/dist/jquery.loading.min.js new file mode 100644 index 0000000..901fdec --- /dev/null +++ b/dist/jquery.loading.min.js @@ -0,0 +1,17 @@ +/** + * jQuery Loading - Shows loading progress animation, flexible and pretty =). + * + * Version: 0.2.8 + * + * Copyright 2014, Sergey Kamardin. + * + * Licensed under the MIT license. + * http://www.opensource.org/licenses/mit-license.php + * + * Date: 2014-04-17 20:56:08 + * Location: Moscow, Russia. + * Contact: gobwas@gmail.com + */ + + +!function(a,b){var c,d,e;c="undefined"!=typeof module&&module.exports,d="function"==typeof define&&define.amd&&"object"==typeof define.amd,c?(e=require("jquery"),module.exports=b(e)):d?define(["jquery"],function(a){return b(a)}):b(a.jQuery)}(this,function(){!function(a){"use strict";var b=function(c,d){var e=function(){var a="abcdefghijklmnopqrstuvwxyz0123456789",b=50;return function(c){var d,e,f=a.length-1,g="";c||(c=b);for(var h=0;c>h;h++)e=parseInt(Math.floor(Math.random()*(f+1)),10),d=a.charAt(e),Math.floor(2*Math.random())&&(d=d.toUpperCase()),g+=d;return g}}(),f=function(a){var c,d;if("function"==typeof a)return a;if("string"==typeof a?c=a:(c=a.name,a.options&&(d=a.options)),b.algorithm.hasOwnProperty(c)){var e=b.algorithm[c];return d&&(e.options=d),e}throw new Error('Algorithm not found: "'+c+'"')},g=function(a){var c,d,e;if("function"==typeof a)return c=a,c.count=1,c;if(a instanceof Array){for(var f=[],h=0;h"),e={position:"absolute",top:0,left:0};return d.css(a.extend({},b.css,e,c)),d},j=function(b,c){var d=a("
"),e={position:"absolute",width:b.width,height:b.height,top:c.y*(b.height+b.margin.top+b.margin.bottom),left:c.x*(b.width+b.margin.left+b.margin.right)};return d.css(a.extend(b.css,e)).attr({"class":"loading-pin"}),d},k=function(a){for(var b=[],c=0;c<=a.matrix.x;c++){b[c]||(b[c]=[]);for(var d=0;d<=a.matrix.y;d++)b[c][d]=j(a.pin,{x:c,y:d})}return b},l=function(b,c,d){var e=a("
");e.css({position:"absolute",left:(c.width-b.width)/2,top:(c.height-b.height)/2,width:b.width,height:b.height});for(var f=0;f=100?void d.call(this):void("number"==typeof this.runtime.interval&&this.runtime.interval!=this.actualInterval&&(this.pause(),this.resume(this.runtime.interval)))},d=function(){clearInterval(this.intervalId),this.background.remove(),this.target.removeData("loading")};return{constructor:b,update:function(b){b||(b={}),a.extend(!0,this.runtime,b)},show:function(){this.background.append(this.spinner).appendTo(document.body)},start:function(a){this.actualInterval=a||this.options.spinner.interval,this.actualInterval>2147483647&&(this.actualInterval=2147483647);var b=this,d={x:this.options.spinner.matrix.x,y:this.options.spinner.matrix.y},e=Math.round(this.actualInterval/this.effect.count);this.intervalId=setInterval(function(){b.algorithmData=b.algorithm(d,b.algorithmData),b.effect(b.pins[b.algorithmData.x][b.algorithmData.y],e,b.runtime),b.counter++,c.call(b)},this.actualInterval)},pause:function(){clearInterval(this.intervalId)},resume:function(a){this.start(a)}}}(),b.algorithm={},b.effect={},a.fn.loading=function(a){var c;this.data("loading")?(c=this.data("loading"),c.update(a)):(c=new b(this,a),this.data({loading:c}),c.show(),c.start())},a.fn.loading.algorithm=function(a,c,d){b.algorithm[a]=c,d&&(b.algorithm[a].options=d)},a.fn.loading.effect=function(a,c,d){b.effect[a]=c,d&&(b.effect[a].options=d)},b}(jQuery),function(a){"use strict";a.fn.loading.defaults={algorithm:{name:"snake",options:{reverse:!1}},effect:["simple"],spinner:{width:"50%",height:"30%",matrix:{x:null,y:null},pin:{width:5,height:5,margin:{top:1,right:1,bottom:0,left:0},css:{background:"green",opacity:0}},interval:100},background:{css:{opacity:.8,"z-index":9999,overflow:"hidden"}}}}(jQuery),function(a){"use strict";a.fn.loading.algorithm("linear",function(){})}.call(this,jQuery),function(a){"use strict";a.fn.loading.algorithm("random",function(){})}.call(this,jQuery),function(a){"use strict";var b={reverse:!0};a.fn.loading.algorithm("snake",function(){function a(b,c){if(!c)return c=j(b),c.path++,c;if(c.path==c.fullPath){if(!g(c,c.reversed))return a.options.reverse?(i(c),c.path=0):c=j(b),c.path++,c;c.path=0,c.fullPath=h(c)}var d=f(c);if(d)return c.x=d.x,c.y=d.y,c.axis=d.axis,c.sign=d.sign,c.path++,c;throw new Error("Cant resolve path")}var b=function(a){return"x"==a?"y":"x"},c=function(a,b,c){var d=!0;return d=d&&c.matrix.x[0]<=a&&a<=c.matrix.x[1],d=d&&c.matrix.y[0]<=b&&b<=c.matrix.y[1]},d=function(a,c,d,e){this.x=a.x,this.y=a.y,this.axis=c?b(a.axis):a.axis,this.sign=d?-1*a.sign:a.sign,e||(this[this.axis]+=this.sign)},e=[function(a){var b=new d(a,!1,!1);return c(b.x,b.y,a)?b:!1},function(a){var b=new d(a,!0,!0);return c(b.x,b.y,a)?b:!1},function(a){var b=new d(a,!0,!1);return c(b.x,b.y,a)?b:!1},function(a){var b=new d(a,!1,!0,!0);return c(b.x,b.y,a)?b:!1}],f=function(a){for(var b,c=0;c