adhearsion 0.7.6 → 0.7.7

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