MDL-11082 Improved groups upgrade performance 1.8x -> 1.9; thanks Eloy for telling...
[moodle-pu.git] / lib / yui / imageloader / imageloader-experimental-debug.js
blob55b85c5efd6ee3e9042338b1298d700382c42f88
1 /*
2 Copyright (c) 2007, Yahoo! Inc. All rights reserved.
3 Code licensed under the BSD License:
4 http://developer.yahoo.net/yui/license.txt
5 version: 2.3.0
6 */
7 /**
8 * The image loader is a framework to dynamically load images
9 * according to certain triggers, enabling faster load times
10 * and a more responsive UI.
12 * @module imageloader
13 * @namespace YAHOO.util
14 * @experimental
17 if (typeof(YAHOO.util.ImageLoader) == 'undefined') {
18 YAHOO.util.ImageLoader = {};
21 /**
22 * A group for images. A group can have one time limit and a series of triggers. Thus the images belonging to this group must share these constraints.
23 * @class YAHOO.util.ImageLoader.group
24 * @requires YAHOO.util.Dom
25 * @requires YAHOO.util.Event
26 * @constructor
27 * @param {String|HTMLElement} trigEl The HTML element id or reference to assign the trigger event to. Can be null for no trigger
28 * @param {String} trigAct The type of event to assign to trigEl. Can be null for no trigger
29 * @param {Number} timeout Timeout (time limit) length, in seconds. Can be undefined, or <= 0, for no time limit
31 YAHOO.util.ImageLoader.group = function(trigEl, trigAct, timeout) {
32 /**
33 * Name for the group. Only used to identify the group in logging statements
34 * @property name
35 * @type String
37 this.name = 'unnamed';
39 /**
40 * Collection of images registered with this group
41 * @property _imgObjs
42 * @private
43 * @type Object
45 this._imgObjs = {};
47 /**
48 * Timeout (time limit) length, in seconds
49 * @property timeoutLen
50 * @type Number
52 this.timeoutLen = timeout;
54 /**
55 * Timeout object to keep a handle on the time limit
56 * @property _timeout
57 * @private
58 * @type Object
60 this._timeout = null;
62 /**
63 * Collection of triggers for this group.
64 * Keeps track of each trigger's element, event, and event-listener-callback "fetch" function
65 * @property _triggers
66 * @private
67 * @type Array
69 this._triggers = [];
71 /**
72 * Flag to check if images are above the fold. If foldConditional is true, the group will check each of its image locations at page load. If any part of the image is within the client viewport, the image is displayed immediately
73 * @property foldConditional
74 * @type Boolean
76 this.foldConditional = false;
78 /**
79 * Class name that will identify images belonging to the group. This class name will be removed from each element in order to fetch images.
80 * This class should have, in its CSS style definition, "background:none !important;"
81 * @property className
82 * @type String
84 this.className = null;
86 /**
87 * HTML elements having the class name that is associated with this group
88 * Elements are stored during the _foldCheck function and reused later during the fetch function. Gives a slight performance improvement when className and foldConditional are both used
89 * @property _classImageEls
90 * @private
91 * @type Array
93 this._classImageEls = null;
95 // add a listener to set the time limit in the onload
96 YAHOO.util.Event.addListener(window, 'load', this._onloadTasks, this, true);
97 // add the trigger
98 this.addTrigger(trigEl, trigAct);
103 * Adds a trigger to the group. Call this with the same style as YAHOO.util.Event.addListener
104 * @method addTrigger
105 * @param {String|HTMLElement} trigEl The HTML element id or reference to assign the trigger event to
106 * @param {String} trigAct The type of event to assign to trigEl
108 YAHOO.util.ImageLoader.group.prototype.addTrigger = function(trigEl, trigAct) {
109 if (! trigEl || ! trigAct) {
110 return;
112 /* Need to wrap the fetch function. Event Util can't distinguish prototyped functions of different instantiations
113 * Leads to this scenario: groupA and groupZ both have window-scroll triggers. groupZ also has a 2-sec timeout (groupA has no timeout).
114 * groupZ's timeout fires; we remove the triggers. The removeListener call finds the first window-scroll event with Y.u.IL.p.fetch, which is groupA's.
115 * groupA's trigger is removed and never fires, leaving images unfetched
117 var wrappedFetch = function() {
118 this.fetch();
120 this._triggers.push([trigEl, trigAct, wrappedFetch]);
121 YAHOO.util.Event.addListener(trigEl, trigAct, wrappedFetch, this, true);
125 * Setup to do in the window's onload
126 * Initiates time limit for group; executes the fold check for the images
127 * @method _onloadTasks
128 * @private
130 YAHOO.util.ImageLoader.group.prototype._onloadTasks = function() {
131 if (this.timeoutLen && typeof(this.timeoutLen) == 'number' && this.timeoutLen > 0) {
132 this._timeout = setTimeout(this._getFetchTimeout(), this.timeoutLen * 1000);
135 if (this.foldConditional) {
136 this._foldCheck();
141 * Returns the group's fetch method, with the proper closure, for use with setTimeout
142 * @method _getFetchTimeout
143 * @return {Function} group's fetch method
144 * @private
146 YAHOO.util.ImageLoader.group.prototype._getFetchTimeout = function() {
147 var self = this;
148 return function() { self.fetch(); };
152 * Registers a background image with the group
153 * @method registerBgImage
154 * @param {String} domId HTML DOM id of the image element
155 * @param {String} url URL for the image
156 * @return {Object} bgImgObj that was registered, for modifying any attributes in the object
158 YAHOO.util.ImageLoader.group.prototype.registerBgImage = function(domId, url) {
159 this._imgObjs[domId] = new YAHOO.util.ImageLoader.bgImgObj(domId, url);
160 return this._imgObjs[domId];
163 * Registers a src image with the group
164 * @method registerSrcImage
165 * @param {String} domId HTML DOM id of the image element
166 * @param {String} url URL for the image
167 * @param {Int} width pixel width of the image - defaults to image's natural size
168 * @param {Int} height pixel height of the image - defaults to image's natural size
169 * @return {Object} srcImgObj that was registered, for modifying any attributes in the object
171 YAHOO.util.ImageLoader.group.prototype.registerSrcImage = function(domId, url, width, height) {
172 this._imgObjs[domId] = new YAHOO.util.ImageLoader.srcImgObj(domId, url, width, height);
173 return this._imgObjs[domId];
176 * Registers an alpha-channel-type png background image with the group
177 * @method registerPngBgImage
178 * @param {String} domId HTML DOM id of the image element
179 * @param {String} url URL for the image
180 * @return {Object} pngBgImgObj that was registered, for modifying any attributes in the object
182 YAHOO.util.ImageLoader.group.prototype.registerPngBgImage = function(domId, url) {
183 this._imgObjs[domId] = new YAHOO.util.ImageLoader.pngBgImgObj(domId, url);
184 return this._imgObjs[domId];
188 * Displays the images in the group
189 * @method fetch
191 YAHOO.util.ImageLoader.group.prototype.fetch = function() {
192 YAHOO.log('Fetching images in group: "' + this.name + '".', 'info', 'imageloader');
194 clearTimeout(this._timeout);
195 // remove all listeners
196 for (var i=0; i < this._triggers.length; i++) {
197 YAHOO.util.Event.removeListener(this._triggers[i][0], this._triggers[i][1], this._triggers[i][2]);
200 // fetch whatever we need to by className
201 this._fetchByClass();
203 // fetch registered images
204 for (var id in this._imgObjs) {
205 if (YAHOO.lang.hasOwnProperty(this._imgObjs, id)) {
206 this._imgObjs[id].fetch();
212 * Checks the position of each image in the group. If any part of the image is within the client viewport, shows the image immediately.
213 * @method _foldCheck
214 * @private
216 YAHOO.util.ImageLoader.group.prototype._foldCheck = function() {
217 YAHOO.log('Checking for images above the fold in group: "' + this.name + '"', 'info', 'imageloader');
218 var scrollTop = (document.compatMode != 'CSS1Compat') ? document.body.scrollTop : document.documentElement.scrollTop;
219 var viewHeight = YAHOO.util.Dom.getViewportHeight();
220 var hLimit = scrollTop + viewHeight;
221 var scrollLeft = (document.compatMode != 'CSS1Compat') ? document.body.scrollLeft : document.documentElement.scrollLeft;
222 var viewWidth = YAHOO.util.Dom.getViewportWidth();
223 var wLimit = scrollLeft + viewWidth;
224 for (var id in this._imgObjs) {
225 if (YAHOO.lang.hasOwnProperty(this._imgObjs, id)) {
226 var elPos = YAHOO.util.Dom.getXY(this._imgObjs[id].domId);
227 if (elPos[1] < hLimit && elPos[0] < wLimit) {
228 YAHOO.log('Image with id "' + this._imgObjs[id].domId + '" is above the fold. Fetching image.', 'info', 'imageloader');
229 this._imgObjs[id].fetch();
233 // and by class
234 if (this.className) {
235 this._classImageEls = YAHOO.util.Dom.getElementsByClassName(this.className);
236 for (var i=0; i < this._classImageEls.length; i++) {
237 var elPos = YAHOO.util.Dom.getXY(this._classImageEls[i]);
238 if (elPos[1] < hLimit && elPos[0] < wLimit) {
239 YAHOO.log('Image with id "' + this._classImageEls[i].id + '" is above the fold. Fetching image. (Image registered by class name with the group - may not have an id.)', 'info', 'imageloader');
240 YAHOO.util.Dom.removeClass(this._classImageEls[i], this.className);
247 * Finds all elements in the Dom with the class name specified in the group. Removes the class from the element in order to let the style definitions trigger the image fetching
248 * @method _fetchByClass
249 * @private
251 YAHOO.util.ImageLoader.group.prototype._fetchByClass = function() {
252 if (! this.className) {
253 return;
256 YAHOO.log('Fetching all images with class "' + this.className + '" in group "' + this.name + '".', 'info', 'imageloader');
257 // this._classImageEls may have been set during _foldCheck
258 if (this._classImageEls === null) {
259 this._classImageEls = YAHOO.util.Dom.getElementsByClassName(this.className);
261 YAHOO.util.Dom.removeClass(this._classImageEls, this.className);
266 * Base class for image objects to be registered with the groups
267 * @class YAHOO.util.ImageLoader.imgObj
268 * @constructor
269 * @param {String} domId HTML DOM id of the image element
270 * @param {String} url URL for the image
272 YAHOO.util.ImageLoader.imgObj = function(domId, url) {
274 * HTML DOM id of the image element
275 * @property domId
276 * @type String
278 this.domId = domId;
281 * URL for the image
282 * @property url
283 * @type String
285 this.url = url;
288 * Pixel width of the image. Will be set as a "width" attribute after the image is fetched.
289 * Detaults to the natural width of the image.
290 * Only appropriate with src images
291 * @property width
292 * @type Int
294 this.width = null;
297 * Pixel height of the image. Will be set as a "height" attribute after the image is fetched.
298 * Detaults to the natural height of the image.
299 * Only appropriate with src images
300 * @property height
301 * @type Int
303 this.height = null;
306 * Whether the style.visibility should be set to "visible" after the image is fetched.
307 * Used when setting src images as visibility:hidden prior to image fetching
308 * @property setVisible
309 * @type Boolean
311 this.setVisible = false;
314 * Whether the image has already been fetched. In the case of a foldCondional group, keeps track for when the trigger is fired so images aren't fetched twice
315 * @property _fetched
316 * @type Boolean
317 * @private
319 this._fetched = false;
323 * Displays the image; puts the URL into the DOM
324 * @method fetch
326 YAHOO.util.ImageLoader.imgObj.prototype.fetch = function() {
327 if (this._fetched) {
328 return;
330 var el = document.getElementById(this.domId);
331 if (! el) {
332 return;
334 YAHOO.log('Fetching image with id "' + this.domId + '".', 'info', 'imageloader');
335 this._applyUrl(el);
337 if (this.setVisible) {
338 el.style.visibility = 'visible';
340 if (this.width) {
341 el.width = this.width;
343 if (this.height) {
344 el.height = this.height;
346 this._fetched = true;
350 * Inserts the image URL into the DOM so that the image is displayed.
351 * Must be overridden by child class
352 * @method _applyUrl
353 * @param {Object} el HTML DOM element
354 * @private
356 YAHOO.util.ImageLoader.imgObj.prototype._applyUrl = function(el) {
360 * Background image object. A background image is one whose URL is specified by "background-image" in the element's style
361 * @class YAHOO.util.ImageLoader.bgImgObj
362 * @constructor
363 * @extends YAHOO.util.ImageLoader.imgObj
364 * @param {String} domId HTML DOM id of the image element
365 * @param {String} url URL for the image
367 YAHOO.util.ImageLoader.bgImgObj = function(domId, url) {
368 YAHOO.util.ImageLoader.bgImgObj.superclass.constructor.call(this, domId, url);
371 YAHOO.lang.extend(YAHOO.util.ImageLoader.bgImgObj, YAHOO.util.ImageLoader.imgObj);
374 * Inserts the image URL into the DOM so that the image is displayed.
375 * Sets style.backgroundImage
376 * @method _applyUrl
377 * @param {Object} el HTML DOM element
378 * @private
380 YAHOO.util.ImageLoader.bgImgObj.prototype._applyUrl = function(el) {
381 el.style.backgroundImage = "url('" + this.url + "')";
385 * Source image object. A source image is one whose URL is specified by a src attribute in the DOM element
386 * @class YAHOO.util.ImageLoader.srcImgObj
387 * @constructor
388 * @extends YAHOO.util.ImageLoader.imgObj
389 * @param {String} domId HTML DOM id of the image element
390 * @param {String} url URL for the image
391 * @param {Int} width pixel width of the image - defaults to image's natural size
392 * @param {Int} height pixel height of the image - defaults to image's natural size
394 YAHOO.util.ImageLoader.srcImgObj = function(domId, url, width, height) {
395 YAHOO.util.ImageLoader.srcImgObj.superclass.constructor.call(this, domId, url);
396 this.width = width;
397 this.height = height;
400 YAHOO.lang.extend(YAHOO.util.ImageLoader.srcImgObj, YAHOO.util.ImageLoader.imgObj);
403 * Inserts the image URL into the DOM so that the image is displayed.
404 * Sets src
405 * @method _applyUrl
406 * @param {Object} el HTML DOM element
407 * @private
409 YAHOO.util.ImageLoader.srcImgObj.prototype._applyUrl = function(el) {
410 el.src = this.url;
414 * PNG background image object. A PNG background image is one whose URL is specified through AlphaImageLoader or by "background-image" in the element's style
415 * @class YAHOO.util.ImageLoader.pngBgImgObj
416 * @constructor
417 * @extends YAHOO.util.ImageLoader.imgObj
418 * @param {String} domId HTML DOM id of the image element
419 * @param {String} url URL for the image
421 YAHOO.util.ImageLoader.pngBgImgObj = function(domId, url) {
422 YAHOO.util.ImageLoader.pngBgImgObj.superclass.constructor.call(this, domId, url);
425 YAHOO.lang.extend(YAHOO.util.ImageLoader.pngBgImgObj, YAHOO.util.ImageLoader.imgObj);
428 * Inserts the image URL into the DOM so that the image is displayed.
429 * If the browser is determined to be IE6 (or older), sets the AlphaImageLoader src; otherwise sets style.backgroundImage
430 * @method _applyUrl
431 * @param {Object} el HTML DOM element
432 * @private
434 YAHOO.util.ImageLoader.pngBgImgObj.prototype._applyUrl = function(el) {
435 if (YAHOO.env.ua.ie && YAHOO.env.ua.ie <= 6) {
436 el.style.filter = 'progid:DXImageTransform.Microsoft.AlphaImageLoader(src="' + this.url + '", sizingMethod="scale")';
438 else {
439 el.style.backgroundImage = "url('" + this.url + "')";
442 YAHOO.register("imageloader", YAHOO.util.ImageLoader, {version: "2.3.0", build: "442"});