author | Giulio Cesare Solaroli <giulio.cesare@solaroli.it> | 2011-10-03 16:04:12 (UTC) |
---|---|---|
committer | Giulio Cesare Solaroli <giulio.cesare@solaroli.it> | 2011-10-03 16:04:12 (UTC) |
commit | 541bb378ddece2eab135a8066a16994e94436dea (patch) (unidiff) | |
tree | ff160ea3e26f7fe07fcfd401387c5a0232ca715e /frontend/beta/js/YUI/dom.js | |
parent | 1bf431fd3d45cbdf4afa3e12afefe5d24f4d3bc7 (diff) | |
parent | ecad5e895831337216544e81f1a467e0c68c4a6a (diff) | |
download | clipperz-541bb378ddece2eab135a8066a16994e94436dea.zip clipperz-541bb378ddece2eab135a8066a16994e94436dea.tar.gz clipperz-541bb378ddece2eab135a8066a16994e94436dea.tar.bz2 |
Merge pull request #1 from gcsolaroli/master
First version of the restructured repository
-rw-r--r-- | frontend/beta/js/YUI/dom.js | 881 |
1 files changed, 881 insertions, 0 deletions
diff --git a/frontend/beta/js/YUI/dom.js b/frontend/beta/js/YUI/dom.js new file mode 100644 index 0000000..6f04c43 --- a/dev/null +++ b/frontend/beta/js/YUI/dom.js | |||
@@ -0,0 +1,881 @@ | |||
1 | /* | ||
2 | Copyright (c) 2006, Yahoo! Inc. All rights reserved. | ||
3 | Code licensed under the BSD License: | ||
4 | http://developer.yahoo.net/yui/license.txt | ||
5 | version: 0.12.0 | ||
6 | */ | ||
7 | |||
8 | /** | ||
9 | * The dom module provides helper methods for manipulating Dom elements. | ||
10 | * @module dom | ||
11 | * | ||
12 | */ | ||
13 | |||
14 | (function() { | ||
15 | var Y = YAHOO.util, // internal shorthand | ||
16 | getStyle, // for load time browser branching | ||
17 | setStyle, // ditto | ||
18 | id_counter = 0, // for use with generateId | ||
19 | propertyCache = {}; // for faster hyphen converts | ||
20 | |||
21 | // brower detection | ||
22 | var ua = navigator.userAgent.toLowerCase(), | ||
23 | isOpera = (ua.indexOf('opera') > -1), | ||
24 | isSafari = (ua.indexOf('safari') > -1), | ||
25 | isGecko = (!isOpera && !isSafari && ua.indexOf('gecko') > -1), | ||
26 | isIE = (!isOpera && ua.indexOf('msie') > -1); | ||
27 | |||
28 | // regex cache | ||
29 | var patterns = { | ||
30 | HYPHEN: /(-[a-z])/i | ||
31 | }; | ||
32 | |||
33 | |||
34 | var toCamel = function(property) { | ||
35 | if ( !patterns.HYPHEN.test(property) ) { | ||
36 | return property; // no hyphens | ||
37 | } | ||
38 | |||
39 | if (propertyCache[property]) { // already converted | ||
40 | return propertyCache[property]; | ||
41 | } | ||
42 | |||
43 | while( patterns.HYPHEN.exec(property) ) { | ||
44 | property = property.replace(RegExp.$1, | ||
45 | RegExp.$1.substr(1).toUpperCase()); | ||
46 | } | ||
47 | |||
48 | propertyCache[property] = property; | ||
49 | return property; | ||
50 | //return property.replace(/-([a-z])/gi, function(m0, m1) {return m1.toUpperCase()}) // cant use function as 2nd arg yet due to safari bug | ||
51 | }; | ||
52 | |||
53 | // branching at load instead of runtime | ||
54 | if (document.defaultView && document.defaultView.getComputedStyle) { // W3C DOM method | ||
55 | getStyle = function(el, property) { | ||
56 | var value = null; | ||
57 | |||
58 | var computed = document.defaultView.getComputedStyle(el, ''); | ||
59 | if (computed) { // test computed before touching for safari | ||
60 | value = computed[toCamel(property)]; | ||
61 | } | ||
62 | |||
63 | return el.style[property] || value; | ||
64 | }; | ||
65 | } else if (document.documentElement.currentStyle && isIE) { // IE method | ||
66 | getStyle = function(el, property) { | ||
67 | switch( toCamel(property) ) { | ||
68 | case 'opacity' :// IE opacity uses filter | ||
69 | var val = 100; | ||
70 | try { // will error if no DXImageTransform | ||
71 | val = el.filters['DXImageTransform.Microsoft.Alpha'].opacity; | ||
72 | |||
73 | } catch(e) { | ||
74 | try { // make sure its in the document | ||
75 | val = el.filters('alpha').opacity; | ||
76 | } catch(e) { | ||
77 | } | ||
78 | } | ||
79 | return val / 100; | ||
80 | break; | ||
81 | default: | ||
82 | // test currentStyle before touching | ||
83 | var value = el.currentStyle ? el.currentStyle[property] : null; | ||
84 | return ( el.style[property] || value ); | ||
85 | } | ||
86 | }; | ||
87 | } else { // default to inline only | ||
88 | getStyle = function(el, property) { return el.style[property]; }; | ||
89 | } | ||
90 | |||
91 | if (isIE) { | ||
92 | setStyle = function(el, property, val) { | ||
93 | switch (property) { | ||
94 | case 'opacity': | ||
95 | if ( typeof el.style.filter == 'string' ) { // in case not appended | ||
96 | el.style.filter = 'alpha(opacity=' + val * 100 + ')'; | ||
97 | |||
98 | if (!el.currentStyle || !el.currentStyle.hasLayout) { | ||
99 | el.style.zoom = 1; // when no layout or cant tell | ||
100 | } | ||
101 | } | ||
102 | break; | ||
103 | default: | ||
104 | el.style[property] = val; | ||
105 | } | ||
106 | }; | ||
107 | } else { | ||
108 | setStyle = function(el, property, val) { | ||
109 | el.style[property] = val; | ||
110 | }; | ||
111 | } | ||
112 | |||
113 | /** | ||
114 | * Provides helper methods for DOM elements. | ||
115 | * @namespace YAHOO.util | ||
116 | * @class Dom | ||
117 | */ | ||
118 | YAHOO.util.Dom = { | ||
119 | /** | ||
120 | * Returns an HTMLElement reference. | ||
121 | * @method get | ||
122 | * @param {String | HTMLElement |Array} el Accepts a string to use as an ID for getting a DOM reference, an actual DOM reference, or an Array of IDs and/or HTMLElements. | ||
123 | * @return {HTMLElement | Array} A DOM reference to an HTML element or an array of HTMLElements. | ||
124 | */ | ||
125 | get: function(el) { | ||
126 | if (!el) { return null; } // nothing to work with | ||
127 | |||
128 | if (typeof el != 'string' && !(el instanceof Array) ) { // assuming HTMLElement or HTMLCollection, so pass back as is | ||
129 | return el; | ||
130 | } | ||
131 | |||
132 | if (typeof el == 'string') { // ID | ||
133 | return document.getElementById(el); | ||
134 | } | ||
135 | else { // array of ID's and/or elements | ||
136 | var collection = []; | ||
137 | for (var i = 0, len = el.length; i < len; ++i) { | ||
138 | collection[collection.length] = Y.Dom.get(el[i]); | ||
139 | } | ||
140 | |||
141 | return collection; | ||
142 | } | ||
143 | |||
144 | return null; // safety, should never happen | ||
145 | }, | ||
146 | |||
147 | /** | ||
148 | * Normalizes currentStyle and ComputedStyle. | ||
149 | * @method getStyle | ||
150 | * @param {String | HTMLElement |Array} el Accepts a string to use as an ID, an actual DOM reference, or an Array of IDs and/or HTMLElements. | ||
151 | * @param {String} property The style property whose value is returned. | ||
152 | * @return {String | Array} The current value of the style property for the element(s). | ||
153 | */ | ||
154 | getStyle: function(el, property) { | ||
155 | property = toCamel(property); | ||
156 | |||
157 | var f = function(element) { | ||
158 | return getStyle(element, property); | ||
159 | }; | ||
160 | |||
161 | return Y.Dom.batch(el, f, Y.Dom, true); | ||
162 | }, | ||
163 | |||
164 | /** | ||
165 | * Wrapper for setting style properties of HTMLElements. Normalizes "opacity" across modern browsers. | ||
166 | * @method setStyle | ||
167 | * @param {String | HTMLElement | Array} el Accepts a string to use as an ID, an actual DOM reference, or an Array of IDs and/or HTMLElements. | ||
168 | * @param {String} property The style property to be set. | ||
169 | * @param {String} val The value to apply to the given property. | ||
170 | */ | ||
171 | setStyle: function(el, property, val) { | ||
172 | property = toCamel(property); | ||
173 | |||
174 | var f = function(element) { | ||
175 | setStyle(element, property, val); | ||
176 | |||
177 | }; | ||
178 | |||
179 | Y.Dom.batch(el, f, Y.Dom, true); | ||
180 | }, | ||
181 | |||
182 | /** | ||
183 | * Gets the current position of an element based on page coordinates. Element must be part of the DOM tree to have page coordinates (display:none or elements not appended return false). | ||
184 | * @method getXY | ||
185 | * @param {String | HTMLElement | Array} el Accepts a string to use as an ID, an actual DOM reference, or an Array of IDs and/or HTMLElements | ||
186 | * @return {Array} The XY position of the element(s) | ||
187 | */ | ||
188 | getXY: function(el) { | ||
189 | var f = function(el) { | ||
190 | |||
191 | // has to be part of document to have pageXY | ||
192 | if (el.parentNode === null || el.offsetParent === null || | ||
193 | this.getStyle(el, 'display') == 'none') { | ||
194 | return false; | ||
195 | } | ||
196 | |||
197 | var parentNode = null; | ||
198 | var pos = []; | ||
199 | var box; | ||
200 | |||
201 | if (el.getBoundingClientRect) { // IE | ||
202 | box = el.getBoundingClientRect(); | ||
203 | var doc = document; | ||
204 | if ( !this.inDocument(el) && parent.document != document) {// might be in a frame, need to get its scroll | ||
205 | doc = parent.document; | ||
206 | |||
207 | if ( !this.isAncestor(doc.documentElement, el) ) { | ||
208 | return false; | ||
209 | } | ||
210 | |||
211 | } | ||
212 | |||
213 | var scrollTop = Math.max(doc.documentElement.scrollTop, doc.body.scrollTop); | ||
214 | var scrollLeft = Math.max(doc.documentElement.scrollLeft, doc.body.scrollLeft); | ||
215 | |||
216 | return [box.left + scrollLeft, box.top + scrollTop]; | ||
217 | } | ||
218 | else { // safari, opera, & gecko | ||
219 | pos = [el.offsetLeft, el.offsetTop]; | ||
220 | parentNode = el.offsetParent; | ||
221 | if (parentNode != el) { | ||
222 | while (parentNode) { | ||
223 | pos[0] += parentNode.offsetLeft; | ||
224 | pos[1] += parentNode.offsetTop; | ||
225 | parentNode = parentNode.offsetParent; | ||
226 | } | ||
227 | } | ||
228 | if (isSafari && this.getStyle(el, 'position') == 'absolute' ) { // safari doubles in some cases | ||
229 | pos[0] -= document.body.offsetLeft; | ||
230 | pos[1] -= document.body.offsetTop; | ||
231 | } | ||
232 | } | ||
233 | |||
234 | if (el.parentNode) { parentNode = el.parentNode; } | ||
235 | else { parentNode = null; } | ||
236 | |||
237 | while (parentNode && parentNode.tagName.toUpperCase() != 'BODY' && parentNode.tagName.toUpperCase() != 'HTML') | ||
238 | { // account for any scrolled ancestors | ||
239 | if (Y.Dom.getStyle(parentNode, 'display') != 'inline') { // work around opera inline scrollLeft/Top bug | ||
240 | pos[0] -= parentNode.scrollLeft; | ||
241 | pos[1] -= parentNode.scrollTop; | ||
242 | } | ||
243 | |||
244 | if (parentNode.parentNode) { | ||
245 | parentNode = parentNode.parentNode; | ||
246 | } else { parentNode = null; } | ||
247 | } | ||
248 | |||
249 | |||
250 | return pos; | ||
251 | }; | ||
252 | |||
253 | return Y.Dom.batch(el, f, Y.Dom, true); | ||
254 | }, | ||
255 | |||
256 | /** | ||
257 | * Gets the current X position of an element based on page coordinates. The element must be part of the DOM tree to have page coordinates (display:none or elements not appended return false). | ||
258 | * @method getX | ||
259 | * @param {String | HTMLElement | Array} el Accepts a string to use as an ID, an actual DOM reference, or an Array of IDs and/or HTMLElements | ||
260 | * @return {String | Array} The X position of the element(s) | ||
261 | */ | ||
262 | getX: function(el) { | ||
263 | var f = function(el) { | ||
264 | return Y.Dom.getXY(el)[0]; | ||
265 | }; | ||
266 | |||
267 | return Y.Dom.batch(el, f, Y.Dom, true); | ||
268 | }, | ||
269 | |||
270 | /** | ||
271 | * Gets the current Y position of an element based on page coordinates. Element must be part of the DOM tree to have page coordinates (display:none or elements not appended return false). | ||
272 | * @method getY | ||
273 | * @param {String | HTMLElement | Array} el Accepts a string to use as an ID, an actual DOM reference, or an Array of IDs and/or HTMLElements | ||
274 | * @return {String | Array} The Y position of the element(s) | ||
275 | */ | ||
276 | getY: function(el) { | ||
277 | var f = function(el) { | ||
278 | return Y.Dom.getXY(el)[1]; | ||
279 | }; | ||
280 | |||
281 | return Y.Dom.batch(el, f, Y.Dom, true); | ||
282 | }, | ||
283 | |||
284 | /** | ||
285 | * Set the position of an html element in page coordinates, regardless of how the element is positioned. | ||
286 | * The element(s) must be part of the DOM tree to have page coordinates (display:none or elements not appended return false). | ||
287 | * @method setXY | ||
288 | * @param {String | HTMLElement | Array} el Accepts a string to use as an ID, an actual DOM reference, or an Array of IDs and/or HTMLElements | ||
289 | * @param {Array} pos Contains X & Y values for new position (coordinates are page-based) | ||
290 | * @param {Boolean} noRetry By default we try and set the position a second time if the first fails | ||
291 | */ | ||
292 | setXY: function(el, pos, noRetry) { | ||
293 | var f = function(el) { | ||
294 | var style_pos = this.getStyle(el, 'position'); | ||
295 | if (style_pos == 'static') { // default to relative | ||
296 | this.setStyle(el, 'position', 'relative'); | ||
297 | style_pos = 'relative'; | ||
298 | } | ||
299 | |||
300 | var pageXY = this.getXY(el); | ||
301 | if (pageXY === false) { // has to be part of doc to have pageXY | ||
302 | return false; | ||
303 | } | ||
304 | |||
305 | var delta = [ // assuming pixels; if not we will have to retry | ||
306 | parseInt( this.getStyle(el, 'left'), 10 ), | ||
307 | parseInt( this.getStyle(el, 'top'), 10 ) | ||
308 | ]; | ||
309 | |||
310 | if ( isNaN(delta[0]) ) {// in case of 'auto' | ||
311 | delta[0] = (style_pos == 'relative') ? 0 : el.offsetLeft; | ||
312 | } | ||
313 | if ( isNaN(delta[1]) ) { // in case of 'auto' | ||
314 | delta[1] = (style_pos == 'relative') ? 0 : el.offsetTop; | ||
315 | } | ||
316 | |||
317 | if (pos[0] !== null) { el.style.left = pos[0] - pageXY[0] + delta[0] + 'px'; } | ||
318 | if (pos[1] !== null) { el.style.top = pos[1] - pageXY[1] + delta[1] + 'px'; } | ||
319 | |||
320 | var newXY = this.getXY(el); | ||
321 | |||
322 | // if retry is true, try one more time if we miss | ||
323 | if (!noRetry && (newXY[0] != pos[0] || newXY[1] != pos[1]) ) { | ||
324 | this.setXY(el, pos, true); | ||
325 | } | ||
326 | |||
327 | }; | ||
328 | |||
329 | Y.Dom.batch(el, f, Y.Dom, true); | ||
330 | }, | ||
331 | |||
332 | /** | ||
333 | * Set the X position of an html element in page coordinates, regardless of how the element is positioned. | ||
334 | * The element must be part of the DOM tree to have page coordinates (display:none or elements not appended return false). | ||
335 | * @method setX | ||
336 | * @param {String | HTMLElement | Array} el Accepts a string to use as an ID, an actual DOM reference, or an Array of IDs and/or HTMLElements. | ||
337 | * @param {Int} x The value to use as the X coordinate for the element(s). | ||
338 | */ | ||
339 | setX: function(el, x) { | ||
340 | Y.Dom.setXY(el, [x, null]); | ||
341 | }, | ||
342 | |||
343 | /** | ||
344 | * Set the Y position of an html element in page coordinates, regardless of how the element is positioned. | ||
345 | * The element must be part of the DOM tree to have page coordinates (display:none or elements not appended return false). | ||
346 | * @method setY | ||
347 | * @param {String | HTMLElement | Array} el Accepts a string to use as an ID, an actual DOM reference, or an Array of IDs and/or HTMLElements. | ||
348 | * @param {Int} x To use as the Y coordinate for the element(s). | ||
349 | */ | ||
350 | setY: function(el, y) { | ||
351 | Y.Dom.setXY(el, [null, y]); | ||
352 | }, | ||
353 | |||
354 | /** | ||
355 | * Returns the region position of the given element. | ||
356 | * The element must be part of the DOM tree to have a region (display:none or elements not appended return false). | ||
357 | * @method getRegion | ||
358 | * @param {String | HTMLElement | Array} el Accepts a string to use as an ID, an actual DOM reference, or an Array of IDs and/or HTMLElements. | ||
359 | * @return {Region | Array} A Region or array of Region instances containing "top, left, bottom, right" member data. | ||
360 | */ | ||
361 | getRegion: function(el) { | ||
362 | var f = function(el) { | ||
363 | var region = new Y.Region.getRegion(el); | ||
364 | return region; | ||
365 | }; | ||
366 | |||
367 | return Y.Dom.batch(el, f, Y.Dom, true); | ||
368 | }, | ||
369 | |||
370 | /** | ||
371 | * Returns the width of the client (viewport). | ||
372 | * @method getClientWidth | ||
373 | * @deprecated Now using getViewportWidth. This interface left intact for back compat. | ||
374 | * @return {Int} The width of the viewable area of the page. | ||
375 | */ | ||
376 | getClientWidth: function() { | ||
377 | return Y.Dom.getViewportWidth(); | ||
378 | }, | ||
379 | |||
380 | /** | ||
381 | * Returns the height of the client (viewport). | ||
382 | * @method getClientHeight | ||
383 | * @deprecated Now using getViewportHeight. This interface left intact for back compat. | ||
384 | * @return {Int} The height of the viewable area of the page. | ||
385 | */ | ||
386 | getClientHeight: function() { | ||
387 | return Y.Dom.getViewportHeight(); | ||
388 | }, | ||
389 | |||
390 | /** | ||
391 | * Returns a array of HTMLElements with the given class. | ||
392 | * For optimized performance, include a tag and/or root node when possible. | ||
393 | * @method getElementsByClassName | ||
394 | * @param {String} className The class name to match against | ||
395 | * @param {String} tag (optional) The tag name of the elements being collected | ||
396 | * @param {String | HTMLElement} root (optional) The HTMLElement or an ID to use as the starting point | ||
397 | * @return {Array} An array of elements that have the given class name | ||
398 | */ | ||
399 | getElementsByClassName: function(className, tag, root) { | ||
400 | var method = function(el) { return Y.Dom.hasClass(el, className); }; | ||
401 | return Y.Dom.getElementsBy(method, tag, root); | ||
402 | }, | ||
403 | |||
404 | /** | ||
405 | * Determines whether an HTMLElement has the given className. | ||
406 | * @method hasClass | ||
407 | * @param {String | HTMLElement | Array} el The element or collection to test | ||
408 | * @param {String} className the class name to search for | ||
409 | * @return {Boolean | Array} A boolean value or array of boolean values | ||
410 | */ | ||
411 | hasClass: function(el, className) { | ||
412 | var re = new RegExp('(?:^|\\s+)' + className + '(?:\\s+|$)'); | ||
413 | |||
414 | var f = function(el) { | ||
415 | return re.test(el['className']); | ||
416 | }; | ||
417 | |||
418 | return Y.Dom.batch(el, f, Y.Dom, true); | ||
419 | }, | ||
420 | |||
421 | /** | ||
422 | * Adds a class name to a given element or collection of elements. | ||
423 | * @method addClass | ||
424 | * @param {String | HTMLElement | Array} el The element or collection to add the class to | ||
425 | * @param {String} className the class name to add to the class attribute | ||
426 | */ | ||
427 | addClass: function(el, className) { | ||
428 | var f = function(el) { | ||
429 | if (this.hasClass(el, className)) { return; } // already present | ||
430 | |||
431 | |||
432 | el['className'] = [el['className'], className].join(' '); | ||
433 | }; | ||
434 | |||
435 | Y.Dom.batch(el, f, Y.Dom, true); | ||
436 | }, | ||
437 | |||
438 | /** | ||
439 | * Removes a class name from a given element or collection of elements. | ||
440 | * @method removeClass | ||
441 | * @param {String | HTMLElement | Array} el The element or collection to remove the class from | ||
442 | * @param {String} className the class name to remove from the class attribute | ||
443 | */ | ||
444 | removeClass: function(el, className) { | ||
445 | var re = new RegExp('(?:^|\\s+)' + className + '(?:\\s+|$)', 'g'); | ||
446 | |||
447 | var f = function(el) { | ||
448 | if (!this.hasClass(el, className)) { return; } // not present | ||
449 | |||
450 | |||
451 | var c = el['className']; | ||
452 | el['className'] = c.replace(re, ' '); | ||
453 | if ( this.hasClass(el, className) ) { // in case of multiple adjacent | ||
454 | this.removeClass(el, className); | ||
455 | } | ||
456 | |||
457 | }; | ||
458 | |||
459 | Y.Dom.batch(el, f, Y.Dom, true); | ||
460 | }, | ||
461 | |||
462 | /** | ||
463 | * Replace a class with another class for a given element or collection of elements. | ||
464 | * If no oldClassName is present, the newClassName is simply added. | ||
465 | * @method replaceClass | ||
466 | * @param {String | HTMLElement | Array} el The element or collection to remove the class from | ||
467 | * @param {String} oldClassName the class name to be replaced | ||
468 | * @param {String} newClassName the class name that will be replacing the old class name | ||
469 | */ | ||
470 | replaceClass: function(el, oldClassName, newClassName) { | ||
471 | if (oldClassName === newClassName) { // avoid infinite loop | ||
472 | return false; | ||
473 | } | ||
474 | |||
475 | var re = new RegExp('(?:^|\\s+)' + oldClassName + '(?:\\s+|$)', 'g'); | ||
476 | |||
477 | var f = function(el) { | ||
478 | |||
479 | if ( !this.hasClass(el, oldClassName) ) { | ||
480 | this.addClass(el, newClassName); // just add it if nothing to replace | ||
481 | return; // note return | ||
482 | } | ||
483 | |||
484 | el['className'] = el['className'].replace(re, ' ' + newClassName + ' '); | ||
485 | |||
486 | if ( this.hasClass(el, oldClassName) ) { // in case of multiple adjacent | ||
487 | this.replaceClass(el, oldClassName, newClassName); | ||
488 | } | ||
489 | }; | ||
490 | |||
491 | Y.Dom.batch(el, f, Y.Dom, true); | ||
492 | }, | ||
493 | |||
494 | /** | ||
495 | * Generates a unique ID | ||
496 | * @method generateId | ||
497 | * @param {String | HTMLElement | Array} el (optional) An optional element array of elements to add an ID to (no ID is added if one is already present). | ||
498 | * @param {String} prefix (optional) an optional prefix to use (defaults to "yui-gen"). | ||
499 | * @return {String | Array} The generated ID, or array of generated IDs (or original ID if already present on an element) | ||
500 | */ | ||
501 | generateId: function(el, prefix) { | ||
502 | prefix = prefix || 'yui-gen'; | ||
503 | el = el || {}; | ||
504 | |||
505 | var f = function(el) { | ||
506 | if (el) { | ||
507 | el = Y.Dom.get(el); | ||
508 | } else { | ||
509 | el = {}; // just generating ID in this case | ||
510 | } | ||
511 | |||
512 | if (!el.id) { | ||
513 | el.id = prefix + id_counter++; | ||
514 | } // dont override existing | ||
515 | |||
516 | |||
517 | return el.id; | ||
518 | }; | ||
519 | |||
520 | return Y.Dom.batch(el, f, Y.Dom, true); | ||
521 | }, | ||
522 | |||
523 | /** | ||
524 | * Determines whether an HTMLElement is an ancestor of another HTML element in the DOM hierarchy. | ||
525 | * @method isAncestor | ||
526 | * @param {String | HTMLElement} haystack The possible ancestor | ||
527 | * @param {String | HTMLElement} needle The possible descendent | ||
528 | * @return {Boolean} Whether or not the haystack is an ancestor of needle | ||
529 | */ | ||
530 | isAncestor: function(haystack, needle) { | ||
531 | haystack = Y.Dom.get(haystack); | ||
532 | if (!haystack || !needle) { return false; } | ||
533 | |||
534 | var f = function(needle) { | ||
535 | if (haystack.contains && !isSafari) { // safari "contains" is broken | ||
536 | return haystack.contains(needle); | ||
537 | } | ||
538 | else if ( haystack.compareDocumentPosition ) { | ||
539 | return !!(haystack.compareDocumentPosition(needle) & 16); | ||
540 | } | ||
541 | else { // loop up and test each parent | ||
542 | var parent = needle.parentNode; | ||
543 | |||
544 | while (parent) { | ||
545 | if (parent == haystack) { | ||
546 | return true; | ||
547 | } | ||
548 | else if (!parent.tagName || parent.tagName.toUpperCase() == 'HTML') { | ||
549 | return false; | ||
550 | } | ||
551 | |||
552 | parent = parent.parentNode; | ||
553 | } | ||
554 | return false; | ||
555 | } | ||
556 | }; | ||
557 | |||
558 | return Y.Dom.batch(needle, f, Y.Dom, true); | ||
559 | }, | ||
560 | |||
561 | /** | ||
562 | * Determines whether an HTMLElement is present in the current document. | ||
563 | * @method inDocument | ||
564 | * @param {String | HTMLElement} el The element to search for | ||
565 | * @return {Boolean} Whether or not the element is present in the current document | ||
566 | */ | ||
567 | inDocument: function(el) { | ||
568 | var f = function(el) { | ||
569 | return this.isAncestor(document.documentElement, el); | ||
570 | }; | ||
571 | |||
572 | return Y.Dom.batch(el, f, Y.Dom, true); | ||
573 | }, | ||
574 | |||
575 | /** | ||
576 | * Returns a array of HTMLElements that pass the test applied by supplied boolean method. | ||
577 | * For optimized performance, include a tag and/or root node when possible. | ||
578 | * @method getElementsBy | ||
579 | * @param {Function} method - A boolean method for testing elements which receives the element as its only argument. | ||
580 | |||
581 | * @param {String} tag (optional) The tag name of the elements being collected | ||
582 | * @param {String | HTMLElement} root (optional) The HTMLElement or an ID to use as the starting point | ||
583 | */ | ||
584 | getElementsBy: function(method, tag, root) { | ||
585 | tag = tag || '*'; | ||
586 | root = Y.Dom.get(root) || document; | ||
587 | |||
588 | var nodes = []; | ||
589 | var elements = root.getElementsByTagName(tag); | ||
590 | |||
591 | if ( !elements.length && (tag == '*' && root.all) ) { | ||
592 | elements = root.all; // IE < 6 | ||
593 | } | ||
594 | |||
595 | for (var i = 0, len = elements.length; i < len; ++i) { | ||
596 | if ( method(elements[i]) ) { nodes[nodes.length] = elements[i]; } | ||
597 | } | ||
598 | |||
599 | |||
600 | return nodes; | ||
601 | }, | ||
602 | |||
603 | /** | ||
604 | * Returns an array of elements that have had the supplied method applied. | ||
605 | * The method is called with the element(s) as the first arg, and the optional param as the second ( method(el, o) ). | ||
606 | * @method batch | ||
607 | * @param {String | HTMLElement | Array} el (optional) An element or array of elements to apply the method to | ||
608 | * @param {Function} method The method to apply to the element(s) | ||
609 | * @param {Any} o (optional) An optional arg that is passed to the supplied method | ||
610 | * @param {Boolean} override (optional) Whether or not to override the scope of "method" with "o" | ||
611 | * @return {HTMLElement | Array} The element(s) with the method applied | ||
612 | */ | ||
613 | batch: function(el, method, o, override) { | ||
614 | var id = el; | ||
615 | el = Y.Dom.get(el); | ||
616 | |||
617 | var scope = (override) ? o : window; | ||
618 | |||
619 | if (!el || el.tagName || !el.length) { // is null or not a collection (tagName for SELECT and others that can be both an element and a collection) | ||
620 | if (!el) { | ||
621 | return false; | ||
622 | } | ||
623 | return method.call(scope, el, o); | ||
624 | } | ||
625 | |||
626 | var collection = []; | ||
627 | |||
628 | for (var i = 0, len = el.length; i < len; ++i) { | ||
629 | if (!el[i]) { | ||
630 | id = el[i]; | ||
631 | } | ||
632 | collection[collection.length] = method.call(scope, el[i], o); | ||
633 | } | ||
634 | |||
635 | return collection; | ||
636 | }, | ||
637 | |||
638 | /** | ||
639 | * Returns the height of the document. | ||
640 | * @method getDocumentHeight | ||
641 | * @return {Int} The height of the actual document (which includes the body and its margin). | ||
642 | */ | ||
643 | getDocumentHeight: function() { | ||
644 | var scrollHeight = (document.compatMode != 'CSS1Compat') ? document.body.scrollHeight : document.documentElement.scrollHeight; | ||
645 | |||
646 | var h = Math.max(scrollHeight, Y.Dom.getViewportHeight()); | ||
647 | return h; | ||
648 | }, | ||
649 | |||
650 | /** | ||
651 | * Returns the width of the document. | ||
652 | * @method getDocumentWidth | ||
653 | * @return {Int} The width of the actual document (which includes the body and its margin). | ||
654 | */ | ||
655 | getDocumentWidth: function() { | ||
656 | var scrollWidth = (document.compatMode != 'CSS1Compat') ? document.body.scrollWidth : document.documentElement.scrollWidth; | ||
657 | var w = Math.max(scrollWidth, Y.Dom.getViewportWidth()); | ||
658 | return w; | ||
659 | }, | ||
660 | |||
661 | /** | ||
662 | * Returns the current height of the viewport. | ||
663 | * @method getViewportHeight | ||
664 | * @return {Int} The height of the viewable area of the page (excludes scrollbars). | ||
665 | */ | ||
666 | getViewportHeight: function() { | ||
667 | var height = self.innerHeight; // Safari, Opera | ||
668 | var mode = document.compatMode; | ||
669 | |||
670 | if ( (mode || isIE) && !isOpera ) { // IE, Gecko | ||
671 | height = (mode == 'CSS1Compat') ? | ||
672 | document.documentElement.clientHeight : // Standards | ||
673 | document.body.clientHeight; // Quirks | ||
674 | } | ||
675 | |||
676 | return height; | ||
677 | }, | ||
678 | |||
679 | /** | ||
680 | * Returns the current width of the viewport. | ||
681 | * @method getViewportWidth | ||
682 | * @return {Int} The width of the viewable area of the page (excludes scrollbars). | ||
683 | */ | ||
684 | |||
685 | getViewportWidth: function() { | ||
686 | var width = self.innerWidth; // Safari | ||
687 | var mode = document.compatMode; | ||
688 | |||
689 | if (mode || isIE) { // IE, Gecko, Opera | ||
690 | width = (mode == 'CSS1Compat') ? | ||
691 | document.documentElement.clientWidth : // Standards | ||
692 | document.body.clientWidth; // Quirks | ||
693 | } | ||
694 | return width; | ||
695 | } | ||
696 | }; | ||
697 | })(); | ||
698 | /** | ||
699 | * A region is a representation of an object on a grid. It is defined | ||
700 | * by the top, right, bottom, left extents, so is rectangular by default. If | ||
701 | * other shapes are required, this class could be extended to support it. | ||
702 | * @namespace YAHOO.util | ||
703 | * @class Region | ||
704 | * @param {Int} t the top extent | ||
705 | * @param {Int} r the right extent | ||
706 | * @param {Int} b the bottom extent | ||
707 | * @param {Int} l the left extent | ||
708 | * @constructor | ||
709 | */ | ||
710 | YAHOO.util.Region = function(t, r, b, l) { | ||
711 | |||
712 | /** | ||
713 | * The region's top extent | ||
714 | * @property top | ||
715 | * @type Int | ||
716 | */ | ||
717 | this.top = t; | ||
718 | |||
719 | /** | ||
720 | * The region's top extent as index, for symmetry with set/getXY | ||
721 | * @property 1 | ||
722 | * @type Int | ||
723 | */ | ||
724 | this[1] = t; | ||
725 | |||
726 | /** | ||
727 | * The region's right extent | ||
728 | * @property right | ||
729 | * @type int | ||
730 | */ | ||
731 | this.right = r; | ||
732 | |||
733 | /** | ||
734 | * The region's bottom extent | ||
735 | * @property bottom | ||
736 | * @type Int | ||
737 | */ | ||
738 | this.bottom = b; | ||
739 | |||
740 | /** | ||
741 | * The region's left extent | ||
742 | * @property left | ||
743 | * @type Int | ||
744 | */ | ||
745 | this.left = l; | ||
746 | |||
747 | /** | ||
748 | * The region's left extent as index, for symmetry with set/getXY | ||
749 | * @property 0 | ||
750 | * @type Int | ||
751 | */ | ||
752 | this[0] = l; | ||
753 | }; | ||
754 | |||
755 | /** | ||
756 | * Returns true if this region contains the region passed in | ||
757 | * @method contains | ||
758 | * @param {Region} region The region to evaluate | ||
759 | * @return {Boolean} True if the region is contained with this region, | ||
760 | * else false | ||
761 | */ | ||
762 | YAHOO.util.Region.prototype.contains = function(region) { | ||
763 | return ( region.left >= this.left && | ||
764 | region.right <= this.right && | ||
765 | region.top >= this.top && | ||
766 | region.bottom <= this.bottom ); | ||
767 | |||
768 | }; | ||
769 | |||
770 | /** | ||
771 | * Returns the area of the region | ||
772 | * @method getArea | ||
773 | * @return {Int} the region's area | ||
774 | */ | ||
775 | YAHOO.util.Region.prototype.getArea = function() { | ||
776 | return ( (this.bottom - this.top) * (this.right - this.left) ); | ||
777 | }; | ||
778 | |||
779 | /** | ||
780 | * Returns the region where the passed in region overlaps with this one | ||
781 | * @method intersect | ||
782 | * @param {Region} region The region that intersects | ||
783 | * @return {Region} The overlap region, or null if there is no overlap | ||
784 | */ | ||
785 | YAHOO.util.Region.prototype.intersect = function(region) { | ||
786 | var t = Math.max( this.top, region.top ); | ||
787 | var r = Math.min( this.right, region.right ); | ||
788 | var b = Math.min( this.bottom, region.bottom ); | ||
789 | var l = Math.max( this.left, region.left ); | ||
790 | |||
791 | if (b >= t && r >= l) { | ||
792 | return new YAHOO.util.Region(t, r, b, l); | ||
793 | } else { | ||
794 | return null; | ||
795 | } | ||
796 | }; | ||
797 | |||
798 | /** | ||
799 | * Returns the region representing the smallest region that can contain both | ||
800 | * the passed in region and this region. | ||
801 | * @method union | ||
802 | * @param {Region} region The region that to create the union with | ||
803 | * @return {Region} The union region | ||
804 | */ | ||
805 | YAHOO.util.Region.prototype.union = function(region) { | ||
806 | var t = Math.min( this.top, region.top ); | ||
807 | var r = Math.max( this.right, region.right ); | ||
808 | var b = Math.max( this.bottom, region.bottom ); | ||
809 | var l = Math.min( this.left, region.left ); | ||
810 | |||
811 | return new YAHOO.util.Region(t, r, b, l); | ||
812 | }; | ||
813 | |||
814 | /** | ||
815 | * toString | ||
816 | * @method toString | ||
817 | * @return string the region properties | ||
818 | */ | ||
819 | YAHOO.util.Region.prototype.toString = function() { | ||
820 | return ( "Region {" + | ||
821 | "top: " + this.top + | ||
822 | ", right: " + this.right + | ||
823 | ", bottom: " + this.bottom + | ||
824 | ", left: " + this.left + | ||
825 | "}" ); | ||
826 | }; | ||
827 | |||
828 | /** | ||
829 | * Returns a region that is occupied by the DOM element | ||
830 | * @method getRegion | ||
831 | * @param {HTMLElement} el The element | ||
832 | * @return {Region} The region that the element occupies | ||
833 | * @static | ||
834 | */ | ||
835 | YAHOO.util.Region.getRegion = function(el) { | ||
836 | var p = YAHOO.util.Dom.getXY(el); | ||
837 | |||
838 | var t = p[1]; | ||
839 | var r = p[0] + el.offsetWidth; | ||
840 | var b = p[1] + el.offsetHeight; | ||
841 | var l = p[0]; | ||
842 | |||
843 | return new YAHOO.util.Region(t, r, b, l); | ||
844 | }; | ||
845 | |||
846 | ///////////////////////////////////////////////////////////////////////////// | ||
847 | |||
848 | /** | ||
849 | * A point is a region that is special in that it represents a single point on | ||
850 | * the grid. | ||
851 | * @namespace YAHOO.util | ||
852 | * @class Point | ||
853 | * @param {Int} x The X position of the point | ||
854 | * @param {Int} y The Y position of the point | ||
855 | * @constructor | ||
856 | * @extends YAHOO.util.Region | ||
857 | */ | ||
858 | YAHOO.util.Point = function(x, y) { | ||
859 | if (x instanceof Array) { // accept output from Dom.getXY | ||
860 | y = x[1]; | ||
861 | x = x[0]; | ||
862 | } | ||
863 | |||
864 | /** | ||
865 | * The X position of the point, which is also the right, left and index zero (for Dom.getXY symmetry) | ||
866 | * @property x | ||
867 | * @type Int | ||
868 | */ | ||
869 | |||
870 | this.x = this.right = this.left = this[0] = x; | ||
871 | |||
872 | /** | ||
873 | * The Y position of the point, which is also the top, bottom and index one (for Dom.getXY symmetry) | ||
874 | * @property y | ||
875 | * @type Int | ||
876 | */ | ||
877 | this.y = this.top = this.bottom = this[1] = y; | ||
878 | }; | ||
879 | |||
880 | YAHOO.util.Point.prototype = new YAHOO.util.Region(); | ||
881 | |||