root/trunk/common/Core.js

Revision 251, 23.5 kB (checked in by ydnar, 2 years ago)

bugid:63155; short aliases for common functions

  • Property svn:keywords set to Id
Line 
1/*
2Core JavaScript Library
3$Id$
4
5Copyright (c) 2005, Six Apart, Ltd.
6All rights reserved.
7
8Redistribution and use in source and binary forms, with or without
9modification, are permitted provided that the following conditions are
10met:
11
12    * Redistributions of source code must retain the above copyright
13notice, this list of conditions and the following disclaimer.
14
15    * Redistributions in binary form must reproduce the above
16copyright notice, this list of conditions and the following disclaimer
17in the documentation and/or other materials provided with the
18distribution.
19
20    * Neither the name of "Six Apart" nor the names of its
21contributors may be used to endorse or promote products derived from
22this software without specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
25"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
26LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
27A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
28OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
29SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
30LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
31DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
32THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
33(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
34OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
35*/
36
37
38/* utility functions */
39
40defined = function( x ) {
41    return x !== undefined;
42};
43
44
45exists = function( x ) {
46    return (x === undefined || x === null) ? false : true;
47};
48
49
50truth = function( x ) {
51    return (x && x != "0") ? true : false; /* because "0" evaluates to true in javascript */
52};
53
54
55finite = function( x ) {
56    return isFinite( x ) ? x : 0;
57};
58
59
60finiteInt = function( x, b ) {
61    return finite( parseInt( x, b ) );
62};
63
64
65finiteFloat = function( x ) {
66    return finite( parseFloat( x ) );
67};
68
69
70max = function() {
71    var a = arguments;
72    var n = a[ 0 ];
73    for( var i = 1; i < a.length; i++ )
74        if( a[ i ] > n )
75            n = a[ i ];
76    return n;
77};
78
79
80min = function() {
81    var a = arguments;
82    var n = a[ 0 ];
83    for( var i = 1; i < a.length; i++ )
84        if( a[ i ] < n )
85            n = a[ i ];
86    return n;
87};
88
89
90extend = function( o ) {
91    var a = arguments;
92    for( var i = 1; i < a.length; i++ ) {
93        var s = a[ i ];
94        for( var p in s ) {
95            try {
96                if( !o[ p ] && (!s.hasOwnProperty || s.hasOwnProperty( p )) )
97                    o[ p ] = s[ p ];
98            } catch( e ) {}
99        }
100    }
101    return o;
102};
103
104
105override = function( o ) {
106    var a = arguments;
107    for( var i = 1; i < a.length; i++ ) {
108        var s = a[ i ];
109        for( var p in s ) {
110            try {
111                if( !s.hasOwnProperty || s.hasOwnProperty( p ) )
112                    o[ p ] = s[ p ];
113            } catch( e ) {}
114        }
115    }
116    return o;
117};
118
119
120/* logging */
121
122log = function() {};
123log.error = log.warn = log.debug = log;
124
125
126/* try block */ 
127 
128Try = {
129    these: function() {
130        var a = arguments;
131        for( var i = 0; i < a.length; i++ ) {
132            try {
133                return a[ i ]();
134            } catch( e ) {}
135        }
136        return undefined;
137    }
138};
139
140
141/* unique id generator */
142
143Unique = {
144    length: 0,
145   
146    id: function() {
147        return ++this.length;
148    }
149};
150
151
152/* event methods */
153
154if( !defined( window.Event ) )
155    Event = {};
156
157
158Event.stop = function( ev ) {
159    ev = ev || this;
160    if( ev === Event )
161        ev = window.event;
162
163    // w3c
164    if( ev.preventDefault )
165        ev.preventDefault();
166    if( ev.stopPropagation )
167        ev.stopPropagation();
168
169    // ie
170    try {
171        ev.cancelBubble = true;
172        ev.returnValue = false;
173    } catch( e ) {}
174
175    return false;
176};
177
178
179Event.prep = function( ev ) {
180    ev = ev || window.event;
181    if( !defined( ev.stop ) )
182        ev.stop = this.stop;
183    if( !defined( ev.target ) )
184        ev.target = ev.srcElement;
185    if( !defined( ev.relatedTarget ) ) {
186        ev.relatedTarget = (event.type == "mouseover" || event.type == "mouseenter")
187            ? ev.fromElement
188            : ev.toElement;
189    }
190    return ev;
191};
192
193
194try { Event.prototype.stop = Event.stop; }
195catch( e ) {}
196
197
198/* object extensions */
199
200Function.stub = function() {};
201
202
203/* function extensions */
204
205extend( Function.prototype, {
206    bind: function( o ) {
207        var m = this;
208        return function() {
209            return m.apply( o, arguments );
210        };
211    },
212   
213   
214    bindEventListener: function( o ) {
215        var m = this; // Use double closure to work around IE 6 memory leak.
216        return function( e ) {
217            try {
218                event = Event.prep( e );
219            } catch( e ) {}
220            return m.call( o, e );
221        };
222    },
223   
224   
225    applySuper: function( o, args ) {
226        return this.__super.apply( o, args || [] );
227    },
228   
229   
230    callSuper: function( o ) {
231        var args = [];
232        for( var i = 1; i < arguments.length; i++ )
233            args.push( arguments[ i ] );
234        return this.__super.apply( o, args );
235    }
236} );
237
238
239/* class helpers */
240
241indirectObjects = [];
242__SUBCLASS__ = { __SUBCLASS__: "__SUBCLASS__" };
243
244
245Class = function( sc ) {
246    var c = function( s ) {
247        this.constructor = arguments.callee;
248        if( s === __SUBCLASS__ )
249            return;
250        this.init.apply( this, arguments );
251    };
252   
253    override( c, Class );
254    sc = sc || Object;
255    override( c, sc );
256    c.__super = sc;
257    c.superClass = sc.prototype;
258   
259    c.prototype = sc === Object ? new sc() : new sc( __SUBCLASS__ );
260    extend( c.prototype, Class.prototype );
261    var a = arguments;
262    for( var i = 1; i < a.length; i++ )
263        override( c.prototype, a[ i ] );
264    c.prototype.constructor = sc; /* the above override could blow this away */
265   
266    for( var p in c.prototype ) {
267        var m = c.prototype[ p ];
268        if( typeof m != "function" || defined( m.__super ) )
269            continue;
270        m.__super = null;
271        var pr = c.prototype;
272        while( pr && !m.__super ) {
273            if( pr === pr.constructor.prototype )
274                break;
275            pr = pr.constructor.prototype;
276            var s = pr[ p ];
277            if( defined( s ) && typeof s == "function" )
278                m.__super = s;
279        }
280    }
281   
282    return c;
283};
284
285
286extend( Class, {
287    initSingleton: function() {
288        if( this.singleton )
289            return this.singleton;
290        var c = this.singletonConstructor || this;
291        this.singleton = new c();
292        return this.singleton;
293    }
294} );
295
296
297Class.prototype = {
298    init: function() {},
299   
300   
301    destroy: function() {
302        try {
303            if( this.indirectIndex )
304                indirectObjects[ this.indirectIndex ] = undefined;
305            delete this.indirectIndex;
306        } catch( e ) {}
307       
308        for( var property in this ) {
309            try {
310                if( this.hasOwnProperty( property ) )
311                    delete this[ property ];
312            } catch( e ) {}
313        }
314    },
315   
316   
317    getBoundMethod: function( mn ) {
318        return this[ mn ].bind( this );
319    },
320   
321   
322    getEventListener: function( mn ) {
323        return this[ mn ].bindEventListener( this );
324    },
325   
326   
327    getIndirectIndex: function() {
328        if( !defined( this.indirectIndex ) ) {
329            this.indirectIndex = indirectObjects.length;
330            indirectObjects.push( this );
331        }
332        return this.indirectIndex;
333    },
334   
335   
336    getIndirectMethod: function( mn ) {
337        if( !this.indirectMethods )
338            this.indirectMethods = {};
339        var m = this[ mn ];
340        if( typeof m != "function" )
341            return undefined;
342        var indirectIndex = this.getIndirectIndex();
343        if( !this.indirectMethods[ mn ] ) {
344            this.indirectMethods[ mn ] = new Function(
345                "if ( !window.indirectObjects ) return; " +
346                "var o = indirectObjects[" + indirectIndex + "];" +
347                "return o['" + mn + "'].apply( o, arguments );"
348            );
349        }
350        return this.indirectMethods[ mn ];
351    },
352   
353   
354    getIndirectEventListener: function( mn ) {
355        if( !this.indirectEventListeners )
356            this.indirectEventListeners = {};
357        var m = this[ mn ];
358        if( typeof m != "function" )
359            return undefined;
360        var indirectIndex = this.getIndirectIndex();
361        if( !this.indirectEventListeners[ mn ] ) {
362            this.indirectEventListeners[ mn ] = new Function( "event",
363                "try { event = Event.prep( event ); } catch( e ) {}" +
364                "if ( !window.indirectObjects ) return; " +
365                "var o = indirectObjects[" + indirectIndex + "];" +
366                "return o['" + mn + "'].call( o, event );"
367            );
368        }
369        return this.indirectEventListeners[ mn ];
370    }
371};
372
373
374extend( Class.prototype, {
375    _gGM: Class.prototype.getBoundMethod,
376    _gEL: Class.prototype.getEventListener,
377    _gII: Class.prototype.getIndirectIndex,
378    _gIM: Class.prototype.getIndirectMethod,
379    _gIEL: Class.prototype.getIndirectEventListener
380} );
381
382
383/* string extensions */
384
385extend( String, {
386    escapeJSChar: function( c ) {
387        // try simple escaping
388        switch( c ) {
389            case "\\": return "\\\\";
390            case "\"": return "\\\"";
391            case "'":  return "\\'";
392            case "\b": return "\\b";
393            case "\f": return "\\f";
394            case "\n": return "\\n";
395            case "\r": return "\\r";
396            case "\t": return "\\t";
397        }
398       
399        // return raw bytes now ... should be UTF-8
400        if( c >= " " )
401            return c;
402       
403        // try \uXXXX escaping, but shouldn't make it for case 1, 2
404        c = c.charCodeAt( 0 ).toString( 16 );
405        switch( c.length ) {
406            case 1: return "\\u000" + c;
407            case 2: return "\\u00" + c;
408            case 3: return "\\u0" + c;
409            case 4: return "\\u" + c;
410        }
411       
412        // should never make it here
413        return "";
414    },
415   
416   
417    encodeEntity: function( c ) {
418        switch( c ) {
419            case "<": return "&lt;";
420            case ">": return "&gt;";
421            case "&": return "&amp;";
422            case '"': return "&quot;";
423            case "'": return "&apos;";
424        }
425        return c;
426    },
427
428
429    decodeEntity: function( c ) {
430        switch( c ) {
431            case "amp": return "&";
432            case "quot": return '"';
433            case "apos": return "'";
434            case "gt": return ">";
435            case "lt": return "<";
436        }
437        var m = c.match( /^#(\d+)$/ );
438        if( m && defined( m[ 1 ] ) )
439            return String.fromCharCode( m[ 1 ] );
440        m = c.match( /^#x([0-9a-f]+)$/i );
441        if(  m && defined( m[ 1 ] ) )
442            return String.fromCharCode( parseInt( hex, m[ 1 ] ) );
443        return c;
444    },
445   
446   
447    encodeQuery: function( o ) {
448        var q = [];
449        var e = encodeURIComponent || escapeURI || escape;
450        for( var p in o )
451            q.push( e( p ) + "=" + e( o[ p ] ) );
452        return q.join( "&" );
453    }
454} );
455
456
457extend( String.prototype, {
458    escapeJS: function() {
459        return this.replace( /([^ -!#-\[\]-~])/g, function( m, c ) { return String.escapeJSChar( c ); } )
460    },
461   
462   
463    encodeHTML: function() {
464        return this.replace( /([<>&"])/g, function( m, c ) { return String.encodeEntity( c ) } ); /* fix syntax highlight: " */
465    },
466
467
468    decodeHTML: function() {
469        return this.replace( /&(.*?);/g, function( m, c ) { return String.decodeEntity( c ) } );
470    },
471   
472   
473    cssToJS: function() {
474        return this.replace( /-([a-z])/g, function( m, c ) { return c.toUpperCase() } );
475    },
476   
477   
478    jsToCSS: function() {
479        return this.replace( /([A-Z])/g, function( m, c ) { return "-" + c.toLowerCase() } );
480    },
481   
482   
483    firstToLowerCase: function() {
484        return this.replace( /^(.)/, function( m, c ) { return c.toLowerCase() } );
485    },
486   
487       
488    rgbToHex: function() {
489        var c = this.match( /(\d+)\D+(\d+)\D+(\d+)/ );
490        if( !c )
491            return undefined;
492        return "#" +
493            finiteInt( c[ 1 ] ).toString( 16 ).pad( 2, "0" ) +
494            finiteInt( c[ 2 ] ).toString( 16 ).pad( 2, "0" ) +
495            finiteInt( c[ 3 ] ).toString( 16 ).pad( 2, "0" );
496    },
497   
498   
499    pad: function( length, padChar ) {
500        var padding = length - this.length;
501        if( padding <= 0 )
502            return this;
503        if( !defined( padChar ) )
504            padChar = " ";
505        var out = [];
506        for( var i = 0; i < padding; i++ )
507            out.push( padChar );
508        out.push( this );
509        return out.join( "" );
510    },
511
512
513    trim: function() {
514        return this.replace( /^\s+|\s+$/g, "" );
515    },
516   
517   
518    interpolate: function( vars ) {
519        return this.replace( /(?!\\)\$\{([^\}]+)\}|(?!\\)\$([a-zA-Z][a-zA-Z0-9_]*)|\\\$/g,
520            function( m, a, b ) {
521                with( vars ) {
522                    if( a )
523                        return eval( "(" + a + ")" );
524                    else if( b )
525                        return eval( "(" + b + ")" );
526                }
527                return "$";
528            } );
529    }
530} );
531
532
533/* extend array object */
534
535extend( Array, { 
536    fromPseudo: function () {
537        var out = [];
538        for ( var j = 0; j < arguments.length; j++ )
539            for ( var i = 0; i < arguments[ j ].length; i++ )
540                out.push( arguments[ j ][ i ] );
541        return out;
542    }
543} );
544
545
546/* extend array object */
547
548extend( Array.prototype, {
549    copy: function() {
550        var out = [];
551        for( var i = 0; i < this.length; i++ )
552            out[ i ] = this[ i ];
553        return out;
554    },
555
556
557    first: function( c, o ) {
558        var l = this.length;
559        for( var i = 0; i < l; i++ ) {
560            var result = o
561                ? c.call( o, this[ i ], i, this )
562                : c( this[ i ], i, this );
563            if( result )
564                return this[ i ];
565        }
566        return null;
567    },
568
569
570    fitIndex: function( i, di ) {
571        if( !exists( i ) )
572            i = di;
573        else if( i < 0 ) {
574            i = this.length + i;
575            if( i < 0 )
576                i = 0;
577        } else if( i >= this.length )
578            i = this.length - 1;
579        return i;
580    },
581
582
583    scramble: function() {
584        for( var i = 0; i < this.length; i++ ) {
585            var j = Math.floor( Math.random() * this.length );
586            var t = this[ i ];
587            this[ i ] = this[ j ];
588            this[ j ] = t;
589        }
590    },
591   
592   
593    add: function() {
594        var a = arguments;
595        for( var i = 0; i < a.length; i++ ) {
596            var j = this.indexOf( a[ i ] );
597            if( j < 0 ) 
598                this.push( arguments[ i ] );
599        }
600        return this.length;
601    },
602       
603   
604    remove: function() {
605        var a = arguments;
606        for( var i = 0; i < a.length; i++ ) {
607            var j = this.indexOf( a[ i ] );
608            if( j >= 0 )
609                this.splice( j, 1 );
610        }
611        return this.length;
612    },
613
614
615    /* javascript 1.5 array methods */
616    /* http://developer-test.mozilla.org/en/docs/Core_JavaScript_1.5_Reference:Objects:Array#Methods */
617
618    every: function( c, o ) {
619        var l = this.length;
620        for( var i = 0; i < l; i++ )
621            if( !(o ? c.call( o, this[ i ], i, this ) : c( this[ i ], i, this )) )
622                return false;
623        return true;
624    },
625
626
627    some: function( c, o ) {
628        var l = this.length;
629        for( var i = 0; i < l; i++ )
630            if( o ? c.call( o, this[ i ], i, this ) : c( this[ i ], i, this ) )
631                return true;
632        return false;
633    },
634
635
636    filter: function( c, o ) {
637        var out = [];
638        var l = this.length;
639        for( var i = 0; i < l; i++ )
640            if( o ? c.call( o, this[ i ], i, this ) : c( this[ i ], i, this ) )
641                out.push( this[ i ] );
642        return out;
643    },
644   
645   
646    forEach: function( c, o ) {
647        var l = this.length;
648        for( var i = 0; i < l; i++ )
649            o ? c.call( o, this[ i ], i, this ) : c( this[ i ], i, this );
650    },
651   
652   
653    indexOf: function( v, fi ) {
654        fi = this.fitIndex( fi, 0 );
655        for( var i = 0; i < this.length; i++ )
656            if( this[ i ] === v )
657                return i;
658        return -1;
659    },
660
661
662    lastIndexOf: function( v, fi ) {
663        fi = this.fitIndex( fi, this.length - 1 );
664        for( var i = fi; i >= 0; i-- )
665            if( this[ i ] == v )
666                return i;
667        return -1;
668    },
669
670
671    /* javascript 1.2 array methods */
672
673    concat: function() {
674        var a = arguments;
675        var o = this.copy();
676        for( i = 0; i < a.length; i++ ) {
677            var b = a[ i ];
678            for( j = 0; j < b.length; j++ )
679                o.push( b[ j ] );
680        }
681        return o;
682    },
683   
684
685    push: function() {
686        var a = arguments;
687        for( var i = 0; i < a.length; i++ )
688            this[ this.length ] = a[ i ];
689        return this.length;     
690    },
691
692
693    pop: function() {
694        if( this.length == 0 )
695            return undefined;
696        var o = this[ this.length - 1 ];
697        this.length--;
698        return o;
699    },
700   
701   
702    unshift: function() {
703        var a = arguments;
704        for( var i = 0; i < a.length; i++ ) {
705            this[ i + a.length ] = this[ i ];
706            this[ i ] = a[ i ];
707        }
708        return this.length;     
709    },
710   
711   
712    shift: function() {
713        if( this.length == 0 )
714            return undefined;
715        var o = this[ 0 ];
716        for( var i = 1; i < this.length; i++ )
717            this[ i - 1 ] = this[ i ];
718        this.length--;
719        return o;
720    }
721} );
722
723
724/* date extensions */
725
726extend( Date, {
727    strings: {
728        localeWeekdays: {},
729        localeShortWeekdays: {},
730        localeMonths: {},
731        localeShortMonths: {}
732    },
733   
734   
735    /*  iso 8601 date format parser
736        this was fun to write...
737        thanks to: http://www.cl.cam.ac.uk/~mgk25/iso-time.html */
738
739    matchISOString: new RegExp(
740        "^([0-9]{4})" +                                                     // year
741        "(?:-(?=0[1-9]|1[0-2])|$)(..)?" +                                   // month
742        "(?:-(?=0[1-9]|[12][0-9]|3[01])|$)([0-9]{2})?" +                    // day of the month
743        "(?:T(?=[01][0-9]|2[0-4])|$)T?([0-9]{2})?" +                        // hours
744        "(?::(?=[0-5][0-9])|\\+|-|Z|$)([0-9]{2})?" +                        // minutes
745        "(?::(?=[0-5][0-9]|60$|60[+|-|Z]|60.0+)|\\+|-|Z|$):?([0-9]{2})?" +  // seconds
746        "(\\.[0-9]+)?" +                                                    // fractional seconds
747        "(Z|\\+[01][0-9]|\\+2[0-4]|-[01][0-9]|-2[0-4])?" +                  // timezone hours
748        ":?([0-5][0-9]|60)?$"                                               // timezone minutes
749    ),
750   
751   
752    fromISOString: function( string ) {
753        var t = this.matchISOString.exec( string );
754        if( !t )
755            return undefined;
756
757        var y = finiteInt( t[ 1 ], 10 );
758        var mo = finiteInt( t[ 2 ], 10 ) - 1;
759        var d = finiteInt( t[ 3 ], 10 );
760        var h = finiteInt( t[ 4 ], 10 );
761        var m = finiteInt( t[ 5 ], 10 );
762        var s = finiteInt( t[ 6 ], 10 );
763        var ms = finiteInt( Math.round( parseFloat( t[ 7 ] ) * 1000 ) );
764        var tzh = finiteInt( t[ 8 ], 10 );
765        var tzm = finiteInt( t[ 9 ], 10 );
766
767        var date = new this( 0 );
768        if( defined( t[ 8 ] ) ) {
769            date.setUTCFullYear( y, mo, d );
770            date.setUTCHours( h, m, s, ms );
771            var o = (tzh * 60 + tzm) * 60000;
772            if( o )
773                date = new this( date - o );
774        } else {
775            date.setFullYear( y, mo, d );
776            date.setHours( h, m, s, ms );
777        }
778
779        return date;
780    }
781} );
782
783
784extend( Date.prototype, {
785    clone: function () {
786        return new Date( this.getTime() );
787    },
788
789
790    getISOTimezoneOffset: function() {
791        var o = -this.getTimezoneOffset();
792        var n = 0;
793        if( o < 0 ) {
794            n = 1;
795            o *= -1;
796        }
797        var h = Math.floor( o / 60 ).toString().pad( 2, "0" );
798        var m = Math.floor( o % 60 ).toString().pad( 2, "0" );
799        return (n ? "-" : "+") + h + ":" + m;
800    },
801
802
803    toISODateString: function() {
804        var y = this.getFullYear();
805        var m = (this.getMonth() + 1).toString().pad( 2, "0" );
806        var d = this.getDate().toString().pad( 2, "0" );
807        return y + "-" + m + "-" + d;
808    },
809
810
811    toUTCISODateString: function() {
812        var y = this.getUTCFullYear();
813        var m = (this.getUTCMonth() + 1).toString().pad( 2, "0" );
814        var d = this.getUTCDate().toString().pad( 2, "0" );
815        return y + "-" + m + "-" + d;
816    },
817
818
819    toISOTimeString: function() {
820        var h = this.getHours().toString().pad( 2, "0" );
821        var m = this.getMinutes().toString().pad( 2, "0" );
822        var s = this.getSeconds().toString().pad( 2, "0" );
823        var ms = this.getMilliseconds().toString().pad( 3, "0" );
824        var tz = this.getISOTimezoneOffset();
825        return h + ":" + m + ":" + s + "." + ms + tz;
826    },
827
828
829    toUTCISOTimeString: function() {
830        var h = this.getUTCHours().toString().pad( 2, "0" );
831        var m = this.getUTCMinutes().toString().pad( 2, "0" );
832        var s = this.getUTCSeconds().toString().pad( 2, "0" );
833        var ms = this.getUTCMilliseconds().toString().pad( 3, "0" );
834        return h + ":" + m + ":" + s + "." + ms + "Z";
835    },
836
837
838    toISOString: function() {
839        return this.toISODateString() + "T" + this.toISOTimeString();
840    },
841
842
843    toUTCISOString: function() {
844        return this.toUTCISODateString() + "T" + this.toUTCISOTimeString();
845    },
846
847   
848    /* day of week, not day of month */
849    getLocaleDayString: function( d ) {
850        if( isNaN(d) )
851            d = this.getDay();
852        return this.constructor.strings.localeWeekdays[ d ];
853    },
854   
855
856    /* day of week, not day of month */
857    getLocaleDayShortString: function( d ) {
858        if( isNaN(d) )
859            d = this.getDay();
860        return this.constructor.strings.localeShortWeekdays[ d ];
861    },
862
863
864    getLocaleMonthString: function( m ) {
865        if( isNaN(m) )
866            m = this.getMonth();
867        return this.constructor.strings.localeMonths[ m ];
868    },
869
870
871    getLocaleMonthShortString: function( m ) {
872        if( isNaN(m) )
873            m = this.getMonth();
874        return this.constructor.strings.localeShortMonths[ m ];
875    }
876} );
877
878
879/* enumerable interface */
880
881if( !defined( window.Enumerator ) ) {
882    window.Enumerator = new Class( Object, {
883        init: function( a ) {
884            this.data = a;
885            this.index = 0;
886        },
887       
888       
889        atEnd: function() {
890            return this.index >= this.data.length ? true : false;
891        },
892       
893       
894        item: function() {
895            return this.atEnd() ? undefined : this.data[ this.index ];
896        },
897       
898       
899        moveFirst: function() {
900            this.index = 0;
901            return this.item();
902        },
903       
904       
905        moveNext: function() {
906            this.index++;
907            return this.item();
908        }
909    } );
910}
911
912
913/* ajax */
914
915if( !defined( window.XMLHttpRequest ) ) {
916    window.XMLHttpRequest = function() {
917        var h = [
918            "Microsoft.XMLHTTP",
919            "MSXML2.XMLHTTP.5.0",
920            "MSXML2.XMLHTTP.4.0",
921            "MSXML2.XMLHTTP.3.0",
922            "MSXML2.XMLHTTP"
923        ];
924       
925        for( var i = 0; i < h.length; i++ ) {
926            try {
927                return new ActiveXObject( h[ i ] );
928            } catch( e ) {}
929        }
930       
931        return undefined;
932    }
933};
Note: See TracBrowser for help on using the browser.