├── .gitignore ├── .jscsrc ├── .jshintrc ├── .travis.yml ├── LICENSE ├── README.md ├── bower.json ├── gulpfile.js ├── package.json ├── queryloader2.min.js ├── src ├── ImagePreloader │ ├── Image.js │ ├── ImageLoaded.js │ └── index.js ├── Overlay │ ├── LoadingBar.js │ ├── Percentage.js │ ├── PercentageParser.js │ └── index.js ├── Polyfills │ └── index.js ├── QueryLoader │ ├── TempOverlay.js │ └── index.js └── index.js └── test ├── browser ├── css │ └── style.css ├── images │ ├── 1.jpg │ ├── 2.jpg │ ├── 3.jpg │ ├── 4.jpg │ ├── Dali_Swans_Reflecting_Elephants.jpg │ ├── LittleSnowHills.jpg │ ├── hokusai_1680_1050.jpg │ └── johnbaizley_Tat.jpg ├── index.html ├── jquery-test.html └── js │ └── script.js └── tests.js /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules/ 3 | build/ 4 | dist/ 5 | .idea/ -------------------------------------------------------------------------------- /.jscsrc: -------------------------------------------------------------------------------- 1 | { 2 | "esnext": true, 3 | "disallowSpacesInNamedFunctionExpression": { 4 | "beforeOpeningRoundBrace": true 5 | }, 6 | "disallowSpacesInFunctionExpression": { 7 | "beforeOpeningRoundBrace": true 8 | }, 9 | "disallowSpacesInAnonymousFunctionExpression": { 10 | "beforeOpeningRoundBrace": true 11 | }, 12 | "disallowSpacesInFunctionDeclaration": { 13 | "beforeOpeningRoundBrace": true 14 | }, 15 | "disallowEmptyBlocks": true, 16 | "disallowSpacesInCallExpression": true, 17 | "disallowSpacesInsideArrayBrackets": true, 18 | "disallowSpacesInsideParentheses": true, 19 | "disallowQuotedKeysInObjects": true, 20 | "disallowSpaceAfterObjectKeys": true, 21 | "disallowSpaceAfterPrefixUnaryOperators": true, 22 | "disallowSpaceBeforePostfixUnaryOperators": true, 23 | "disallowSpaceBeforeBinaryOperators": [ 24 | "," 25 | ], 26 | "disallowMixedSpacesAndTabs": true, 27 | "disallowTrailingWhitespace": true, 28 | "requireTrailingComma": { "ignoreSingleLine": true }, 29 | "disallowSpaceBeforeComma": true, 30 | "requireSpaceAfterComma": true, 31 | "disallowYodaConditions": true, 32 | "disallowKeywords": [ "with" ], 33 | "disallowKeywordsOnNewLine": ["else"], 34 | "disallowMultipleLineBreaks": true, 35 | "disallowMultipleLineStrings": true, 36 | "disallowMultipleVarDecl": true, 37 | "disallowSpaceBeforeSemicolon": true, 38 | "requireSpaceBeforeBlockStatements": true, 39 | "requireParenthesesAroundIIFE": true, 40 | "requireSpacesInConditionalExpression": true, 41 | "requireBlocksOnNewline": 1, 42 | "requireCommaBeforeLineBreak": true, 43 | "requireSpaceBeforeBinaryOperators": true, 44 | "requireSpaceAfterBinaryOperators": true, 45 | "requireCamelCaseOrUpperCaseIdentifiers": true, 46 | "requireLineFeedAtFileEnd": true, 47 | "requireCapitalizedConstructors": true, 48 | "requireDotNotation": true, 49 | "requireSpacesInForStatement": true, 50 | "requireSpaceBetweenArguments": true, 51 | "requireCurlyBraces": [ 52 | "do" 53 | ], 54 | "requireSpaceAfterKeywords": [ 55 | "if", 56 | "else", 57 | "for", 58 | "while", 59 | "do", 60 | "switch", 61 | "case", 62 | "return", 63 | "try", 64 | "catch", 65 | "typeof" 66 | ], 67 | "requirePaddingNewLinesBeforeLineComments": { 68 | "allExcept": "firstAfterCurly" 69 | }, 70 | "requirePaddingNewLinesAfterBlocks": true, 71 | "requireSemicolons": true, 72 | "safeContextKeyword": "_this", 73 | "validateLineBreaks": "LF", 74 | "validateQuoteMarks": "'", 75 | "validateIndentation": 2 76 | } -------------------------------------------------------------------------------- /.jshintrc: -------------------------------------------------------------------------------- 1 | { 2 | "bitwise" : true, 3 | "curly" : true, 4 | "eqeqeq" : true, 5 | "forin" : true, 6 | "immed" : true, 7 | "latedef" : "nofunc", 8 | "maxparams" : 4, 9 | "newcap" : false, 10 | "noarg" : true, 11 | "noempty" : true, 12 | "nonew" : true, 13 | "undef" : true, 14 | "unused" : true, 15 | "node" : true, 16 | "browser" : true, 17 | "jquery" : true, 18 | "globals" : { 19 | "define" : false 20 | } 21 | } -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | node_js: 3 | - "node" 4 | - "0.12" 5 | - "0.11" 6 | notifications: 7 | email: false 8 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2014 Gaya Kessler 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | QueryLoader2 2 | ============== 3 | QueryLoader2 serves the main purpose of pre-loading the images on your website by showing an overlay and a loading bar. It automatically fetches all your images and background images and pre-loads them before showing the web page. 4 | 5 | [![Code Climate](https://codeclimate.com/github/Gaya/QueryLoader2/badges/gpa.svg)](https://codeclimate.com/github/Gaya/QueryLoader2) 6 | [![Build Status](https://travis-ci.org/Gaya/queryloader2.svg?branch=master)](https://travis-ci.org/Gaya/queryloader2) 7 | 8 | Compatibility 9 | ------------- 10 | QueryLoader currently works in IE version 9+, Chrome, Safari and Firefox. 11 | 12 | **No dependencies**, so **no** jQuery / Zepto / MooTools required. 13 | 14 | Read the full post here: [http://blog.gaya.ninja/articles/queryloader2-preload-your-images-with-ease/](http://blog.gaya.ninja/articles/queryloader2-preload-your-images-with-ease/) 15 | 16 | [View example of how QueryLoader2 works](https://gaya.github.io/scripts/queryLoader2/). 17 | 18 | Example usage 19 | ------------- 20 | Include the `queryloader2.min.js` script (which is in the root of this repository) in the head section of your webpage. 21 | 22 | 23 | 24 | Create a QueryLoader2 object like this for example: 25 | 26 | 38 | 39 | Use with NPM / Browserify 40 | ------------------------- 41 | First install QueryLoader as a dependency in your project: 42 | 43 | npm install queryloader2 --save-dev 44 | 45 | Use it in a node / browserify project: 46 | 47 | var QueryLoader2 = require("queryloader2"); 48 | 49 | var loader = QueryLoader2(document.querySelector("body"), { 50 | barColor: "#efefef", 51 | backgroundColor: "#111", 52 | percentage: true, 53 | barHeight: 1, 54 | minimumTime: 200, 55 | fadeOutTime: 1000 56 | }); 57 | 58 | jQuery usage 59 | ------------ 60 | Include jQuery and `queryloader2.min.js` scripts in the header. 61 | 62 | 63 | 64 | 65 | Call QueryLoader in `$(document).ready()` like this: 66 | 67 | $(document).ready(function () { 68 | $("body").queryLoader2(); 69 | }); 70 | 71 | Install using Bower 72 | ------------------- 73 | 74 | bower install queryloader2 75 | 76 | Basic usage 77 | ----------- 78 | 79 | QueryLoader2(element, options); 80 | 81 | Options 82 | ------- 83 | 84 | **backgroundColor** 85 | `string` background color of the loader (in hex). 86 | Default: "#000" 87 | 88 | **barColor** 89 | `string` background color of the bar (in hex). 90 | Default: "#FFF" 91 | 92 | **barHeight** 93 | `int` height of the bar in pixels. 94 | Default: 1 95 | 96 | **minimumTime** 97 | `int` time in miliseconds which the loading has to run. If time has not passed the animation will still show. 98 | Default: 500 99 | 100 | **maxTime** 101 | `int` maximum time in milliseconds the loader may take. Go past this time and the loader with automatically close. 102 | Default: 10000 103 | 104 | **fadeOutTime** 105 | `int` time in miliseconds it takes for the overlay to fade out at the end. 106 | Default: 1000 107 | 108 | **deepSearch** 109 | `boolean` set to true to find ALL images with the selected elements. If you don't want queryLoader to look in the children, set to false. 110 | Default: true 111 | 112 | **percentage** 113 | `boolean` Set to true to enable percentage visualising. 114 | Default: false 115 | 116 | **onComplete** 117 | `function` this function is called once the loading and animation are completed. 118 | Default: none 119 | 120 | **onProgress** 121 | `function` this function is called when an image is loaded. Get parameters `percentage`, `imagesLoaded`, `totalImages`. 122 | Default: none 123 | -------------------------------------------------------------------------------- /bower.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "QueryLoader2", 3 | "version": "3.1.0", 4 | "homepage": "http://www.gayadesign.com/diy/queryloader2-preload-your-images-with-ease/", 5 | "authors": [ 6 | "Gaya " 7 | ], 8 | "description": "A simple script to create a preloader for images", 9 | "main": "queryloader2.min.js", 10 | "keywords": [ 11 | "preloader", 12 | "queryloader", 13 | "gayadesign" 14 | ], 15 | "license": "MIT" 16 | } 17 | -------------------------------------------------------------------------------- /gulpfile.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | var gulp = require('gulp'); 3 | var browserify = require('browserify'); 4 | var source = require('vinyl-source-stream'); 5 | var mochaPhantomJS = require('gulp-mocha-phantomjs'); 6 | var browserSync = require('browser-sync'); 7 | var uglify = require('gulp-uglify'); 8 | var rename = require('gulp-rename'); 9 | var header = require('gulp-header'); 10 | 11 | var config = { 12 | src: 'src', 13 | dist: 'dist', 14 | build: '', 15 | test: 'test', 16 | }; 17 | var pkg = require('./package.json'); 18 | 19 | gulp.task('browserify', function() { 20 | return browserify('./' + config.src + '/index.js') 21 | .bundle() 22 | .on('error', function(err) { 23 | console.log(err.toString()); 24 | this.emit('end'); 25 | }) 26 | .pipe(source(pkg.name + '.js')) 27 | .pipe(gulp.dest(config.dist)) 28 | .pipe(browserSync.reload({stream:true})); 29 | }); 30 | 31 | gulp.task('browserify-tests', function() { 32 | return browserify('./' + config.test + '/tests.js') 33 | .bundle() 34 | .on('error', function(err) { 35 | console.log(err.toString()); 36 | this.emit('end'); 37 | }) 38 | .pipe(source(pkg.name + '-tests.js')) 39 | .pipe(gulp.dest(config.dist)) 40 | .pipe(browserSync.reload({stream:true})); 41 | }); 42 | 43 | gulp.task('browser-sync', function() { 44 | browserSync({ 45 | server: { 46 | baseDir: ['./' + config.test + '/browser/', './'], 47 | }, 48 | }); 49 | }); 50 | 51 | gulp.task('serve-test', ['browserify', 'browserify-tests'], function() { 52 | gulp.start('browser-sync'); 53 | gulp.watch(config.test + '/*.js', ['browserify', 'browserify-tests']); 54 | gulp.watch(config.src + '/**/*.js', ['browserify', 'browserify-tests']); 55 | }); 56 | 57 | gulp.task('build', ['browserify'], function() { 58 | var headerText = 59 | '/*\n' + 60 | ' * QueryLoader2 - A simple script to create a preloader for images\n' + 61 | ' *\n' + 62 | ' * For instructions read the original post:\n' + 63 | ' * http://www.gayadesign.com/diy/queryloader2-preload-your-images-with-ease/\n' + 64 | ' *\n' + 65 | ' * Copyright (c) 2011 - Gaya Kessler\n' + 66 | ' *\n' + 67 | ' * Licensed under the MIT license:\n' + 68 | ' * http://www.opensource.org/licenses/mit-license.php\n' + 69 | ' *\n' + 70 | ' * Version: <%= version %>\n' + 71 | ' * Last update: <%= date %>\n' + 72 | ' */\n'; 73 | 74 | gulp.src(config.dist + '/' + pkg.name + '.js') 75 | .pipe(uglify()) 76 | .pipe(rename(pkg.name + '.min.js')) 77 | .pipe(header(headerText, { 78 | version: pkg.version, 79 | date: new Date().toJSON().slice(0, 10), 80 | })) 81 | .pipe(gulp.dest(config.build)); 82 | }); -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "queryloader2", 3 | "version": "3.2.3", 4 | "homepage": "http://gaya.ninja", 5 | "description": "QueryLoader2 serves the main purpose of preloading the images on your website by showing an overlay and a loading bar. It automatically fetches all your images and background images and preloads them before showing the webpage.", 6 | "dependencies": { 7 | "browser-sync": "^2.9.11", 8 | "browserify": "^11.2.0", 9 | "gulp": "^3.9.0", 10 | "gulp-header": "^1.7.1", 11 | "gulp-mocha-phantomjs": "^0.10.1", 12 | "gulp-rename": "^1.2.2", 13 | "gulp-uglify": "^1.4.2", 14 | "gulp-watch": "^4.3.5", 15 | "jscs": "^2.3.1", 16 | "mocha": "^2.3.3", 17 | "mocha-phantomjs": "^4.0.1", 18 | "vinyl-source-stream": "^1.1.0" 19 | }, 20 | "repository": { 21 | "type": "git", 22 | "url": "https://github.com/Gaya/QueryLoader2" 23 | }, 24 | "scripts": { 25 | "prepublish": "node ./node_modules/gulp/bin/gulp.js browserify && node ./node_modules/gulp/bin/gulp.js browserify-tests", 26 | "test": "node ./node_modules/jscs/bin/jscs src && node ./node_modules/gulp/bin/gulp.js browserify && node ./node_modules/gulp/bin/gulp.js browserify-tests && node ./node_modules/mocha-phantomjs/bin/mocha-phantomjs test/browser/index.html" 27 | }, 28 | "main": "./queryloader2.min.js", 29 | "author": { 30 | "name": "Gaya Kessler", 31 | "email": "hi@gaya.ninja", 32 | "url": "http://gaya.ninja/" 33 | }, 34 | "license": "MIT", 35 | "devDependencies": {} 36 | } 37 | -------------------------------------------------------------------------------- /queryloader2.min.js: -------------------------------------------------------------------------------- 1 | /* 2 | * QueryLoader2 - A simple script to create a preloader for images 3 | * 4 | * For instructions read the original post: 5 | * http://www.gayadesign.com/diy/queryloader2-preload-your-images-with-ease/ 6 | * 7 | * Copyright (c) 2011 - Gaya Kessler 8 | * 9 | * Licensed under the MIT license: 10 | * http://www.opensource.org/licenses/mit-license.php 11 | * 12 | * Version: 3.2.2 13 | * Last update: 2016-06-28 14 | */ 15 | !function e(t,n,i){function r(s,a){if(!n[s]){if(!t[s]){var l="function"==typeof require&&require;if(!a&&l)return l(s,!0);if(o)return o(s,!0);var u=new Error("Cannot find module '"+s+"'");throw u.code="MODULE_NOT_FOUND",u}var c=n[s]={exports:{}};t[s][0].call(c.exports,function(e){var n=t[s][1][e];return r(n?n:e)},c,c.exports,e,t,n,i)}return n[s].exports}for(var o="function"==typeof require&&require,s=0;s0&&!e.match(/^(data:)/i)},urlIsNew:function(e){return-1===this.sources.indexOf(e)},isIE:function(){return navigator.userAgent.match(/msie/i)},isOpera:function(){return navigator.userAgent.match(/Opera/i)}};t.exports=function(e){var t=Object.create(r);return t.parent=e,t.sources=[],t.images=[],t.loaded=0,t.deepSearch=!0,t}},{"./Image.js":1}],4:[function(e,t,n){"use strict";var i=e("./PercentageParser"),r={create:function(){this.element=document.createElement("div"),this.element.setAttribute("class",this.className),this.setStyling(),this.updateProgress(0,0)},setStyling:function(){this.element.style.height=this.barHeight+"px",this.element.style.marginTop="-"+this.barHeight/2+"px",this.element.style.backgroundColor=this.barColor,this.element.style.position="absolute",this.element.style.top="50%",this.setTransitionTime(100)},updateProgress:function(e,t){0!==t&&this.setTransitionTime(t),e=i(e),this.element.style.width=e+"%"},setTransitionTime:function(e){this.element.style.WebkitTransition="width "+e+"ms",this.element.style.MozTransition="width "+e+"ms",this.element.style.OTransition="width "+e+"ms",this.element.style.MsTransition="width "+e+"ms",this.element.style.Transition="width "+e+"ms"}};t.exports=function(){var e=Object.create(r);return e.element=null,e.className="queryloader__overlay__bar",e.barHeight=1,e.barColor="#fff",e}},{"./PercentageParser":6}],5:[function(e,t,n){"use strict";var i=e("./PercentageParser"),r={create:function(){this.element=document.createElement("div"),this.element.setAttribute("class",this.className),this.element.setAttribute("id",this.idName),this.applyStyling(),this.updateProgress(0,0)},applyStyling:function(){this.element.style.height="40px",this.element.style.width="100%",this.element.style.position="absolute",this.element.style.fontSize="3em",this.element.style.top="50%",this.element.style.left="0",this.element.style.marginTop="-"+(59+this.barHeight)+"px",this.element.style.textAlign="center",this.element.style.color=this.barColor},updateProgress:function(e,t){e=i(e),this.element.innerHTML=e+"%"}};t.exports=function(){var e=Object.create(r);return e.element=null,e.idName="qlPercentage",e.className="queryloader__overlay__percentage",e.barHeight=1,e.barColor="#fff",e}},{"./PercentageParser":6}],6:[function(e,t,n){"use strict";function i(e){return parseInt(e)<0?0:parseInt(e)>100?100:parseInt(e)}t.exports=i},{}],7:[function(e,t,n){"use strict";var i=e("./LoadingBar"),r=e("./Percentage"),o={init:function(){this.create(),this.loadingBar=i(),this.loadingBar.barHeight=this.barHeight,this.loadingBar.barColor=this.barColor,this.loadingBar.create(),this.element.appendChild(this.loadingBar.element),this.showPercentage&&(this.percentage=r(),this.percentage.barColor=this.barColor,this.percentage.idName=this.percentageId,this.percentage.create(),this.element.appendChild(this.percentage.element)),this.parentElement.appendChild(this.element)},create:function(){this.element=document.querySelector("#"+this.idName)||document.createElement("div"),this.element.setAttribute("class",this.className),this.element.setAttribute("id",this.idName),this.applyStyling()},applyStyling:function(){this.element.style.position=this.calculatePosition(),this.element.style.width="100%",this.element.style.height="100%",this.element.style.backgroundColor=this.backgroundColor,this.element.style.backgroundPosition="fixed",this.element.style.zIndex=666999,this.element.style.top="0",this.element.style.left="0",this.element.style.WebkitTransition="opacity "+this.fadeOutTime+"ms",this.element.style.MozTransition="opacity "+this.fadeOutTime+"ms",this.element.style.OTransition="opacity "+this.fadeOutTime+"ms",this.element.style.MsTransition="opacity "+this.fadeOutTime+"ms",this.element.style.Transition="opacity "+this.fadeOutTime+"ms"},calculatePosition:function(){var e="absolute";return"body"===this.parentElement.tagName.toLowerCase()?e="fixed":"fixed"===this.parentElement.style.position&&"absolute"===this.parentElement.style.position||(this.parentElement.style.position="relative"),e},updateProgress:function(e,t){null!==this.loadingBar&&this.loadingBar.updateProgress(e,t),null!==this.percentage&&this.percentage.updateProgress(e,t)},remove:function(){this.canRemove(this.element)&&this.element.parentNode.removeChild(this.element)},canRemove:function(e){return e.parentNode&&"undefined"!=typeof e.parentNode.removeChild}};t.exports=function(e){var t=Object.create(o);return t.parentElement=e,t.idName="qLoverlay",t.percentageId="qlPercentage",t.className="queryloader__overlay",t.element=null,t.loadingBar=null,t.percentage=null,t.barColor="#ff0000",t.backgroundColor="#000",t.barHeight=1,t.fadeOutTime=300,t.showPercentage=!1,t}},{"./LoadingBar":4,"./Percentage":5}],8:[function(e,t,n){Function.prototype.bind||(Function.prototype.bind=function(e){"use strict";if("function"!=typeof this)throw new TypeError("Function.prototype.bind - what is trying to be bound is not callable");var t=Array.prototype.slice.call(arguments,1),n=this,i=function(){},r=function(){return n.apply(this instanceof i&&e?this:e,t.concat(Array.prototype.slice.call(arguments)))};return i.prototype=this.prototype,r.prototype=new i,r}),"function"!=typeof Object.create&&(Object.create=function(){function e(){}var t=Object.prototype.hasOwnProperty;return function(n){if("object"!=typeof n)throw TypeError("Object prototype may only be an Object or null");e.prototype=n;var i=new e;if(e.prototype=null,arguments.length>1){var r=Object(arguments[1]);for(var o in r)t.call(r,o)&&(i[o]=r[o])}return i}}())},{}],9:[function(e,t,n){"use strict";t.exports=function(){var e=window.setInterval(function(){if("undefined"!=typeof document.getElementsByTagName("body")[0]){var t=document.createElement("div");t.style.position="fixed",t.style.width="100%",t.style.height="100%",t.style.zIndex="9999",t.style.backgroundColor="#000",t.style.left="0",t.style.top="0",t.setAttribute("id","qLtempOverlay"),document.getElementsByTagName("body")[0].appendChild(t),window.clearInterval(e)}},1)}},{}],10:[function(e,t,n){"use strict";var i=e("./../ImagePreloader"),r=e("./../Overlay"),o={init:function(e,t){this.options=this.extend(t,e),"undefined"!=typeof this.element&&(this.createOverlay(),this.removeTempOverlay(),this.createPreloader(),this.startMaxTimeout())},extend:function(e,t){"undefined"==typeof e&&(e={});for(var n in t)t.hasOwnProperty(n)&&(e[n]=t[n]);return e},startMaxTimeout:function(){this.maxTimeout=window.setTimeout(this.doneLoading.bind(this),this.options.maxTime)},createOverlay:function(){this.overlay=r(this.element),this.overlay.idName=this.options.overlayId,this.overlay.percentageId=this.options.percentageId,this.overlay.backgroundColor=this.options.backgroundColor,this.overlay.barHeight=this.options.barHeight,this.overlay.barColor=this.options.barColor,this.overlay.showPercentage=this.options.percentage,this.overlay.fadeOutTime=this.options.fadeOutTime,"undefined"!=typeof this.element&&this.overlay.init()},removeTempOverlay:function(){window.setTimeout(function(){var e=document.getElementById("qLtempOverlay");e&&e.parentNode&&e.parentNode.removeChild(e)},0)},createPreloader:function(){this.preloader=i(this),this.preloader.deepSearch=this.options.deepSearch,window.setTimeout(function(){this.preloader.findAndPreload(this.element)}.bind(this),100)},updateProgress:function(e,t){var n=e/t*100;this.overlay.updateProgress(n,this.options.minimumTime),"function"==typeof this.options.onProgress&&this.options.onProgress(n,e,t),e===t&&this.done===!1&&(window.clearTimeout(this.maxTimeout),window.setTimeout(this.doneLoading.bind(this),this.options.minimumTime))},doneLoading:function(){window.clearTimeout(this.maxTimeout),this.done=!0,this.overlay.element.style.opacity=0,window.setTimeout(this.destroy.bind(this),this.options.fadeOutTime)},destroy:function(){this.overlay.remove(),this.options.onComplete()}};t.exports=function(e,t){var n=Object.create(o);if(n.element=e,n.options={},n.done=!1,n.maxTimeout=null,n.overlay=null,n.preloader=null,null!==e){var i=function(){};n.init(t,{onComplete:i,onProgress:i,backgroundColor:"#000",barColor:"#fff",overlayId:"qLoverlay",percentageId:"qLpercentage",barHeight:1,percentage:!1,deepSearch:!0,minimumTime:300,maxTime:1e4,fadeOutTime:1e3})}return n}},{"./../ImagePreloader":3,"./../Overlay":7}],11:[function(e,t,n){e("./Polyfills");var i=e("./QueryLoader"),r=e("./QueryLoader/TempOverlay");(window.jQuery||window.Zepto)&&!function(e){"use strict";e.fn.queryLoader2=function(e){return this.each(function(){i(this,e)})}}(window.jQuery||window.Zepto),"undefined"!=typeof t&&(t.exports=i),"function"==typeof define&&define.amd&&define([],function(){"use strict";return i}),window.QueryLoader2=i,r()},{"./Polyfills":8,"./QueryLoader":10,"./QueryLoader/TempOverlay":9}]},{},[11]); -------------------------------------------------------------------------------- /src/ImagePreloader/Image.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | var ImageLoaded = require('./ImageLoaded.js'); 3 | 4 | var QueryLoaderImage = { 5 | create: function() { 6 | this.element = document.createElement('img'); 7 | this.element.setAttribute('src', this.src); 8 | }, 9 | 10 | preload: function(cb) { 11 | ImageLoaded(this.element, function(err, alreadyLoaded) { 12 | cb(err, alreadyLoaded); 13 | }); 14 | }, 15 | }; 16 | 17 | module.exports = function(src) { 18 | var image = Object.create(QueryLoaderImage); 19 | 20 | image.src = src; 21 | image.element = null; 22 | 23 | if (typeof src !== 'undefined') { 24 | image.create(); 25 | } 26 | 27 | return image; 28 | }; 29 | -------------------------------------------------------------------------------- /src/ImagePreloader/ImageLoaded.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Modified version of http://github.com/desandro/imagesloaded v2.1.1 3 | * MIT License. by Paul Irish et al. 4 | */ 5 | 6 | 'use strict'; 7 | var BLANK = 'data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///ywAAAAAAQABAAACAUwAOw=='; 8 | 9 | function loaded(image, callback) { 10 | var src; 11 | 12 | if (!image.nodeName) { 13 | return callback(new Error('First argument must be an image element')); 14 | } 15 | 16 | if (image.nodeName.toLowerCase() !== 'img') { 17 | return callback(new Error('Element supplied is not an image')); 18 | } 19 | 20 | if (image.src && image.complete && image.naturalWidth !== undefined) { 21 | return callback(null, true); 22 | } 23 | 24 | function bindEvent(element, event, attach, cb) { 25 | if (!element.addEventListener) { 26 | element[(attach ? 'attachEvent' : 'detachEvent')]('on' + event, cb); 27 | } else { 28 | element[(attach ? 'addEventListener' : 'removeEventListener')](event, cb); 29 | } 30 | } 31 | 32 | function onload() { 33 | bindEvent(image, 'load', false, onload); 34 | bindEvent(image, 'error', false, onload); 35 | 36 | callback(null, false); 37 | } 38 | 39 | bindEvent(image, 'load', true, onload); 40 | bindEvent(image, 'error', true, onload); 41 | 42 | if (image.readyState || image.complete) { 43 | src = image.src; 44 | image.src = BLANK; 45 | image.src = src; 46 | } 47 | } 48 | 49 | module.exports = loaded; 50 | -------------------------------------------------------------------------------- /src/ImagePreloader/index.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | var QueryLoaderImage = require('./Image.js'); 3 | 4 | var ImagePreloader = { 5 | getImageSrcs: function(element) { 6 | this.sources = []; 7 | 8 | if (typeof element !== 'undefined') { 9 | this.findImageInElement(element); 10 | 11 | if (this.deepSearch === true) { 12 | var elements = element.querySelectorAll('*'); 13 | for (var i = 0; i < elements.length; i++) { 14 | if (elements[i].tagName !== 'SCRIPT') { 15 | this.findImageInElement(elements[i]); 16 | } 17 | } 18 | } 19 | } 20 | 21 | // if there's no img or bg-img, use a 1px transparent data uri as a fallback, 22 | // otherwise the user will be blocked for 10s 23 | if (!this.sources.length) { 24 | this.sources.push('data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7'); 25 | } 26 | 27 | return this.sources; 28 | }, 29 | 30 | findAndPreload: function(element) { 31 | if (typeof element === 'undefined') { 32 | return; 33 | } 34 | 35 | this.sources = this.getImageSrcs(element); 36 | 37 | for (var i = 0; i < this.sources.length; i++) { 38 | var image = QueryLoaderImage(this.sources[i]); 39 | image.preload(this.imageLoaded.bind(this)); 40 | this.images.push(image); 41 | } 42 | }, 43 | 44 | imageLoaded: function() { 45 | this.loaded++; 46 | 47 | this.updateProgress(); 48 | }, 49 | 50 | updateProgress: function() { 51 | this.parent.updateProgress(this.loaded, this.sources.length); 52 | }, 53 | 54 | findImageInElement: function(element) { 55 | var urlType = this.determineUrlAndType(element); 56 | 57 | //skip if gradient 58 | if (!this.hasGradient(urlType.url)) { 59 | //remove unwanted chars 60 | urlType.url = this.stripUrl(urlType.url); 61 | 62 | //split urls 63 | var urls = urlType.url.split(', '); 64 | 65 | for (var i = 0; i < urls.length; i++) { 66 | if (this.validUrl(urls[i]) && this.urlIsNew(urls[i])) { 67 | var extra = ''; 68 | 69 | if (this.isIE() || this.isOpera()) { 70 | //filthy always no cache for IE, sorry peeps! 71 | extra = '?rand=' + Math.random(); 72 | } 73 | 74 | //add image to found list 75 | this.sources.push(urls[i] + extra); 76 | } 77 | } 78 | } 79 | }, 80 | 81 | determineUrlAndType: function(element) { 82 | var url = ''; 83 | var type = 'normal'; 84 | var style = element.currentStyle || window.getComputedStyle(element, null); 85 | var blacklisted = ['', 'none', 'initial', 'inherit']; 86 | 87 | if (typeof style.backgroundImage !== 'undefined' && blacklisted.indexOf(style.backgroundImage) === -1) { 88 | //if object has background image (computed style) 89 | url = style.backgroundImage; 90 | type = 'background'; 91 | } else if (typeof element.style.backgroundImage !== 'undefined' && blacklisted.indexOf(element.style.backgroundImage) === -1) { 92 | //if object has background image (inline style) 93 | url = element.style.backgroundImage; 94 | type = 'background'; 95 | } else if (element.nodeName.toLowerCase() === 'img') { 96 | //if is img and has src 97 | url = element.src; 98 | } 99 | 100 | return { 101 | url: url, 102 | type: type, 103 | }; 104 | }, 105 | 106 | hasGradient: function(url) { 107 | return (url && typeof url.indexOf !== 'undefined' ? url.indexOf('gradient(') !== -1 : false); 108 | }, 109 | 110 | stripUrl: function(url) { 111 | url = url.replace(/url\(\'/g, ''); 112 | url = url.replace(/url\(/g, ''); 113 | url = url.replace(/\'\)/g, ''); 114 | url = url.replace(/\)/g, ''); 115 | url = url.replace(/"/g, ''); 116 | 117 | return url; 118 | }, 119 | 120 | validUrl: function(url) { 121 | if (url.length > 0 && !url.match(/^(data:)/i)) { 122 | return true; 123 | } else { 124 | return false; 125 | } 126 | }, 127 | 128 | urlIsNew: function(url) { 129 | return this.sources.indexOf(url) === -1; 130 | }, 131 | 132 | isIE: function() { 133 | return navigator.userAgent.match(/msie/i); 134 | }, 135 | 136 | isOpera: function() { 137 | return navigator.userAgent.match(/Opera/i); 138 | }, 139 | }; 140 | 141 | module.exports = function(parent) { 142 | var imagePreloader = Object.create(ImagePreloader); 143 | 144 | imagePreloader.parent = parent; 145 | imagePreloader.sources = []; 146 | imagePreloader.images = []; 147 | imagePreloader.loaded = 0; 148 | imagePreloader.deepSearch = true; 149 | 150 | return imagePreloader; 151 | }; 152 | -------------------------------------------------------------------------------- /src/Overlay/LoadingBar.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | var PercentageParser = require('./PercentageParser'); 3 | 4 | var LoadingBar = { 5 | /** 6 | * Creates the element for the loading bar 7 | */ 8 | create: function() { 9 | this.element = document.createElement('div'); 10 | this.element.setAttribute('class', this.className); 11 | this.setStyling(); 12 | this.updateProgress(0, 0); 13 | }, 14 | 15 | setStyling: function() { 16 | this.element.style.height = this.barHeight + 'px'; 17 | this.element.style.marginTop = '-' + (this.barHeight / 2) + 'px'; 18 | this.element.style.backgroundColor = this.barColor; 19 | this.element.style.position = 'absolute'; 20 | this.element.style.top = '50%'; 21 | 22 | this.setTransitionTime(100); 23 | }, 24 | 25 | updateProgress: function(percentage, time) { 26 | if (time !== 0) { 27 | this.setTransitionTime(time); 28 | } 29 | 30 | percentage = PercentageParser(percentage); 31 | 32 | this.element.style.width = percentage + '%'; 33 | }, 34 | 35 | setTransitionTime: function(ms) { 36 | this.element.style.WebkitTransition = 'width ' + ms + 'ms'; 37 | this.element.style.MozTransition = 'width ' + ms + 'ms'; 38 | this.element.style.OTransition = 'width ' + ms + 'ms'; 39 | this.element.style.MsTransition = 'width ' + ms + 'ms'; 40 | this.element.style.Transition = 'width ' + ms + 'ms'; 41 | }, 42 | }; 43 | 44 | module.exports = function() { 45 | var loadingBar = Object.create(LoadingBar); 46 | 47 | loadingBar.element = null; 48 | loadingBar.className = 'queryloader__overlay__bar'; 49 | loadingBar.barHeight = 1; 50 | loadingBar.barColor = '#fff'; 51 | 52 | return loadingBar; 53 | }; 54 | -------------------------------------------------------------------------------- /src/Overlay/Percentage.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | var PercentageParser = require('./PercentageParser'); 3 | 4 | var Percentage = { 5 | create: function() { 6 | this.element = document.createElement('div'); 7 | this.element.setAttribute('class', this.className); 8 | this.element.setAttribute('id', this.idName); 9 | this.applyStyling(); 10 | this.updateProgress(0, 0); 11 | }, 12 | 13 | applyStyling: function() { 14 | this.element.style.height = '40px'; 15 | this.element.style.width = '100%'; 16 | this.element.style.position = 'absolute'; 17 | this.element.style.fontSize = '3em'; 18 | this.element.style.top = '50%'; 19 | this.element.style.left = '0'; 20 | this.element.style.marginTop = '-' + (59 + this.barHeight) + 'px'; 21 | this.element.style.textAlign = 'center'; 22 | this.element.style.color = this.barColor; 23 | }, 24 | 25 | updateProgress: function(percentage, time) { 26 | percentage = PercentageParser(percentage); 27 | 28 | this.element.innerHTML = percentage + '%'; 29 | }, 30 | }; 31 | 32 | module.exports = function() { 33 | var percentage = Object.create(Percentage); 34 | 35 | percentage.element = null; 36 | percentage.idName = 'qlPercentage'; 37 | percentage.className = 'queryloader__overlay__percentage'; 38 | percentage.barHeight = 1; 39 | percentage.barColor = '#fff'; 40 | 41 | return percentage; 42 | }; 43 | -------------------------------------------------------------------------------- /src/Overlay/PercentageParser.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | function parsePercentage(percentage) { 3 | if (parseInt(percentage) < 0) { 4 | return 0; 5 | } 6 | 7 | if (parseInt(percentage) > 100) { 8 | return 100; 9 | } 10 | 11 | return parseInt(percentage); 12 | } 13 | 14 | module.exports = parsePercentage; 15 | -------------------------------------------------------------------------------- /src/Overlay/index.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | var LoadingBar = require('./LoadingBar'); 3 | var Percentage = require('./Percentage'); 4 | 5 | var Overlay = { 6 | init: function() { 7 | this.create(); 8 | 9 | this.loadingBar = LoadingBar(); 10 | this.loadingBar.barHeight = this.barHeight; 11 | this.loadingBar.barColor = this.barColor; 12 | this.loadingBar.create(); 13 | this.element.appendChild(this.loadingBar.element); 14 | 15 | if (this.showPercentage) { 16 | this.percentage = Percentage(); 17 | this.percentage.barColor = this.barColor; 18 | this.percentage.idName = this.percentageId; 19 | this.percentage.create(); 20 | this.element.appendChild(this.percentage.element); 21 | } 22 | 23 | this.parentElement.appendChild(this.element); 24 | }, 25 | 26 | create: function() { 27 | this.element = (document.querySelector('#' + this.idName) || document.createElement('div')); 28 | this.element.setAttribute('class', this.className); 29 | this.element.setAttribute('id', this.idName); 30 | this.applyStyling(); 31 | }, 32 | 33 | applyStyling: function() { 34 | //determine postion of overlay and set parent position 35 | this.element.style.position = this.calculatePosition(); 36 | this.element.style.width = '100%'; 37 | this.element.style.height = '100%'; 38 | this.element.style.backgroundColor = this.backgroundColor; 39 | this.element.style.backgroundPosition = 'fixed'; 40 | this.element.style.zIndex = 666999; //very HIGH 41 | this.element.style.top = '0'; 42 | this.element.style.left = '0'; 43 | 44 | this.element.style.WebkitTransition = 'opacity ' + this.fadeOutTime + 'ms'; 45 | this.element.style.MozTransition = 'opacity ' + this.fadeOutTime + 'ms'; 46 | this.element.style.OTransition = 'opacity ' + this.fadeOutTime + 'ms'; 47 | this.element.style.MsTransition = 'opacity ' + this.fadeOutTime + 'ms'; 48 | this.element.style.Transition = 'opacity ' + this.fadeOutTime + 'ms'; 49 | }, 50 | 51 | calculatePosition: function() { 52 | var overlayPosition = 'absolute'; 53 | 54 | if (this.parentElement.tagName.toLowerCase() === 'body') { 55 | overlayPosition = 'fixed'; 56 | } else { 57 | if (this.parentElement.style.position !== 'fixed' || this.parentElement.style.position !== 'absolute') { 58 | this.parentElement.style.position = 'relative'; 59 | } 60 | } 61 | 62 | return overlayPosition; 63 | }, 64 | 65 | updateProgress: function(percentage, time) { 66 | if (this.loadingBar !== null) { 67 | this.loadingBar.updateProgress(percentage, time); 68 | } 69 | 70 | if (this.percentage !== null) { 71 | this.percentage.updateProgress(percentage, time); 72 | } 73 | }, 74 | 75 | remove: function() { 76 | if (this.canRemove(this.element)) { 77 | this.element.parentNode.removeChild(this.element); 78 | } 79 | }, 80 | 81 | canRemove: function(element) { 82 | return (element.parentNode && typeof element.parentNode.removeChild !== 'undefined'); 83 | }, 84 | }; 85 | 86 | module.exports = function(parentElement) { 87 | var overlay = Object.create(Overlay); 88 | 89 | overlay.parentElement = parentElement; 90 | overlay.idName = 'qLoverlay'; 91 | overlay.percentageId = 'qlPercentage'; 92 | overlay.className = 'queryloader__overlay'; 93 | overlay.element = null; 94 | overlay.loadingBar = null; 95 | overlay.percentage = null; 96 | overlay.barColor = '#ff0000'; 97 | overlay.backgroundColor = '#000'; 98 | overlay.barHeight = 1; 99 | overlay.fadeOutTime = 300; 100 | overlay.showPercentage = false; 101 | 102 | return overlay; 103 | }; 104 | -------------------------------------------------------------------------------- /src/Polyfills/index.js: -------------------------------------------------------------------------------- 1 | if (!Function.prototype.bind) { 2 | Function.prototype.bind = function(oThis) { 3 | 'use strict'; 4 | if (typeof this !== 'function') { 5 | // closest thing possible to the ECMAScript 5 6 | // internal IsCallable function 7 | throw new TypeError('Function.prototype.bind - what is trying to be bound is not callable'); 8 | } 9 | 10 | var aArgs = Array.prototype.slice.call(arguments, 1); 11 | var _this = this; 12 | var FNOP = function() {}; 13 | 14 | var fBound = function() { 15 | return _this.apply(this instanceof FNOP && oThis 16 | ? this 17 | : oThis, 18 | aArgs.concat(Array.prototype.slice.call(arguments))); 19 | }; 20 | 21 | FNOP.prototype = this.prototype; 22 | fBound.prototype = new FNOP(); 23 | 24 | return fBound; 25 | }; 26 | } 27 | 28 | if (typeof Object.create !== 'function') { 29 | // Production steps of ECMA-262, Edition 5, 15.2.3.5 30 | // Reference: http://es5.github.io/#x15.2.3.5 31 | Object.create = (function() { 32 | // To save on memory, use a shared constructor 33 | function Temp() {} 34 | 35 | // make a safe reference to Object.prototype.hasOwnProperty 36 | var hasOwn = Object.prototype.hasOwnProperty; 37 | 38 | return function(O) { 39 | // 1. If Type(O) is not Object or Null throw a TypeError exception. 40 | if (typeof O !== 'object') { 41 | throw TypeError('Object prototype may only be an Object or null'); 42 | } 43 | 44 | // 2. Let obj be the result of creating a new object as if by the 45 | // expression new Object() where Object is the standard built-in 46 | // constructor with that name 47 | // 3. Set the [[Prototype]] internal property of obj to O. 48 | Temp.prototype = O; 49 | var obj = new Temp(); 50 | Temp.prototype = null; // Let's not keep a stray reference to O... 51 | 52 | // 4. If the argument Properties is present and not undefined, add 53 | // own properties to obj as if by calling the standard built-in 54 | // function Object.defineProperties with arguments obj and 55 | // Properties. 56 | if (arguments.length > 1) { 57 | // Object.defineProperties does ToObject on its first argument. 58 | var Properties = Object(arguments[1]); 59 | for (var prop in Properties) { 60 | if (hasOwn.call(Properties, prop)) { 61 | obj[prop] = Properties[prop]; 62 | } 63 | } 64 | } 65 | 66 | // 5. Return obj 67 | return obj; 68 | }; 69 | })(); 70 | } 71 | -------------------------------------------------------------------------------- /src/QueryLoader/TempOverlay.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | module.exports = function() { 3 | var timeout = window.setInterval(function() { 4 | if (typeof document.getElementsByTagName('body')[0] !== 'undefined') { 5 | var tempOverlay = document.createElement('div'); 6 | tempOverlay.style.position = 'fixed'; 7 | tempOverlay.style.width = '100%'; 8 | tempOverlay.style.height = '100%'; 9 | tempOverlay.style.zIndex = '9999'; 10 | tempOverlay.style.backgroundColor = '#000'; 11 | tempOverlay.style.left = '0'; 12 | tempOverlay.style.top = '0'; 13 | tempOverlay.setAttribute('id', 'qLtempOverlay'); 14 | document.getElementsByTagName('body')[0].appendChild(tempOverlay); 15 | 16 | window.clearInterval(timeout); 17 | } 18 | }, 1); 19 | }; 20 | -------------------------------------------------------------------------------- /src/QueryLoader/index.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | var ImagePreloader = require('./../ImagePreloader'); 3 | var Overlay = require('./../Overlay'); 4 | 5 | var QueryLoader = { 6 | init: function(options, defaultOptions) { 7 | this.options = this.extend(defaultOptions, options); 8 | 9 | if (typeof this.element !== 'undefined') { 10 | this.createOverlay(); 11 | this.removeTempOverlay(); 12 | this.createPreloader(); 13 | this.startMaxTimeout(); 14 | } 15 | }, 16 | 17 | extend: function(base, adding) { 18 | if (typeof base === 'undefined') { 19 | base = {}; 20 | } 21 | 22 | for (var property in adding) { 23 | if (adding.hasOwnProperty(property)) { 24 | base[property] = adding[property]; 25 | } 26 | } 27 | 28 | return base; 29 | }, 30 | 31 | startMaxTimeout: function() { 32 | this.maxTimeout = window.setTimeout(this.doneLoading.bind(this), this.options.maxTime); 33 | }, 34 | 35 | createOverlay: function() { 36 | this.overlay = Overlay(this.element); 37 | this.overlay.idName = this.options.overlayId; 38 | this.overlay.percentageId = this.options.percentageId; 39 | this.overlay.backgroundColor = this.options.backgroundColor; 40 | this.overlay.barHeight = this.options.barHeight; 41 | this.overlay.barColor = this.options.barColor; 42 | this.overlay.showPercentage = this.options.percentage; 43 | this.overlay.fadeOutTime = this.options.fadeOutTime; 44 | 45 | if (typeof this.element !== 'undefined') { 46 | this.overlay.init(); 47 | } 48 | }, 49 | 50 | removeTempOverlay: function() { 51 | window.setTimeout(function() { 52 | var tempOverlay = document.getElementById('qLtempOverlay'); 53 | if (tempOverlay && tempOverlay.parentNode) { 54 | tempOverlay.parentNode.removeChild(tempOverlay); 55 | } 56 | }, 0); 57 | }, 58 | 59 | createPreloader: function() { 60 | this.preloader = ImagePreloader(this); 61 | this.preloader.deepSearch = this.options.deepSearch; 62 | 63 | window.setTimeout(function() { 64 | this.preloader.findAndPreload(this.element); 65 | }.bind(this), 100); 66 | }, 67 | 68 | updateProgress: function(done, total) { 69 | var percentage = ((done / total) * 100); 70 | this.overlay.updateProgress(percentage, this.options.minimumTime); 71 | 72 | if (typeof this.options.onProgress === 'function') { 73 | this.options.onProgress(percentage, done, total); 74 | } 75 | 76 | if (done === total && this.done === false) { 77 | window.clearTimeout(this.maxTimeout); 78 | window.setTimeout(this.doneLoading.bind(this), this.options.minimumTime); 79 | } 80 | }, 81 | 82 | doneLoading: function() { 83 | window.clearTimeout(this.maxTimeout); 84 | this.done = true; 85 | 86 | this.overlay.element.style.opacity = 0; 87 | 88 | window.setTimeout(this.destroy.bind(this), this.options.fadeOutTime); 89 | }, 90 | 91 | destroy: function() { 92 | this.overlay.remove(); 93 | 94 | this.options.onComplete(); 95 | }, 96 | }; 97 | 98 | module.exports = function(element, options) { 99 | var queryLoader = Object.create(QueryLoader); 100 | 101 | queryLoader.element = element; 102 | queryLoader.options = {}; 103 | queryLoader.done = false; 104 | queryLoader.maxTimeout = null; 105 | 106 | //children 107 | queryLoader.overlay = null; 108 | queryLoader.preloader = null; 109 | 110 | if (element !== null) { 111 | var voidFunc = function() {}; 112 | 113 | queryLoader.init(options, { 114 | onComplete: voidFunc, 115 | onProgress: voidFunc, 116 | backgroundColor: '#000', 117 | barColor: '#fff', 118 | overlayId: 'qLoverlay', 119 | percentageId: 'qLpercentage', 120 | barHeight: 1, 121 | percentage: false, 122 | deepSearch: true, 123 | minimumTime: 300, 124 | maxTime: 10000, 125 | fadeOutTime: 1000, 126 | }); 127 | } 128 | 129 | return queryLoader; 130 | }; 131 | -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | require('./Polyfills'); 2 | var QueryLoader2 = require('./QueryLoader'); 3 | var TempOverlay = require('./QueryLoader/TempOverlay'); 4 | 5 | //jquery and zepto 6 | if (window.jQuery || window.Zepto) { 7 | (function($) { 8 | 'use strict'; 9 | $.fn.queryLoader2 = function(options) { 10 | return this.each(function() { 11 | (QueryLoader2(this, options)); 12 | }); 13 | }; 14 | })(window.jQuery || window.Zepto); 15 | } 16 | 17 | // component 18 | if (typeof module !== 'undefined') { 19 | module.exports = QueryLoader2; 20 | } 21 | 22 | // requirejs support 23 | if (typeof define === 'function' && define.amd) { 24 | define([], function() { 25 | 'use strict'; 26 | return QueryLoader2; 27 | }); 28 | } 29 | 30 | window.QueryLoader2 = QueryLoader2; 31 | TempOverlay(); 32 | -------------------------------------------------------------------------------- /test/browser/css/style.css: -------------------------------------------------------------------------------- 1 | body { 2 | background-color: #000; 3 | margin: 0px; 4 | padding: 0px; 5 | background-image: url(../images/LittleSnowHills.jpg); 6 | background-position: 50% 50%; 7 | background-attachment: fixed; 8 | font-family: sans-serif; 9 | font-size: 14px; 10 | } 11 | 12 | h1 { 13 | 14 | } 15 | 16 | p { 17 | line-height: 1.4em; 18 | } 19 | 20 | body #qLoverlay { 21 | background-color: #111; 22 | position: fixed; 23 | z-index: 666999; 24 | top: 0; 25 | left: 0; 26 | width: 100%; 27 | height: 100%; 28 | } 29 | 30 | body #content { 31 | width: 800px; 32 | padding: 20px; 33 | background-color: #f1f1f1; 34 | margin: 20px auto; 35 | overflow: hidden; 36 | } 37 | 38 | body #content ul { 39 | padding: 0px; 40 | margin: 0px; 41 | } 42 | 43 | body #content ul li { 44 | display: block; 45 | list-style-type: none; 46 | float: left; 47 | width: 400px; 48 | height: 400px; 49 | overflow: hidden; 50 | text-align: center; 51 | } 52 | 53 | body #content ul li.baizley { 54 | background: url(../images/johnbaizley_Tat.jpg); 55 | } 56 | 57 | body #content ul li.gradient { 58 | padding: 20px; 59 | width: 360px; 60 | height: 360px; 61 | 62 | background: #efc5ca; /* Old browsers */ 63 | background: -moz-linear-gradient(top, #efc5ca 0%, #ef2f43 100%); /* FF3.6+ */ 64 | background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,#efc5ca), color-stop(100%,#ef2f43)); /* Chrome,Safari4+ */ 65 | background: -webkit-linear-gradient(top, #efc5ca 0%,#ef2f43 100%); /* Chrome10+,Safari5.1+ */ 66 | background: -o-linear-gradient(top, #efc5ca 0%,#ef2f43 100%); /* Opera 11.10+ */ 67 | background: -ms-linear-gradient(top, #efc5ca 0%,#ef2f43 100%); /* IE10+ */ 68 | background: linear-gradient(top, #efc5ca 0%,#ef2f43 100%); /* W3C */ 69 | filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#efc5ca', endColorstr='#ef2f43',GradientType=0 ); /* IE6-9 */ 70 | } 71 | 72 | body #mocha { 73 | background: white; 74 | position: relative; 75 | margin: 0; 76 | padding: 60px 50px; 77 | } 78 | 79 | body #mocha-stats { 80 | position: absolute; 81 | } -------------------------------------------------------------------------------- /test/browser/images/1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Gaya/queryloader2/353a3cb68f38d42072145053c76f99709197435b/test/browser/images/1.jpg -------------------------------------------------------------------------------- /test/browser/images/2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Gaya/queryloader2/353a3cb68f38d42072145053c76f99709197435b/test/browser/images/2.jpg -------------------------------------------------------------------------------- /test/browser/images/3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Gaya/queryloader2/353a3cb68f38d42072145053c76f99709197435b/test/browser/images/3.jpg -------------------------------------------------------------------------------- /test/browser/images/4.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Gaya/queryloader2/353a3cb68f38d42072145053c76f99709197435b/test/browser/images/4.jpg -------------------------------------------------------------------------------- /test/browser/images/Dali_Swans_Reflecting_Elephants.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Gaya/queryloader2/353a3cb68f38d42072145053c76f99709197435b/test/browser/images/Dali_Swans_Reflecting_Elephants.jpg -------------------------------------------------------------------------------- /test/browser/images/LittleSnowHills.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Gaya/queryloader2/353a3cb68f38d42072145053c76f99709197435b/test/browser/images/LittleSnowHills.jpg -------------------------------------------------------------------------------- /test/browser/images/hokusai_1680_1050.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Gaya/queryloader2/353a3cb68f38d42072145053c76f99709197435b/test/browser/images/hokusai_1680_1050.jpg -------------------------------------------------------------------------------- /test/browser/images/johnbaizley_Tat.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Gaya/queryloader2/353a3cb68f38d42072145053c76f99709197435b/test/browser/images/johnbaizley_Tat.jpg -------------------------------------------------------------------------------- /test/browser/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | QueryLoader v2 Demo - Gaya Design 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 |
16 |

QueryLoader v2 demo page

17 | 18 |

19 | This was a simple demo of what QueryLoader2 does: Giving a simple loading overlay 20 | before showing the webpage. 21 |

22 | 23 |

24 | 25 | Go back to the post 26 | 27 |

28 | 29 |
    30 |
  • 31 | 32 |
  • 33 |
  • 34 | 35 |
  • 36 |
  • 37 |
  • 38 |
  • 39 | Gradient test 40 |
  • 41 |
  • 42 | Non existant 43 | 44 |
  • 45 |
46 |
47 | 48 |
49 | 50 | 51 | 52 | 59 | 60 | 61 | -------------------------------------------------------------------------------- /test/browser/jquery-test.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | QueryLoader v2 Demo - Gaya Design 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 23 | 24 | 25 | 26 |
27 |

QueryLoader v2 demo page

28 | 29 |

30 | This was a simple demo of what QueryLoader2 does: Giving a simple loading overlay 31 | before showing the webpage. 32 |

33 | 34 |

35 | 36 | Go back to the post 37 | 38 |

39 | 40 |
    41 |
  • 42 | 43 |
  • 44 |
  • 45 | 46 |
  • 47 |
  • 48 |
  • 49 |
  • 50 | Gradient test 51 |
  • 52 |
  • 53 | Non existant 54 | 55 |
  • 56 |
57 |
58 | 59 |
60 | 61 | 62 | 63 | 70 | 71 | 72 | -------------------------------------------------------------------------------- /test/browser/js/script.js: -------------------------------------------------------------------------------- 1 | window.addEventListener('DOMContentLoaded', function() { 2 | 'use strict'; 3 | var ql = QueryLoader2(document.querySelector('body'), { 4 | barColor: '#efefef', 5 | backgroundColor: '#111', 6 | percentage: true, 7 | barHeight: 1, 8 | minimumTime: 200, 9 | fadeOutTime: 1000, 10 | }); 11 | }); -------------------------------------------------------------------------------- /test/tests.js: -------------------------------------------------------------------------------- 1 | var assert = require('assert'); 2 | 3 | var PercentageParser = require('../src/Overlay/PercentageParser'); 4 | var LoadingBar = require('../src/Overlay/LoadingBar'); 5 | var Percentage = require('../src/Overlay/Percentage'); 6 | var Overlay = require('../src/Overlay'); 7 | var Image = require('../src/ImagePreloader/Image'); 8 | var QueryLoader = require('../src/QueryLoader'); 9 | var ImagePreloader = require('../src/ImagePreloader'); 10 | 11 | describe('PercentageParser', function() { 12 | it('should round given percentages below zero to zero', function() { 13 | assert.equal(PercentageParser(-100), 0); 14 | assert.equal(PercentageParser(-10), 0); 15 | assert.equal(PercentageParser(-1), 0); 16 | assert.equal(PercentageParser(0), 0); 17 | }); 18 | 19 | it('should round given percentages above 100 to 100', function() { 20 | assert.equal(PercentageParser(1000), 100); 21 | assert.equal(PercentageParser(100), 100); 22 | assert.equal(PercentageParser(101), 100); 23 | }); 24 | 25 | it('should round decimals to round numbers', function() { 26 | assert.equal(PercentageParser(1.5), 1); 27 | assert.equal(PercentageParser(1.6), 1); 28 | assert.equal(PercentageParser(2.1), 2); 29 | assert.equal(PercentageParser(2), 2); 30 | assert.equal(PercentageParser('2'), 2); 31 | assert.equal(PercentageParser('2.2'), 2); 32 | }); 33 | }); 34 | 35 | describe('LoadingBar', function() { 36 | describe('#create()', function() { 37 | var lb = LoadingBar(); 38 | lb.create(); 39 | 40 | it('should create an element for itself', function() { 41 | assert.notEqual(null, lb.element); 42 | assert.notEqual('undefined', typeof lb.element); 43 | assert.notEqual('undefined', typeof lb.element.tagName); 44 | assert.equal('div', lb.element.tagName.toLowerCase()); 45 | assert.equal(lb.className, lb.element.getAttribute('class')); 46 | }); 47 | 48 | it('should apply default styling', function() { 49 | assert.equal('absolute', lb.element.style.position); 50 | assert.equal(lb.barHeight + 'px', lb.element.style.height); 51 | }); 52 | }); 53 | 54 | describe('#updateProgress()', function() { 55 | it('should update the progress and adjust the loading bar', function() { 56 | var lb = LoadingBar(); 57 | lb.create(); 58 | 59 | assert.equal('0%', lb.element.style.width); 60 | 61 | lb.updateProgress(10, 0); 62 | assert.equal('10%', lb.element.style.width); 63 | 64 | lb.updateProgress(50, 0); 65 | assert.equal('50%', lb.element.style.width); 66 | 67 | lb.updateProgress(100, 0); 68 | assert.equal('100%', lb.element.style.width); 69 | 70 | lb.updateProgress(-20, 0); 71 | assert.equal('0%', lb.element.style.width); 72 | 73 | lb.updateProgress(420, 0); 74 | assert.equal('100%', lb.element.style.width); 75 | }); 76 | 77 | it('should not break on floats', function() { 78 | var lb = LoadingBar(); 79 | lb.create(); 80 | 81 | lb.updateProgress(10.6, 0); 82 | assert.equal('10%', lb.element.style.width); 83 | 84 | lb.updateProgress(50.456, 0); 85 | assert.equal('50%', lb.element.style.width); 86 | }); 87 | }); 88 | }); 89 | 90 | describe('Percentage', function() { 91 | describe('#create()', function() { 92 | var p = Percentage(); 93 | p.create(); 94 | 95 | it('should create an element for itself', function() { 96 | assert.notEqual(null, p.element); 97 | assert.notEqual('undefined', typeof p.element); 98 | assert.notEqual('undefined', typeof p.element.tagName); 99 | assert.equal('div', p.element.tagName.toLowerCase()); 100 | assert.equal(p.className, p.element.getAttribute('class')); 101 | }); 102 | 103 | it('should apply default styling', function() { 104 | assert.equal('absolute', p.element.style.position); 105 | }); 106 | }); 107 | 108 | describe('#updateProgress()', function() { 109 | var p = Percentage(); 110 | p.create(); 111 | 112 | it('should update the progress and adjust the loading bar', function() { 113 | assert.equal('0%', p.element.innerHTML); 114 | 115 | p.updateProgress(10, 0); 116 | assert.equal('10%', p.element.innerHTML); 117 | 118 | p.updateProgress(50, 0); 119 | assert.equal('50%', p.element.innerHTML); 120 | 121 | p.updateProgress(100, 0); 122 | assert.equal('100%', p.element.innerHTML); 123 | 124 | p.updateProgress(-20, 0); 125 | assert.equal('0%', p.element.innerHTML); 126 | 127 | p.updateProgress(420, 0); 128 | assert.equal('100%', p.element.innerHTML); 129 | }); 130 | 131 | it('should not break on floats', function() { 132 | p.updateProgress(10.6, 0); 133 | assert.equal('10%', p.element.innerHTML); 134 | 135 | p.updateProgress(50.456, 0); 136 | assert.equal('50%', p.element.innerHTML); 137 | }); 138 | }); 139 | }); 140 | 141 | describe('Overlay', function() { 142 | var fakeBody = document.createElement('body'); 143 | 144 | describe('#create()', function() { 145 | var o = Overlay(fakeBody); 146 | o.create(); 147 | 148 | it('should create an element for itself', function() { 149 | assert.notEqual(null, o.element); 150 | assert.notEqual('undefined', typeof o.element); 151 | assert.notEqual('undefined', typeof o.element.tagName); 152 | assert.equal('div', o.element.tagName.toLowerCase()); 153 | assert.equal(o.className, o.element.getAttribute('class')); 154 | }); 155 | }); 156 | 157 | describe('#calculatePosition()', function() { 158 | var o = Overlay(); 159 | 160 | it('should give the correct needed position of the overlay', function() { 161 | o.parentElement = fakeBody; 162 | 163 | assert.equal('fixed', o.calculatePosition()); 164 | 165 | var fakeContainer = document.createElement('div'); 166 | fakeContainer.style.position = 'static'; 167 | 168 | o.parentElement = fakeContainer; 169 | 170 | assert.equal('absolute', o.calculatePosition()); 171 | assert.equal('relative', o.parentElement.style.position); 172 | 173 | o.parentElement.style.position = 'absolute'; 174 | 175 | assert.equal('absolute', o.calculatePosition()); 176 | }); 177 | }); 178 | 179 | describe('#updateProgess()', function() { 180 | var o = Overlay(); 181 | o.parentElement = fakeBody; 182 | o.create(); 183 | 184 | o.percentage = Percentage(); 185 | o.percentage.create(); 186 | 187 | o.loadingBar = LoadingBar(); 188 | o.loadingBar.create(); 189 | 190 | it('should update the loading progress of both percentage and loadingbar', function() { 191 | assert.equal('0%', o.percentage.element.innerHTML); 192 | assert.equal('0%', o.loadingBar.element.style.width); 193 | 194 | o.updateProgress(10, 0); 195 | 196 | assert.equal('10%', o.percentage.element.innerHTML); 197 | assert.equal('10%', o.loadingBar.element.style.width); 198 | }); 199 | }); 200 | }); 201 | 202 | describe('Image', function() { 203 | describe('#constructor()', function() { 204 | it('should create an image object with given src', function() { 205 | var exampleImage = Image('some/src'); 206 | 207 | assert.equal('some/src', exampleImage.src); 208 | }); 209 | 210 | it('should create a dom object with given src', function() { 211 | var exampleImage = Image('some/src'); 212 | 213 | assert.notEqual(-1, exampleImage.element.src.indexOf('some/src')); 214 | }); 215 | }); 216 | 217 | describe('#preload()', function() { 218 | it('should callback when an image is loaded', function(done) { 219 | var exampleImage = Image('images/1.jpg'); 220 | 221 | exampleImage.preload(done); 222 | }); 223 | }); 224 | }); 225 | 226 | describe('QueryLoader', function() { 227 | describe('#constructor', function() { 228 | it('should be the same not matter how you instantiate', function() { 229 | var qlNew = new QueryLoader(); 230 | var qlFactory = QueryLoader(); 231 | 232 | assert.equal(JSON.stringify(qlNew), JSON.stringify(qlFactory)); 233 | }); 234 | }); 235 | 236 | describe('#createOverlay()', function() { 237 | var ql = QueryLoader(); 238 | 239 | it('should create an overlay when called', function() { 240 | ql.createOverlay(); 241 | 242 | assert.notEqual(ql.overlay, null); 243 | }); 244 | }); 245 | 246 | describe('#createPreloader()', function() { 247 | var ql = QueryLoader(); 248 | 249 | it('should create the preloader', function() { 250 | ql.createPreloader(); 251 | 252 | assert.notEqual(ql.preloader, null); 253 | }); 254 | }); 255 | 256 | describe('#extend()', function() { 257 | it('should merge two objects', function() { 258 | var ql = QueryLoader(); 259 | 260 | var destination = { 261 | some: 'thing', 262 | is: 'not', 263 | right: 'man', 264 | }; 265 | 266 | var source = { 267 | some: 'one', 268 | right: 'dude', 269 | }; 270 | 271 | assert.deepEqual({ 272 | some: 'one', 273 | is: 'not', 274 | right: 'dude', 275 | }, ql.extend(destination, source)); 276 | }); 277 | }); 278 | 279 | describe('#updateProgress()', function() { 280 | var called = false; 281 | var ql = QueryLoader(document.createElement('div'), { 282 | onProgress: function(amount) { 283 | called = true; 284 | }, 285 | }); 286 | 287 | it('should call the onProgress event', function() { 288 | ql.updateProgress(); 289 | 290 | assert.equal(called, true); 291 | }); 292 | }); 293 | }); 294 | 295 | describe('ImagePreloader', function() { 296 | 'use strict'; 297 | describe('#getImageSrcs()', function() { 298 | var ip = ImagePreloader(); 299 | 300 | var fakeImagesContainer = document.createElement('div'); 301 | 302 | var img1 = document.createElement('img'); 303 | img1.setAttribute('src', 'fakeimg1.png'); 304 | fakeImagesContainer.appendChild(img1); 305 | 306 | var img2 = document.createElement('img'); 307 | img2.setAttribute('src', 'fakeimg2.png'); 308 | fakeImagesContainer.appendChild(img2); 309 | 310 | var img3 = document.createElement('section'); 311 | img3.style.backgroundImage = 'url(fakeimg3.png)'; 312 | fakeImagesContainer.appendChild(img3); 313 | 314 | var img4 = document.createElement('section'); 315 | img4.style.backgroundImage = 'linear-gradient(left, #fff, #eee)'; 316 | fakeImagesContainer.appendChild(img4); 317 | 318 | var img5 = document.createElement('section'); 319 | img5.style.background = 'url(fakeimg5.png)'; 320 | fakeImagesContainer.appendChild(img5); 321 | 322 | var img6 = document.createElement('img'); 323 | fakeImagesContainer.appendChild(img6); 324 | 325 | it('should get all images within the given element', function() { 326 | var images = ip.getImageSrcs(fakeImagesContainer); 327 | 328 | assert.equal(4, images.length); 329 | assert.notEqual(-1, images[0].indexOf('fakeimg1.png')); 330 | assert.notEqual(-1, images[1].indexOf('fakeimg2.png')); 331 | assert.notEqual(-1, images[2].indexOf('fakeimg3.png')); 332 | assert.notEqual(-1, images[3].indexOf('fakeimg5.png')); 333 | }); 334 | }); 335 | 336 | describe('#hasGradient()', function() { 337 | var ip = ImagePreloader(); 338 | 339 | it('should check if given url has a gradient', function() { 340 | assert.equal(false, ip.hasGradient('hasnogradienthere.png')); 341 | assert.equal(false, ip.hasGradient('grasdfsadg')); 342 | assert.equal(true, ip.hasGradient('linear-gradient(left, #fff, #fff)')); 343 | }); 344 | }); 345 | 346 | describe('#stripUrl()', function() { 347 | var ip = ImagePreloader(); 348 | 349 | it('should strip the url() part from given src', function() { 350 | assert.equal(-1, ip.stripUrl('url(this/path/file.png)').indexOf('url')); 351 | assert.equal(-1, ip.stripUrl('file.png').indexOf('url')); 352 | }); 353 | 354 | it('should strip quotes from the URL', function() { 355 | assert.equal('this/path/file.png', ip.stripUrl('url("this/path/file.png")')); 356 | assert.equal('this/path/file.png', ip.stripUrl('url(\'this/path/file.png\')')); 357 | }); 358 | }); 359 | 360 | describe('#validUrl()', function() { 361 | var ip = ImagePreloader(); 362 | 363 | it('should check if given url is valid', function() { 364 | assert.equal(false, ip.validUrl('')); 365 | assert.equal(false, ip.validUrl('data:blablabla')); 366 | assert.equal(true, ip.validUrl('/this/is/valid.png')); 367 | }); 368 | }); 369 | 370 | describe('#urlIsNew()', function() { 371 | var ip = ImagePreloader(); 372 | ip.sources = ['test.png', 'something.png', 'image.jpg']; 373 | 374 | it('should check if given url is new in this.images', function() { 375 | assert.equal(false, ip.urlIsNew('image.jpg')); 376 | assert.equal(true, ip.urlIsNew('new.png')); 377 | }); 378 | }); 379 | }); 380 | --------------------------------------------------------------------------------