]> CyberLeo.Net >> Repos - Github/sugarcrm.git/blob - include/javascript/yui/build/imageloader/imageloader.js
Release 6.2.0beta4
[Github/sugarcrm.git] / include / javascript / yui / build / imageloader / imageloader.js
1 /*
2 Copyright (c) 2009, Yahoo! Inc. All rights reserved.
3 Code licensed under the BSD License:
4 http://developer.yahoo.net/yui/license.txt
5 version: 2.8.0r4
6 */
7 /**
8  * The ImageLoader Utility is a framework to dynamically load images according to certain triggers,
9  * enabling faster load times and a more responsive UI.
10  *
11  * @module imageloader
12  * @namespace YAHOO.util
13  * @requires yahoo, dom, event
14  */
15
16 if (typeof(YAHOO.util.ImageLoader) == 'undefined') {
17         YAHOO.util.ImageLoader = {};
18 }
19
20 /**
21  * 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.
22  * @class YAHOO.util.ImageLoader.group
23  * @requires YAHOO.util.Dom
24  * @requires YAHOO.util.Event
25  * @constructor
26  * @param {String|HTMLElement}  trigEl  The HTML element id or reference to assign the trigger event to. Can be null for no trigger
27  * @param {String}      trigAct The type of event to assign to trigEl. Can be null for no trigger
28  * @param {Number}      timeout Timeout (time limit) length, in seconds. Can be undefined, or <= 0, for no time limit
29  */
30 YAHOO.util.ImageLoader.group = function(trigEl, trigAct, timeout) {
31         /**
32          * Name for the group. Only used to identify the group in logging statements
33          * @property name
34          * @type String
35          */
36         this.name = 'unnamed';
37         
38         /**
39          * Collection of images registered with this group
40          * @property _imgObjs
41          * @private
42          * @type Object
43          */
44         this._imgObjs = {};
45         
46         /**
47          * Timeout (time limit) length, in seconds
48          * @property timeoutLen
49          * @type Number
50          */
51         this.timeoutLen = timeout;
52         
53         /**
54          * Timeout object to keep a handle on the time limit
55          * @property _timeout
56          * @private
57          * @type Object
58          */
59         this._timeout = null;
60         
61         /**
62          * Collection of triggers for this group.
63          * Keeps track of each trigger's element, event, and event-listener-callback "fetch" function
64          * @property _triggers
65          * @private
66          * @type Array
67          */
68         this._triggers = [];
69
70         /**
71          * Collection of custom-event triggers for this group.
72          * Keeps track of each trigger's event object and event-listener-callback "fetch" function
73          * @property _customTriggers
74          * @private
75          * @type Array
76          */
77         this._customTriggers = [];
78
79         /**
80          * 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
81          * @property foldConditional
82          * @type Boolean
83          */
84         this.foldConditional = false;
85
86         /**
87          * Class name that will identify images belonging to the group. This class name will be removed from each element in order to fetch images.
88          * This class should have, in its CSS style definition, "background:none !important;"
89          * @property className
90          * @type String
91          */
92         this.className = null;
93
94         /**
95          * HTML elements having the class name that is associated with this group
96          * 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
97          * @property _classImageEls
98          * @private
99          * @type Array
100          */
101         this._classImageEls = null;
102
103         // add a listener to set the time limit in the onload
104         YAHOO.util.Event.addListener(window, 'load', this._onloadTasks, this, true);
105         // add the trigger
106         this.addTrigger(trigEl, trigAct);
107
108 };
109
110 /**
111  * Adds a trigger to the group. Call this with the same style as YAHOO.util.Event.addListener
112  * @method addTrigger
113  * @param {String|HTMLElement} trigEl  The HTML element id or reference to assign the trigger event to
114  * @param {String} trigAct The type of event to assign to trigEl
115  */
116 YAHOO.util.ImageLoader.group.prototype.addTrigger = function(trigEl, trigAct) {
117         if (! trigEl || ! trigAct) {
118                 return;
119         }
120         /* Need to wrap the fetch function. Event Util can't distinguish prototyped functions of different instantiations
121          *   Leads to this scenario: groupA and groupZ both have window-scroll triggers. groupZ also has a 2-sec timeout (groupA has no timeout).
122          *   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. 
123          *   groupA's trigger is removed and never fires, leaving images unfetched
124          */
125         var wrappedFetch = function() {
126                 this.fetch();
127         };
128         this._triggers.push([trigEl, trigAct, wrappedFetch]);
129         YAHOO.util.Event.addListener(trigEl, trigAct, wrappedFetch, this, true);
130 };
131
132 /**
133  * Adds a custom event trigger to the group.
134  * @method addCustomTrigger
135  * @param {Object} event A YAHOO.util.CustomEvent object
136  */
137 YAHOO.util.ImageLoader.group.prototype.addCustomTrigger = function(event) {
138         // make sure we're dealing with a CustomEvent object
139         if (! event || ! event instanceof YAHOO.util.CustomEvent) {
140                 return;
141         }
142
143         // see comment in addTrigger()
144         var wrappedFetch = function() {
145                 this.fetch();
146         };
147         this._customTriggers.push([event, wrappedFetch]);
148         event.subscribe(wrappedFetch, this, true);
149 };
150
151 /**
152  * Setup to do in the window's onload
153  * Initiates time limit for group; executes the fold check for the images
154  * @method _onloadTasks
155  * @private
156  */
157 YAHOO.util.ImageLoader.group.prototype._onloadTasks = function() {
158         if (this.timeoutLen && typeof(this.timeoutLen) == 'number' && this.timeoutLen > 0) {
159                 this._timeout = setTimeout(this._getFetchTimeout(), this.timeoutLen * 1000);
160         }
161
162         if (this.foldConditional) {
163                 this._foldCheck();
164         }
165 };
166
167 /**
168  * Returns the group's fetch method, with the proper closure, for use with setTimeout
169  * @method _getFetchTimeout
170  * @return {Function}  group's fetch method
171  * @private
172  */
173 YAHOO.util.ImageLoader.group.prototype._getFetchTimeout = function() {
174         var self = this;
175         return function() { self.fetch(); };
176 };
177
178 /**
179  * Registers a background image with the group
180  * @method registerBgImage
181  * @param {String}      domId   HTML DOM id of the image element
182  * @param {String}      url     URL for the image
183  * @return {Object}     bgImgObj that was registered, for modifying any attributes in the object
184  */
185 YAHOO.util.ImageLoader.group.prototype.registerBgImage = function(domId, url) {
186         this._imgObjs[domId] = new YAHOO.util.ImageLoader.bgImgObj(domId, url);
187         return this._imgObjs[domId];
188 };
189 /**
190  * Registers a src image with the group
191  * @method registerSrcImage
192  * @param {String}      domId   HTML DOM id of the image element
193  * @param {String}      url     URL for the image
194  * @param {Int} width   pixel width of the image - defaults to image's natural size
195  * @param {Int} height  pixel height of the image - defaults to image's natural size
196  * @return {Object}     srcImgObj that was registered, for modifying any attributes in the object
197  */
198 YAHOO.util.ImageLoader.group.prototype.registerSrcImage = function(domId, url, width, height) {
199         this._imgObjs[domId] = new YAHOO.util.ImageLoader.srcImgObj(domId, url, width, height);
200         return this._imgObjs[domId];
201 };
202 /**
203  * Registers an alpha-channel-type png background image with the group
204  * @method registerPngBgImage
205  * @param {String}      domId   HTML DOM id of the image element
206  * @param {String}      url     URL for the image
207  * @param {Object}  ailProps The AlphaImageLoader properties to be set for the image
208  *                    Valid properties are 'sizingMethod' and 'enabled'
209  * @return {Object}     pngBgImgObj that was registered, for modifying any attributes in the object
210  */
211 YAHOO.util.ImageLoader.group.prototype.registerPngBgImage = function(domId, url, ailProps) {
212         this._imgObjs[domId] = new YAHOO.util.ImageLoader.pngBgImgObj(domId, url, ailProps);
213         return this._imgObjs[domId];
214 };
215
216 /**
217  * Displays the images in the group
218  * @method fetch
219  */
220 YAHOO.util.ImageLoader.group.prototype.fetch = function() {
221
222         clearTimeout(this._timeout);
223         // remove all listeners
224         for (var i=0, len = this._triggers.length; i < len; i++) {
225                 YAHOO.util.Event.removeListener(this._triggers[i][0], this._triggers[i][1], this._triggers[i][2]);
226         }
227         // remove custom event subscriptions
228         for (var i=0, len = this._customTriggers.length; i < len; i++) {
229                 this._customTriggers[i][0].unsubscribe(this._customTriggers[i][1], this);
230         }
231
232         // fetch whatever we need to by className
233         this._fetchByClass();
234
235         // fetch registered images
236         for (var id in this._imgObjs) {
237                 if (YAHOO.lang.hasOwnProperty(this._imgObjs, id)) {
238                         this._imgObjs[id].fetch();
239                 }
240         }
241 };
242
243 /**
244  * Checks the position of each image in the group. If any part of the image is within the client viewport, shows the image immediately.
245  * @method _foldCheck
246  * @private
247  */
248 YAHOO.util.ImageLoader.group.prototype._foldCheck = function() {
249         var scrollTop = (document.compatMode != 'CSS1Compat') ? document.body.scrollTop : document.documentElement.scrollTop;
250         var viewHeight = YAHOO.util.Dom.getViewportHeight();
251         var hLimit = scrollTop + viewHeight;
252         var scrollLeft = (document.compatMode != 'CSS1Compat') ? document.body.scrollLeft : document.documentElement.scrollLeft;
253         var viewWidth = YAHOO.util.Dom.getViewportWidth();
254         var wLimit = scrollLeft + viewWidth;
255         for (var id in this._imgObjs) {
256                 if (YAHOO.lang.hasOwnProperty(this._imgObjs, id)) {
257                         var elPos = YAHOO.util.Dom.getXY(this._imgObjs[id].domId);
258                         if (elPos[1] < hLimit && elPos[0] < wLimit) {
259                                 this._imgObjs[id].fetch();
260                         }
261                 }
262         }
263         // and by class
264         if (this.className) {
265                 this._classImageEls = YAHOO.util.Dom.getElementsByClassName(this.className);
266                 for (var i=0, len = this._classImageEls.length; i < len; i++) {
267                         var elPos = YAHOO.util.Dom.getXY(this._classImageEls[i]);
268                         if (elPos[1] < hLimit && elPos[0] < wLimit) {
269                                 YAHOO.util.Dom.removeClass(this._classImageEls[i], this.className);
270                         }
271                 }
272         }
273 };
274
275 /**
276  * 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
277  * @method _fetchByClass
278  * @private
279  */
280 YAHOO.util.ImageLoader.group.prototype._fetchByClass = function() {
281         if (! this.className) {
282                 return;
283         }
284
285         // this._classImageEls may have been set during _foldCheck
286         if (this._classImageEls === null) {
287                 this._classImageEls = YAHOO.util.Dom.getElementsByClassName(this.className);
288         }
289         YAHOO.util.Dom.removeClass(this._classImageEls, this.className);
290 };
291
292
293 /**
294  * Base class for image objects to be registered with the groups
295  * @class YAHOO.util.ImageLoader.imgObj
296  * @constructor
297  * @param {String}      domId   HTML DOM id of the image element
298  * @param {String}      url     URL for the image
299  */
300 YAHOO.util.ImageLoader.imgObj = function(domId, url) {
301         /**
302          * HTML DOM id of the image element
303          * @property domId
304          * @type String
305          */
306         this.domId = domId;
307
308         /**
309          * URL for the image
310          * @property url
311          * @type String
312          */
313         this.url = url;
314
315         /**
316          * Pixel width of the image. Will be set as a "width" attribute after the image is fetched.
317          * Detaults to the natural width of the image.
318          * Only appropriate with src images
319          * @property width
320          * @type Int
321          */
322         this.width = null;
323
324         /**
325          * Pixel height of the image. Will be set as a "height" attribute after the image is fetched.
326          * Detaults to the natural height of the image.
327          * Only appropriate with src images
328          * @property height
329          * @type Int
330          */
331         this.height = null;
332
333         /**
334          * Whether the style.visibility should be set to "visible" after the image is fetched.
335          * Used when setting src images as visibility:hidden prior to image fetching
336          * @property setVisible
337          * @type Boolean
338          */
339         this.setVisible = false;
340
341         /**
342          * 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
343          * @property _fetched
344          * @type Boolean
345          * @private
346          */
347         this._fetched = false;
348 };
349
350 /**
351  * Displays the image; puts the URL into the DOM
352  * @method fetch
353  */
354 YAHOO.util.ImageLoader.imgObj.prototype.fetch = function() {
355         if (this._fetched) {
356                 return;
357         }
358         var el = document.getElementById(this.domId);
359         if (! el) {
360                 return;
361         }
362         this._applyUrl(el);
363
364         if (this.setVisible) {
365                 el.style.visibility = 'visible';
366         }
367         if (this.width) {
368                 el.width = this.width;
369         }
370         if (this.height) {
371                 el.height = this.height;
372         }
373         this._fetched = true;
374 };
375
376 /**
377  * Inserts the image URL into the DOM so that the image is displayed.
378  * Must be overridden by child class
379  * @method _applyUrl
380  * @param {Object}      el      HTML DOM element
381  * @private
382  */
383 YAHOO.util.ImageLoader.imgObj.prototype._applyUrl = function(el) {
384 };
385
386 /**
387  * Background image object. A background image is one whose URL is specified by "background-image" in the element's style
388  * @class YAHOO.util.ImageLoader.bgImgObj
389  * @constructor
390  * @extends YAHOO.util.ImageLoader.imgObj
391  * @param {String}      domId   HTML DOM id of the image element
392  * @param {String}      url     URL for the image
393  */
394 YAHOO.util.ImageLoader.bgImgObj = function(domId, url) {
395         YAHOO.util.ImageLoader.bgImgObj.superclass.constructor.call(this, domId, url);
396 };
397
398 YAHOO.lang.extend(YAHOO.util.ImageLoader.bgImgObj, YAHOO.util.ImageLoader.imgObj);
399
400 /**
401  * Inserts the image URL into the DOM so that the image is displayed.
402  * Sets style.backgroundImage
403  * @method _applyUrl
404  * @param {Object}      el      HTML DOM element
405  * @private
406  */
407 YAHOO.util.ImageLoader.bgImgObj.prototype._applyUrl = function(el) {
408         el.style.backgroundImage = "url('" + this.url + "')";
409 };
410
411 /**
412  * Source image object. A source image is one whose URL is specified by a src attribute in the DOM element
413  * @class YAHOO.util.ImageLoader.srcImgObj
414  * @constructor
415  * @extends YAHOO.util.ImageLoader.imgObj
416  * @param {String}      domId   HTML DOM id of the image element
417  * @param {String}      url     URL for the image
418  * @param {Int} width   pixel width of the image - defaults to image's natural size
419  * @param {Int} height  pixel height of the image - defaults to image's natural size
420  */
421 YAHOO.util.ImageLoader.srcImgObj = function(domId, url, width, height) {
422         YAHOO.util.ImageLoader.srcImgObj.superclass.constructor.call(this, domId, url);
423         this.width = width;
424         this.height = height;
425 };
426
427 YAHOO.lang.extend(YAHOO.util.ImageLoader.srcImgObj, YAHOO.util.ImageLoader.imgObj);
428
429 /**
430  * Inserts the image URL into the DOM so that the image is displayed.
431  * Sets src
432  * @method _applyUrl
433  * @param {Object}      el      HTML DOM element
434  * @private
435  */
436 YAHOO.util.ImageLoader.srcImgObj.prototype._applyUrl = function(el) {
437         el.src = this.url;
438 };
439
440 /**
441  * 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
442  * @class YAHOO.util.ImageLoader.pngBgImgObj
443  * @constructor
444  * @extends YAHOO.util.ImageLoader.imgObj
445  * @param {String}      domId   HTML DOM id of the image element
446  * @param {String}      url     URL for the image
447  * @param {Object}  ailProps The AlphaImageLoader properties to be set for the image
448  *                    Valid properties are 'sizingMethod' and 'enabled'
449  */
450 YAHOO.util.ImageLoader.pngBgImgObj = function(domId, url, ailProps) {
451         YAHOO.util.ImageLoader.pngBgImgObj.superclass.constructor.call(this, domId, url);
452
453         /**
454          * AlphaImageLoader properties to be set for the image.
455          * Valid properties are "sizingMethod" and "enabled".
456          * @property props
457          * @type Object
458          */
459         this.props = ailProps || {};
460 };
461
462 YAHOO.lang.extend(YAHOO.util.ImageLoader.pngBgImgObj, YAHOO.util.ImageLoader.imgObj);
463
464 /**
465  * Inserts the image URL into the DOM so that the image is displayed.
466  * If the browser is determined to be IE6 (or older), sets the AlphaImageLoader src; otherwise sets style.backgroundImage
467  * @method _applyUrl
468  * @param {Object}      el      HTML DOM element
469  * @private
470  */
471 YAHOO.util.ImageLoader.pngBgImgObj.prototype._applyUrl = function(el) {
472         if (YAHOO.env.ua.ie && YAHOO.env.ua.ie <= 6) {
473                 var sizingMethod = (YAHOO.lang.isUndefined(this.props.sizingMethod)) ? 'scale' : this.props.sizingMethod;
474                 var enabled = (YAHOO.lang.isUndefined(this.props.enabled)) ? 'true' : this.props.enabled;
475                 el.style.filter = 'progid:DXImageTransform.Microsoft.AlphaImageLoader(src="' + this.url + '", sizingMethod="' + sizingMethod + '", enabled="' + enabled + '")';
476         }
477         else {
478                 el.style.backgroundImage = "url('" + this.url + "')";
479         }
480 };
481 YAHOO.register("imageloader", YAHOO.util.ImageLoader, {version: "2.8.0r4", build: "2449"});