PageRenderTime 38ms CodeModel.GetById 18ms app.highlight 16ms RepoModel.GetById 1ms app.codeStats 0ms

/hippo/src/main/webapp/yui/imageloader/imageloader.js

http://hdbc.googlecode.com/
JavaScript | 481 lines | 171 code | 46 blank | 264 comment | 36 complexity | 2d71f67e9892c85aa64290f49f746245 MD5 | raw file
  1/*
  2Copyright (c) 2009, Yahoo! Inc. All rights reserved.
  3Code licensed under the BSD License:
  4http://developer.yahoo.net/yui/license.txt
  5version: 2.7.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.
 11 *
 12 * @module imageloader
 13 * @namespace YAHOO.util
 14 */
 15
 16if (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 */
 30YAHOO.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 */
116YAHOO.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 */
137YAHOO.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 */
157YAHOO.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 */
173YAHOO.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 */
185YAHOO.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 */
198YAHOO.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 */
211YAHOO.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 */
220YAHOO.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 */
248YAHOO.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 */
280YAHOO.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 */
300YAHOO.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 */
354YAHOO.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 */
383YAHOO.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 */
394YAHOO.util.ImageLoader.bgImgObj = function(domId, url) {
395	YAHOO.util.ImageLoader.bgImgObj.superclass.constructor.call(this, domId, url);
396};
397
398YAHOO.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 */
407YAHOO.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 */
421YAHOO.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
427YAHOO.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 */
436YAHOO.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 */
450YAHOO.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
462YAHOO.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 */
471YAHOO.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};
481YAHOO.register("imageloader", YAHOO.util.ImageLoader, {version: "2.7.0", build: "1799"});