1/** 2 * jQuery.imageloader 3 * (C) 2012, Takashi Mizohata 4 * http://beatak.github.com/jquery-imageloader/ 5 * MIT LICENSE 6 */ 7(function($) { 8 9"use strict"; 10 11var DEFAULT_OPTIONS = { 12 selector: '', 13 dataattr: 'src', 14 background: false, 15 each: null, 16 eacherror: null, 17 callback: null, 18 timeout: 5000 19}; 20 21var init = function (_i, self, opts) { 22 var q = Queue.getInstance(); 23 var $this = $(self); 24 var defaults = $.extend({}, DEFAULT_OPTIONS, opts || {}); 25 var ns = '_' + ('' + (new Date()).valueOf()).slice(-7); 26 var $elms; 27 var len = 0; 28 29 if (defaults.selector === '' && $this.data(defaults.dataattr) ) { 30 $elms = $this; 31 len = 1; 32 } 33 else { 34 $elms = $this.find([defaults.selector, '[data-', defaults.dataattr, ']'].join('')); 35 len = $elms.length; 36 } 37 38 $this.data( 39 ns, 40 { 41 each: defaults.each, 42 eacherror: defaults.eacherror, 43 callback: defaults.callback, 44 isLoading: true, 45 loadedImageCounter: 0, 46 length: len 47 } 48 ); 49 50 if (len === 0) { 51 finishImageLoad(self, ns); 52 } 53 else { 54 $elms.each( 55 function (i, elm) { 56 q.add(buildImageLoadFunc(elm, self, ns, defaults.background, defaults.dataattr, defaults.timeout)); 57 } 58 ); 59 // console.log(['we are gonna load ', len, ' image(s) on ', ns].join('')); 60 $this.on('loadImage.' + ns, onLoadImage); 61 q.run(); 62 } 63 return self; 64}; 65 66// =================================================================== 67 68var onLoadImage = function (ev, elm, img, isError) { 69 // console.log('onLoadImage: ', ev.namespace); 70 var parent = ev.currentTarget; 71 var defaults = $(parent).data(ev.namespace); 72 if (!defaults.isLoading) { 73 // console.log('onLoadImage: is not loading but still called?'); 74 return; 75 } 76 if (isError) { 77 if (typeof defaults.eacherror === 'function') { 78 defaults.eacherror(elm); 79 } 80 else { 81 if (elm.parentNode !== null) { 82 elm.parentNode.removeChild(elm); 83 } 84 } 85 } 86 else if (typeof defaults.each === 'function') { 87 defaults.each(elm, img); 88 } 89 ++defaults.loadedImageCounter; 90 if (defaults.loadedImageCounter >= defaults.length) { 91 finishImageLoad(parent, ev.namespace); 92 } 93}; 94 95var finishImageLoad = function (parent, ns) { 96 // console.log('finishImageLoad: ', ns); 97 var $parent = $(parent); 98 var data = $parent.data(); 99 var callback = data[ns].callback; 100 $parent.off('loadImage.' + ns, onLoadImage); 101 delete data[ns]; 102 if (typeof callback === 'function') { 103 setTimeout( 104 function () { 105 callback(parent); 106 }, 107 $.imageloader.queueInterval * 2 108 ); 109 } 110}; 111 112var buildImageLoadFunc = function (elm, parent, namespace, isBg, attr, milsec_timeout) { 113 var $elm = $(elm); 114 var src = $elm.data(attr); 115 var hasFinished = false; 116 117 var onFinishLoagImage = function (ev, img) { 118 // delete attribute 119 $elm.removeAttr( ['data-', attr].join('') ); 120 $(parent).triggerHandler('loadImage.' + namespace, [elm, img, (ev && ev.type === 'error')]); 121 }; 122 123 return function () { 124 var timer_handler; 125 var $img = $('<img />'); // this statement is kinda silly, but IE needs this separated. 126 $img 127 .bind( 128 'error', 129 function (ev) { 130 hasFinished = true; 131 clearTimeout(timer_handler); 132 $(this).unbind('error').unbind('load'); 133 onFinishLoagImage(ev); 134 } 135 ) 136 .bind( 137 'load', 138 function(ev) { 139 hasFinished = true; 140 clearTimeout(timer_handler); 141 $(this).unbind('error').unbind('load'); 142 if (isBg) { 143 $elm.css('background-image', ['url(', src, ')'].join('')); 144 } 145 else { 146 $elm.attr('src', src); 147 } 148 onFinishLoagImage(ev, $img[0]); 149 } 150 ) 151 .attr('src', src); 152 timer_handler = setTimeout( 153 function () { 154 if (hasFinished === false) { 155 // console.log('timeout'); 156 $img.trigger('error'); 157 } 158 }, 159 milsec_timeout 160 ); 161 }; 162}; 163 164// =================================================================== 165 166var _queue_instance_; 167var Queue = { 168 getInstance: function () { 169 if (_queue_instance_ instanceof QueueImpl === false) { 170 _queue_instance_ = new QueueImpl(); 171 } 172 return _queue_instance_; 173 } 174}; 175 176var QueueImpl = function () { 177 this.index = 0; 178 this.queue = []; 179 this.isRunning = false;
180}; 181 182QueueImpl.prototype.add = function (func) { 183 if (typeof func !== 'function') { 184 throw new Error('you can only pass function.'); 185 } 186 this.queue.push(func); 187}; 188 189QueueImpl.prototype.run = function (firenow) { 190 var run = $.proxy(this.run, this); 191 firenow = firenow || false; 192 if (this.isRunning && !firenow) { 193 return; 194 } 195 this.isRunning = true; 196 this.queue[this.index++](); 197 if (this.index < this.queue.length) { 198 setTimeout( 199 function () { 200 run(true); 201 }, 202 $.imageloader.queueInterval 203 ); 204 } 205 else { 206 this.isRunning = false; 207 } 208}; 209 210// =================================================================== 211 212$.imageloader = { 213 queueInterval: 17 214}; 215 216$.fn.imageloader = function (opts) { 217 return this.each( 218 function (i, elm) { 219 init(i, elm, opts); 220 } 221 ); 222}; 223 224})(jQuery);
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.