Project

General

Profile

1 2887 anderson
/**
2
  *
3
  *  Copyright 2005 Sabre Airline Solutions
4
  *
5
  *  Licensed under the Apache License, Version 2.0 (the "License"); you may not use this
6
  *  file except in compliance with the License. You may obtain a copy of the License at
7
  *
8
  *         http://www.apache.org/licenses/LICENSE-2.0
9
  *
10
  *  Unless required by applicable law or agreed to in writing, software distributed under the
11
  *  License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
12
  *  either express or implied. See the License for the specific language governing permissions
13
  *  and limitations under the License.
14
  **/
15
16
17
//-------------------- rico.js
18
var Rico = {
19
  Version: '1.1.0',
20
  prototypeVersion: parseFloat(Prototype.Version.split(".")[0] + "." + Prototype.Version.split(".")[1])
21
}
22
23
if((typeof Prototype=='undefined') || Rico.prototypeVersion < 1.3)
24
      throw("Rico requires the Prototype JavaScript framework >= 1.3");
25
26
Rico.ArrayExtensions = new Array();
27
28
if (Object.prototype.extend) {
29
   Rico.ArrayExtensions[ Rico.ArrayExtensions.length ] = Object.prototype.extend;
30
}else{
31
  Object.prototype.extend = function(object) {
32
    return Object.extend.apply(this, [this, object]);
33
  }
34
  Rico.ArrayExtensions[ Rico.ArrayExtensions.length ] = Object.prototype.extend;
35
}
36
37
if (Array.prototype.push) {
38
   Rico.ArrayExtensions[ Rico.ArrayExtensions.length ] = Array.prototype.push;
39
}
40
41
if (!Array.prototype.remove) {
42
   Array.prototype.remove = function(dx) {
43
      if( isNaN(dx) || dx > this.length )
44
         return false;
45
      for( var i=0,n=0; i<this.length; i++ )
46
         if( i != dx )
47
            this[n++]=this[i];
48
      this.length-=1;
49
   };
50
  Rico.ArrayExtensions[ Rico.ArrayExtensions.length ] = Array.prototype.remove;
51
}
52
53
if (!Array.prototype.removeItem) {
54
   Array.prototype.removeItem = function(item) {
55
      for ( var i = 0 ; i < this.length ; i++ )
56
         if ( this[i] == item ) {
57
            this.remove(i);
58
            break;
59
         }
60
   };
61
  Rico.ArrayExtensions[ Rico.ArrayExtensions.length ] = Array.prototype.removeItem;
62
}
63
64
if (!Array.prototype.indices) {
65
   Array.prototype.indices = function() {
66
      var indexArray = new Array();
67
      for ( index in this ) {
68
         var ignoreThis = false;
69
         for ( var i = 0 ; i < Rico.ArrayExtensions.length ; i++ ) {
70
            if ( this[index] == Rico.ArrayExtensions[i] ) {
71
               ignoreThis = true;
72
               break;
73
            }
74
         }
75
         if ( !ignoreThis )
76
            indexArray[ indexArray.length ] = index;
77
      }
78
      return indexArray;
79
   }
80
  Rico.ArrayExtensions[ Rico.ArrayExtensions.length ] = Array.prototype.indices;
81
}
82
83
// Create the loadXML method and xml getter for Mozilla
84
if ( window.DOMParser &&
85
	  window.XMLSerializer &&
86
	  window.Node && Node.prototype && Node.prototype.__defineGetter__ ) {
87
88
   if (!Document.prototype.loadXML) {
89
      Document.prototype.loadXML = function (s) {
90
         var doc2 = (new DOMParser()).parseFromString(s, "text/xml");
91
         while (this.hasChildNodes())
92
            this.removeChild(this.lastChild);
93
94
         for (var i = 0; i < doc2.childNodes.length; i++) {
95
            this.appendChild(this.importNode(doc2.childNodes[i], true));
96
         }
97
      };
98
	}
99
100
	Document.prototype.__defineGetter__( "xml",
101
	   function () {
102
		   return (new XMLSerializer()).serializeToString(this);
103
	   }
104
	 );
105
}
106
107
document.getElementsByTagAndClassName = function(tagName, className) {
108
  if ( tagName == null )
109
     tagName = '*';
110
111
  var children = document.getElementsByTagName(tagName) || document.all;
112
  var elements = new Array();
113
114
  if ( className == null )
115
    return children;
116
117
  for (var i = 0; i < children.length; i++) {
118
    var child = children[i];
119
    var classNames = child.className.split(' ');
120
    for (var j = 0; j < classNames.length; j++) {
121
      if (classNames[j] == className) {
122
        elements.push(child);
123
        break;
124
      }
125
    }
126
  }
127
128
  return elements;
129
}
130
131
132
//-------------------- ricoAccordion.js
133
Rico.Accordion = Class.create();
134
135
Rico.Accordion.prototype = {
136
137
   initialize: function(container, options) {
138
      this.container            = $(container);
139
      this.lastExpandedTab      = null;
140
      this.accordionTabs        = new Array();
141
	  this.clickBeforeActions	= new Array();
142
	  this.clickAfterActions	= new Array();
143
      this.setOptions(options);
144
      this._attachBehaviors();
145
      if(!container) return;
146
147 2890 sgarg
	  //PMA
148
      ///////this.container.style.borderBottom = '1px solid ' + this.options.borderColor;
149 2887 anderson
      // validate onloadShowTab
150
       if (this.options.onLoadShowTab >= this.accordionTabs.length)
151
        this.options.onLoadShowTab = 0;
152
153
      // set the initial visual state...
154
	  //if (!onLoadHideTabs) {
155
		  for ( var i=0 ; i < this.accordionTabs.length ; i++ )
156
		  {
157
			if (i != this.options.onLoadShowTab){
158
			 this.accordionTabs[i].collapse();
159
			 this.accordionTabs[i].content.style.display = 'none';
160
			}
161
		  }
162
	  //}
163
      this.lastExpandedTab = this.accordionTabs[this.options.onLoadShowTab];
164
      if (this.options.panelHeight == 'auto'){
165
          var tabToCheck = (this.options.onloadShowTab === 0)? 1 : 0;
166
          var titleBarSize = parseInt(RicoUtil.getElementsComputedStyle(this.accordionTabs[tabToCheck].titleBar, 'height'));
167
          if (isNaN(titleBarSize))
168
            titleBarSize = this.accordionTabs[tabToCheck].titleBar.offsetHeight;
169
170
          var totalTitleBarSize = this.accordionTabs.length * titleBarSize;
171
          var parentHeight = parseInt(RicoUtil.getElementsComputedStyle(this.container.parentNode, 'height'));
172
          if (isNaN(parentHeight))
173
            parentHeight = this.container.parentNode.offsetHeight;
174
175
          this.options.panelHeight = parentHeight - totalTitleBarSize-2;
176
      }
177
178
      this.lastExpandedTab.content.style.height = this.options.panelHeight + "px";
179
      this.lastExpandedTab.showExpanded();
180
      this.lastExpandedTab.titleBar.style.fontWeight = this.options.expandedFontWeight;
181
182
   },
183
184
   setOptions: function(options) {
185
      this.options = {
186
         expandedBg          : '#63699c',
187
         hoverBg             : '#63699c',
188
         collapsedBg         : '#6b79a5',
189
         expandedTextColor   : '#ffffff',
190
         expandedFontWeight  : 'bold',
191
         hoverTextColor      : '#ffffff',
192
         collapsedTextColor  : '#ced7ef',
193
         collapsedFontWeight : 'normal',
194
         borderColor         : '#1f669b',
195
         panelHeight         : 200,
196
         onHideTab           : null,
197
         onShowTab           : null,
198
         onLoadShowTab       : 0
199
      }
200
      Object.extend(this.options, options || {});
201
   },
202
203
   showTabByIndex: function( anIndex, animate ) {
204
      var doAnimate = arguments.length == 1 ? true : animate;
205
      this.showTab( this.accordionTabs[anIndex], doAnimate );
206
   },
207
208
   showTab: function( accordionTab, animate ) {
209
210
      var doAnimate = arguments.length == 1 ? true : animate;
211
212
      if ( this.options.onHideTab )
213
         this.options.onHideTab(this.lastExpandedTab);
214
215
      this.lastExpandedTab.showCollapsed();
216
      var accordion = this;
217
      var lastExpandedTab = this.lastExpandedTab;
218
219
      this.lastExpandedTab.content.style.height = (this.options.panelHeight - 1) + 'px';
220
      accordionTab.content.style.display = '';
221
222
      accordionTab.titleBar.style.fontWeight = this.options.expandedFontWeight;
223
224
      if ( doAnimate ) {
225
         new Rico.Effect.AccordionSize( this.lastExpandedTab.content,
226
                                   accordionTab.content,
227
                                   1,
228
                                   this.options.panelHeight,
229
                                   100, 10,
230
                                   { complete: function() {accordion.showTabDone(lastExpandedTab)} } );
231
         this.lastExpandedTab = accordionTab;
232
      }
233
      else {
234
         this.lastExpandedTab.content.style.height = "1px";
235
         accordionTab.content.style.height = this.options.panelHeight + "px";
236
         this.lastExpandedTab = accordionTab;
237
         this.showTabDone(lastExpandedTab);
238
      }
239
   },
240
241
   showTabDone: function(collapsedTab) {
242
      collapsedTab.content.style.display = 'none';
243
      this.lastExpandedTab.showExpanded();
244
      if ( this.options.onShowTab )
245
         this.options.onShowTab(this.lastExpandedTab);
246
   },
247
248
   _attachBehaviors: function() {
249
      var panels = this._getDirectChildrenByTag(this.container, 'DIV');
250
      for ( var i = 0 ; i < panels.length ; i++ ) {
251
252
         var tabChildren = this._getDirectChildrenByTag(panels[i],'DIV');
253
         if ( tabChildren.length != 2 )
254
            continue; // unexpected
255
256
         var tabTitleBar   = tabChildren[0];
257
         var tabContentBox = tabChildren[1];
258
         this.accordionTabs.push( new Rico.Accordion.Tab(this,tabTitleBar,tabContentBox) );
259
      }
260
   },
261
262
   _getDirectChildrenByTag: function(e, tagName) {
263
      var kids = new Array();
264
      var allKids = e.childNodes;
265
      for( var i = 0 ; i < allKids.length ; i++ )
266
         if ( allKids[i] && allKids[i].tagName && allKids[i].tagName == tagName )
267
            kids.push(allKids[i]);
268
      return kids;
269
   }
270
271
};
272
273
Rico.Accordion.Tab = Class.create();
274
275
Rico.Accordion.Tab.prototype = {
276
277
   initialize: function(accordion, titleBar, content) {
278
      this.accordion = accordion;
279
      this.titleBar  = titleBar;
280
      this.content   = content;
281
      this._attachBehaviors();
282
   },
283
284
   collapse: function() {
285
      this.showCollapsed();
286
      this.content.style.height = "1px";
287
   },
288
289
   showCollapsed: function() {
290
      this.expanded = false;
291
      this.titleBar.style.backgroundColor = this.accordion.options.collapsedBg;
292
      this.titleBar.style.color           = this.accordion.options.collapsedTextColor;
293
      this.titleBar.style.fontWeight      = this.accordion.options.collapsedFontWeight;
294
      this.content.style.overflow = "hidden";
295
   },
296
297
   showExpanded: function() {
298
      this.expanded = true;
299
      this.titleBar.style.backgroundColor = this.accordion.options.expandedBg;
300
      this.titleBar.style.color           = this.accordion.options.expandedTextColor;
301
      this.content.style.overflow         = "visible";
302
   },
303
304
   titleBarClicked: function(e) {
305
      if ( this.accordion.lastExpandedTab == this )
306
         return;
307
308
309
	  for (var i=0 ; i < this.accordion.clickBeforeActions.length; i++) {
310
		  this.accordion.clickBeforeActions[i](this);
311
	  }
312
313
	  // show the selected tab
314
      this.accordion.showTab(this);
315
316
	  for (i=0 ; i < this.accordion.clickAfterActions.length; i++) {
317
		  this.accordion.clickAfterActions[i](this);
318
	  }
319
   },
320
321
   hover: function(e) {
322
		this.titleBar.style.backgroundColor = this.accordion.options.hoverBg;
323
		this.titleBar.style.color           = this.accordion.options.hoverTextColor;
324
   },
325
326
   unhover: function(e) {
327
      if ( this.expanded ) {
328
         this.titleBar.style.backgroundColor = this.accordion.options.expandedBg;
329
         this.titleBar.style.color           = this.accordion.options.expandedTextColor;
330
      }
331
      else {
332
         this.titleBar.style.backgroundColor = this.accordion.options.collapsedBg;
333
         this.titleBar.style.color           = this.accordion.options.collapsedTextColor;
334
      }
335
   },
336
337
   _attachBehaviors: function() {
338
      this.content.style.border = "1px solid " + this.accordion.options.borderColor;
339
      this.content.style.borderTopWidth    = "0px";
340
      this.content.style.borderBottomWidth = "0px";
341
      this.content.style.margin            = "0px";
342
343
      this.titleBar.onclick     = this.titleBarClicked.bindAsEventListener(this);
344
      this.titleBar.onmouseover = this.hover.bindAsEventListener(this);
345
      this.titleBar.onmouseout  = this.unhover.bindAsEventListener(this);
346
   }
347
348
};
349
350
351
//-------------------- ricoEffects.js
352
353
/**
354
  *  Use the Effect namespace for effects.  If using scriptaculous effects
355
  *  this will already be defined, otherwise we'll just create an empty
356
  *  object for it...
357
 **/
358
if ( window.Effect == undefined )
359
   Rico.Effect = {};
360
361
Rico.Effect.SizeAndPosition = Class.create();
362
Rico.Effect.SizeAndPosition.prototype = {
363
364
   initialize: function(element, x, y, w, h, duration, steps, options) {
365
      this.element = $(element);
366
      this.x = x;
367
      this.y = y;
368
      this.w = w;
369
      this.h = h;
370
      this.duration = duration;
371
      this.steps    = steps;
372
      this.options  = arguments[7] || {};
373
374
      this.sizeAndPosition();
375
   },
376
377
   sizeAndPosition: function() {
378
      if (this.isFinished()) {
379
         if(this.options.complete) this.options.complete(this);
380
         return;
381
      }
382
383
      if (this.timer)
384
         clearTimeout(this.timer);
385
386
      var stepDuration = Math.round(this.duration/this.steps) ;
387
388
      // Get original values: x,y = top left corner;  w,h = width height
389
      var currentX = this.element.offsetLeft;
390
      var currentY = this.element.offsetTop;
391
      var currentW = this.element.offsetWidth;
392
      var currentH = this.element.offsetHeight;
393
394
      // If values not set, or zero, we do not modify them, and take original as final as well
395
      this.x = (this.x) ? this.x : currentX;
396
      this.y = (this.y) ? this.y : currentY;
397
      this.w = (this.w) ? this.w : currentW;
398
      this.h = (this.h) ? this.h : currentH;
399
400
      // how much do we need to modify our values for each step?
401
      var difX = this.steps >  0 ? (this.x - currentX)/this.steps : 0;
402
      var difY = this.steps >  0 ? (this.y - currentY)/this.steps : 0;
403
      var difW = this.steps >  0 ? (this.w - currentW)/this.steps : 0;
404
      var difH = this.steps >  0 ? (this.h - currentH)/this.steps : 0;
405
406
      this.moveBy(difX, difY);
407
      this.resizeBy(difW, difH);
408
409
      this.duration -= stepDuration;
410
      this.steps--;
411
412
      this.timer = setTimeout(this.sizeAndPosition.bind(this), stepDuration);
413
   },
414
415
   isFinished: function() {
416
      return this.steps <= 0;
417
   },
418
419
   moveBy: function( difX, difY ) {
420
      var currentLeft = this.element.offsetLeft;
421
      var currentTop  = this.element.offsetTop;
422
      var intDifX     = parseInt(difX);
423
      var intDifY     = parseInt(difY);
424
425
      var style = this.element.style;
426
      if ( intDifX != 0 )
427
         style.left = (currentLeft + intDifX) + "px";
428
      if ( intDifY != 0 )
429
         style.top  = (currentTop + intDifY) + "px";
430
   },
431
432
   resizeBy: function( difW, difH ) {
433
      var currentWidth  = this.element.offsetWidth;
434
      var currentHeight = this.element.offsetHeight;
435
      var intDifW       = parseInt(difW);
436
      var intDifH       = parseInt(difH);
437
438
      var style = this.element.style;
439
      if ( intDifW != 0 )
440
         style.width   = (currentWidth  + intDifW) + "px";
441
      if ( intDifH != 0 )
442
         style.height  = (currentHeight + intDifH) + "px";
443
   }
444
}
445
446
Rico.Effect.Size = Class.create();
447
Rico.Effect.Size.prototype = {
448
449
   initialize: function(element, w, h, duration, steps, options) {
450
      new Rico.Effect.SizeAndPosition(element, null, null, w, h, duration, steps, options);
451
  }
452
}
453
454
Rico.Effect.Position = Class.create();
455
Rico.Effect.Position.prototype = {
456
457
   initialize: function(element, x, y, duration, steps, options) {
458
      new Rico.Effect.SizeAndPosition(element, x, y, null, null, duration, steps, options);
459
  }
460
}
461
462
Rico.Effect.Round = Class.create();
463
Rico.Effect.Round.prototype = {
464
465
   initialize: function(tagName, className, options) {
466
      var elements = document.getElementsByTagAndClassName(tagName,className);
467
      for ( var i = 0 ; i < elements.length ; i++ )
468
         Rico.Corner.round( elements[i], options );
469
   }
470
};
471
472
Rico.Effect.FadeTo = Class.create();
473
Rico.Effect.FadeTo.prototype = {
474
475
   initialize: function( element, opacity, duration, steps, options) {
476
      this.element  = $(element);
477
      this.opacity  = opacity;
478
      this.duration = duration;
479
      this.steps    = steps;
480
      this.options  = arguments[4] || {};
481
      this.fadeTo();
482
   },
483
484
   fadeTo: function() {
485
      if (this.isFinished()) {
486
         if(this.options.complete) this.options.complete(this);
487
         return;
488
      }
489
490
      if (this.timer)
491
         clearTimeout(this.timer);
492
493
      var stepDuration = Math.round(this.duration/this.steps) ;
494
      var currentOpacity = this.getElementOpacity();
495
      var delta = this.steps > 0 ? (this.opacity - currentOpacity)/this.steps : 0;
496
497
      this.changeOpacityBy(delta);
498
      this.duration -= stepDuration;
499
      this.steps--;
500
501
      this.timer = setTimeout(this.fadeTo.bind(this), stepDuration);
502
   },
503
504
   changeOpacityBy: function(v) {
505
      var currentOpacity = this.getElementOpacity();
506
      var newOpacity = Math.max(0, Math.min(currentOpacity+v, 1));
507
      this.element.ricoOpacity = newOpacity;
508
509
      this.element.style.filter = "alpha(opacity:"+Math.round(newOpacity*100)+")";
510
      this.element.style.opacity = newOpacity; /*//*/;
511
   },
512
513
   isFinished: function() {
514
      return this.steps <= 0;
515
   },
516
517
   getElementOpacity: function() {
518
      if ( this.element.ricoOpacity == undefined ) {
519
         var opacity = RicoUtil.getElementsComputedStyle(this.element, 'opacity');
520
         this.element.ricoOpacity = opacity != undefined ? opacity : 1.0;
521
      }
522
      return parseFloat(this.element.ricoOpacity);
523
   }
524
}
525
526
Rico.Effect.AccordionSize = Class.create();
527
528
Rico.Effect.AccordionSize.prototype = {
529
530
   initialize: function(e1, e2, start, end, duration, steps, options) {
531
      this.e1       = $(e1);
532
      this.e2       = $(e2);
533
      this.start    = start;
534
      this.end      = end;
535
      this.duration = duration;
536
      this.steps    = steps;
537
      this.options  = arguments[6] || {};
538
539
      this.accordionSize();
540
   },
541
542
   accordionSize: function() {
543
544
      if (this.isFinished()) {
545
         // just in case there are round errors or such...
546
         this.e1.style.height = this.start + "px";
547
         this.e2.style.height = this.end + "px";
548
549
         if(this.options.complete)
550
            this.options.complete(this);
551
         return;
552
      }
553
554
      if (this.timer)
555
         clearTimeout(this.timer);
556
557
      var stepDuration = Math.round(this.duration/this.steps) ;
558
559
      var diff = this.steps > 0 ? (parseInt(this.e1.offsetHeight) - this.start)/this.steps : 0;
560
      this.resizeBy(diff);
561
562
      this.duration -= stepDuration;
563
      this.steps--;
564
565
      this.timer = setTimeout(this.accordionSize.bind(this), stepDuration);
566
   },
567
568
   isFinished: function() {
569
      return this.steps <= 0;
570
   },
571
572
   resizeBy: function(diff) {
573
      var h1Height = this.e1.offsetHeight;
574
      var h2Height = this.e2.offsetHeight;
575
      var intDiff = parseInt(diff);
576
      if ( diff != 0 ) {
577
         this.e1.style.height = (h1Height - intDiff) + "px";
578
         this.e2.style.height = (h2Height + intDiff) + "px";
579
      }
580
   }
581
582
};
583
584
585
//-------------------- ricoUtil.js
586
Rico.ArrayExtensions = new Array();
587
588
if (Object.prototype.extend) {
589
   // in prototype.js...
590
   Rico.ArrayExtensions[ Rico.ArrayExtensions.length ] = Object.prototype.extend;
591
}else{
592
  Object.prototype.extend = function(object) {
593
    return Object.extend.apply(this, [this, object]);
594
  }
595
  Rico.ArrayExtensions[ Rico.ArrayExtensions.length ] = Object.prototype.extend;
596
}
597
598
if (Array.prototype.push) {
599
   // in prototype.js...
600
   Rico.ArrayExtensions[ Rico.ArrayExtensions.length ] = Array.prototype.push;
601
}
602
603
if (!Array.prototype.remove) {
604
   Array.prototype.remove = function(dx) {
605
      if( isNaN(dx) || dx > this.length )
606
         return false;
607
      for( var i=0,n=0; i<this.length; i++ )
608
         if( i != dx )
609
            this[n++]=this[i];
610
      this.length-=1;
611
   };
612
  Rico.ArrayExtensions[ Rico.ArrayExtensions.length ] = Array.prototype.remove;
613
}
614
615
if (!Array.prototype.removeItem) {
616
   Array.prototype.removeItem = function(item) {
617
      for ( var i = 0 ; i < this.length ; i++ )
618
         if ( this[i] == item ) {
619
            this.remove(i);
620
            break;
621
         }
622
   };
623
  Rico.ArrayExtensions[ Rico.ArrayExtensions.length ] = Array.prototype.removeItem;
624
}
625
626
if (!Array.prototype.indices) {
627
   Array.prototype.indices = function() {
628
      var indexArray = new Array();
629
      for ( index in this ) {
630
         var ignoreThis = false;
631
         for ( var i = 0 ; i < Rico.ArrayExtensions.length ; i++ ) {
632
            if ( this[index] == Rico.ArrayExtensions[i] ) {
633
               ignoreThis = true;
634
               break;
635
            }
636
         }
637
         if ( !ignoreThis )
638
            indexArray[ indexArray.length ] = index;
639
      }
640
      return indexArray;
641
   }
642
  Rico.ArrayExtensions[ Rico.ArrayExtensions.length ] = Array.prototype.indices;
643
}
644
645
  Rico.ArrayExtensions[ Rico.ArrayExtensions.length ] = Array.prototype.unique;
646
  Rico.ArrayExtensions[ Rico.ArrayExtensions.length ] = Array.prototype.inArray;
647
648
649
// Create the loadXML method and xml getter for Mozilla
650
if ( window.DOMParser &&
651
	  window.XMLSerializer &&
652
	  window.Node && Node.prototype && Node.prototype.__defineGetter__ ) {
653
654
   if (!Document.prototype.loadXML) {
655
      Document.prototype.loadXML = function (s) {
656
         var doc2 = (new DOMParser()).parseFromString(s, "text/xml");
657
         while (this.hasChildNodes())
658
            this.removeChild(this.lastChild);
659
660
         for (var i = 0; i < doc2.childNodes.length; i++) {
661
            this.appendChild(this.importNode(doc2.childNodes[i], true));
662
         }
663
      };
664
	}
665
666
	Document.prototype.__defineGetter__( "xml",
667
	   function () {
668
		   return (new XMLSerializer()).serializeToString(this);
669
	   }
670
	 );
671
}
672
673
document.getElementsByTagAndClassName = function(tagName, className) {
674
  if ( tagName == null )
675
     tagName = '*';
676
677
  var children = document.getElementsByTagName(tagName) || document.all;
678
  var elements = new Array();
679
680
  if ( className == null )
681
    return children;
682
683
  for (var i = 0; i < children.length; i++) {
684
    var child = children[i];
685
    var classNames = child.className.split(' ');
686
    for (var j = 0; j < classNames.length; j++) {
687
      if (classNames[j] == className) {
688
        elements.push(child);
689
        break;
690
      }
691
    }
692
  }
693
694
  return elements;
695
}
696
697
var RicoUtil = {
698
699
   getElementsComputedStyle: function ( htmlElement, cssProperty, mozillaEquivalentCSS) {
700
      if ( arguments.length == 2 )
701
         mozillaEquivalentCSS = cssProperty;
702
703
      var el = $(htmlElement);
704
      if ( el.currentStyle )
705
         return el.currentStyle[cssProperty];
706
      else
707
         return document.defaultView.getComputedStyle(el, null).getPropertyValue(mozillaEquivalentCSS);
708
   },
709
710
   createXmlDocument : function() {
711
      if (document.implementation && document.implementation.createDocument) {
712
         var doc = document.implementation.createDocument("", "", null);
713
714
         if (doc.readyState == null) {
715
            doc.readyState = 1;
716
            doc.addEventListener("load", function () {
717
               doc.readyState = 4;
718
               if (typeof doc.onreadystatechange == "function")
719
                  doc.onreadystatechange();
720
            }, false);
721
         }
722
723
         return doc;
724
      }
725
726
      if (window.ActiveXObject)
727
          return Try.these(
728
            function() { return new ActiveXObject('MSXML2.DomDocument')   },
729
            function() { return new ActiveXObject('Microsoft.DomDocument')},
730
            function() { return new ActiveXObject('MSXML.DomDocument')    },
731
            function() { return new ActiveXObject('MSXML3.DomDocument')   }
732
          ) || false;
733
734
      return null;
735
   },
736
737
   getContentAsString: function( parentNode ) {
738
      return parentNode.xml != undefined ?
739
         this._getContentAsStringIE(parentNode) :
740
         this._getContentAsStringMozilla(parentNode);
741
   },
742
743
  _getContentAsStringIE: function(parentNode) {
744
     var contentStr = "";
745
     for ( var i = 0 ; i < parentNode.childNodes.length ; i++ ) {
746
         var n = parentNode.childNodes[i];
747
         if (n.nodeType == 4) {
748
             contentStr += n.nodeValue;
749
         }
750
         else {
751
           contentStr += n.xml;
752
       }
753
     }
754
     return contentStr;
755
  },
756
757
  _getContentAsStringMozilla: function(parentNode) {
758
     var xmlSerializer = new XMLSerializer();
759
     var contentStr = "";
760
     for ( var i = 0 ; i < parentNode.childNodes.length ; i++ ) {
761
          var n = parentNode.childNodes[i];
762
          if (n.nodeType == 4) { // CDATA node
763
              contentStr += n.nodeValue;
764
          }
765
          else {
766
            contentStr += xmlSerializer.serializeToString(n);
767
        }
768
     }
769
     return contentStr;
770
  },
771
772
   toViewportPosition: function(element) {
773
      return this._toAbsolute(element,true);
774
   },
775
776
   toDocumentPosition: function(element) {
777
      return this._toAbsolute(element,false);
778
   },
779
780
   /**
781
    *  Compute the elements position in terms of the window viewport
782
    *  so that it can be compared to the position of the mouse (dnd)
783
    *  This is additions of all the offsetTop,offsetLeft values up the
784
    *  offsetParent hierarchy, ...taking into account any scrollTop,
785
    *  scrollLeft values along the way...
786
    *
787
    * IE has a bug reporting a correct offsetLeft of elements within a
788
    * a relatively positioned parent!!!
789
    **/
790
   _toAbsolute: function(element,accountForDocScroll) {
791
792
      if ( navigator.userAgent.toLowerCase().indexOf("msie") == -1 )
793
         return this._toAbsoluteMozilla(element,accountForDocScroll);
794
795
      var x = 0;
796
      var y = 0;
797
      var parent = element;
798
      while ( parent ) {
799
800
         var borderXOffset = 0;
801
         var borderYOffset = 0;
802
         if ( parent != element ) {
803
            var borderXOffset = parseInt(this.getElementsComputedStyle(parent, "borderLeftWidth" ));
804
            var borderYOffset = parseInt(this.getElementsComputedStyle(parent, "borderTopWidth" ));
805
            borderXOffset = isNaN(borderXOffset) ? 0 : borderXOffset;
806
            borderYOffset = isNaN(borderYOffset) ? 0 : borderYOffset;
807
         }
808
809
         x += parent.offsetLeft - parent.scrollLeft + borderXOffset;
810
         y += parent.offsetTop - parent.scrollTop + borderYOffset;
811
         parent = parent.offsetParent;
812
      }
813
814
      if ( accountForDocScroll ) {
815
         x -= this.docScrollLeft();
816
         y -= this.docScrollTop();
817
      }
818
819
      return { x:x, y:y };
820
   },
821
822
   /**
823
    *  Mozilla did not report all of the parents up the hierarchy via the
824
    *  offsetParent property that IE did.  So for the calculation of the
825
    *  offsets we use the offsetParent property, but for the calculation of
826
    *  the scrollTop/scrollLeft adjustments we navigate up via the parentNode
827
    *  property instead so as to get the scroll offsets...
828
    *
829
    **/
830
   _toAbsoluteMozilla: function(element,accountForDocScroll) {
831
      var x = 0;
832
      var y = 0;
833
      var parent = element;
834
      while ( parent ) {
835
         x += parent.offsetLeft;
836
         y += parent.offsetTop;
837
         parent = parent.offsetParent;
838
      }
839
840
      parent = element;
841
      while ( parent &&
842
              parent != document.body &&
843
              parent != document.documentElement ) {
844
         if ( parent.scrollLeft  )
845
            x -= parent.scrollLeft;
846
         if ( parent.scrollTop )
847
            y -= parent.scrollTop;
848
         parent = parent.parentNode;
849
      }
850
851
      if ( accountForDocScroll ) {
852
         x -= this.docScrollLeft();
853
         y -= this.docScrollTop();
854
      }
855
856
      return { x:x, y:y };
857
   },
858
859
   docScrollLeft: function() {
860
      if ( window.pageXOffset )
861
         return window.pageXOffset;
862
      else if ( document.documentElement && document.documentElement.scrollLeft )
863
         return document.documentElement.scrollLeft;
864
      else if ( document.body )
865
         return document.body.scrollLeft;
866
      else
867
         return 0;
868
   },
869
870
   docScrollTop: function() {
871
      if ( window.pageYOffset )
872
         return window.pageYOffset;
873
      else if ( document.documentElement && document.documentElement.scrollTop )
874
         return document.documentElement.scrollTop;
875
      else if ( document.body )
876
         return document.body.scrollTop;
877
      else
878
         return 0;
879
   }
880
881
};