root/trunk/common/DOM.js

Revision 257, 28.4 kB (checked in by ddavis, 2 years ago)

the max function returns undef if any values are undef. I wrapped all values passed to max with finiteInt. This fixes window scroll calculations. BugzID:64047

  • Property svn:keywords set to Id
Line 
1/*
2DOM 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/* Node class */
39
40if( !defined( window.Node ) )
41    Node = {};
42
43try {
44    extend( Node, {
45        ELEMENT_NODE: 1,
46        ATTRIBUTE_NODE: 2,
47        TEXT_NODE: 3,
48        CDATA_SECTION_NODE: 4, 
49        COMMENT_NODE: 8,   
50        DOCUMENT_NODE: 9,
51        DOCUMENT_FRAGMENT_NODE: 11
52    } );
53} catch( e ) {}
54
55
56/* DOM class */
57
58if( !defined( window.DOM ) )
59    DOM = {};
60
61
62extend( DOM, {
63    getElement: function( e ) {
64        return (typeof e == "string" || typeof e == "number") ? document.getElementById( e ) : e;
65    },
66   
67   
68    reload: function( w ) {
69        if( !w || !w.location || !w.location.reload )
70            w = window;
71        w.location.reload( true );
72    },
73
74
75    addEventListener: function( e, en, f, uc ) {
76        try {
77            if( e.addEventListener )
78                e.addEventListener( en, f, uc );
79            else if( e.attachEvent )
80                e.attachEvent( "on" + en, f );
81            else
82                e[ "on" + en ] = f;
83        } catch( e ) {}
84    },
85
86
87    removeEventListener: function( e, en, f, uc ) {
88        try {
89            if( e.removeEventListener )
90                e.removeEventListener( en, f, uc );
91            else if( e.detachEvent )
92                e.detachEvent( "on" + en, f );
93            else
94                e[ "on" + en ] = undefined;
95        } catch( e ) {}
96    },
97   
98   
99    focus: function( e ) {
100        try {
101            e = DOM.getElement( e );
102            e.focus();
103        } catch( e ) {}
104    },
105
106
107    blur: function( e ) {
108        try {
109            e = DOM.getElement( e );
110            e.blur();
111        } catch( e ) {}
112    },
113   
114
115    /* Form Data */
116   
117    /**
118     * Class: <code>DOM</code><br/>
119     * Set any elements in the dialog dom element that correspond to properties of this dialog's
120     * <code>data</code> property to the values of the respective properties in <code>data</code>.
121     * This method also sets a reference (param <code>firstInput</code>) to the first input element in the
122     * form, if it is not set when the method is called.
123     * (See the doc for the method <code>open</code>.
124     * @param element <code>Node</code> A dom element.
125     * @param data <code>Object</code>
126     */
127    setFormData: function( el, d ) {
128        if ( typeof el == "string" || typeof el == "number" )
129            el = DOM.getElement( el );
130        if ( !d )
131            d = {};
132       
133        var es = Array.fromPseudo(
134            el.getElementsByTagName( "input" ),
135            el.getElementsByTagName( "textarea" ),
136            el.getElementsByTagName( "select" )
137        );
138
139        for ( var i = 0; i < es.length; i++ ) {
140            var e = es[ i ];
141            var t = e.getAttribute( "type" );
142            t = t ? t.toLowerCase() : "";
143       
144            var tn = e.tagName.toLowerCase();
145            var v = d[ e.name ];
146            switch( tn ) {
147                case "input":
148                    if ( t == "image" || t == "submit" )
149                        break;
150                   
151                    if ( t == "radio" ) {
152                        if ( d.hasOwnProperty( e.name ) )
153                            e.checked = v == e.value ? true : false;
154                        break;
155                    }
156                   
157                    if ( t == "checkbox" ) {
158                        if ( v instanceof Array )
159                            e.checked = ( v.indexOf( e.value ) != -1 ) ? true : false;
160                        else
161                            e.checked = v == e.value ? true : false;
162                        break;
163                    }
164   
165                case "textarea": // Catches "text" input types too.
166                    if ( d.hasOwnProperty( e.name ) && defined( v ) )
167                        e.value = v;
168                    break;
169   
170                case "select":
171                    for( var j = 0; j < e.options.length; j++ ) {
172                        if ( e.options[ j ].value == v ) {
173                            e.selectedIndex = j;
174                            break;
175                        }
176                    }
177                    break;
178            }
179        }
180    },
181
182   
183    /**
184     * Class: <code>DOM</code><br/>
185     * Get all the form element data, outside of blacklisted elements, and 'stuff' it into the dialog's
186     * <code>data</code> property.
187     * @param element <code>Node</code> A dom element.
188     * @param data <code>Object</code>
189     * @return Object The aggregated form-element data
190     */
191    getFormData: function( el, d ) {
192        if ( typeof el == "string" || typeof el == "number" )
193            el = DOM.getElement( el );
194        if ( !d )
195            d = {};
196
197        var es = Array.fromPseudo(
198            el.getElementsByTagName( "input" ),
199            el.getElementsByTagName( "textarea" ),
200            el.getElementsByTagName( "select" )
201        );
202
203        for ( var i = 0; i < es.length; i++ ) {
204            var e = es[ i ];
205            var t = e.getAttribute( "type" );
206            t = t ? t.toLowerCase() : "";
207       
208            var tn = e.tagName.toLowerCase();
209            switch( tn ) {
210                case "input":
211                    if ( t == "image" || t == "submit" )
212                        break;
213                       
214                    if ( t == "radio" ) {
215                        if ( e.checked )
216                            d[ e.name.cssToJS() ] = e.value;
217                        break;
218   
219                    } else if ( t == "checkbox" ) {
220                        var name = e.name.cssToJS();
221                        var value = ( e.checked ) ? e.value : "";
222                       
223                        if ( d.hasOwnProperty( name ) ) {
224                            /* do conversion into array (based on multiple of same name
225                             * even if we don't add the empty value
226                             */
227                            if ( !( d[ name ] instanceof Array ) ) {
228                                if ( d[ name ] )
229                                    d[ name ] = [ d[ name ] ];
230                                else
231                                    d[ name ] = [];
232                            }
233                           
234                            var pos = d[ name ].indexOf( e.value );
235                            if ( pos != -1 )
236                                d[ name ].splice( pos, 1 );
237                               
238                            if ( value )
239                                d[ name ].push( value );
240                        } else
241                            d[ name ] = value;
242                       
243                        break;
244                    }
245                   
246                case "textarea":
247                    d[ e.name.cssToJS() ] = e.value;
248                    break;
249               
250                case "select":
251                    if ( e.selectedIndex < 0 ) 
252                        d[ e.name.cssToJS() ] = undefined;
253                    else 
254                        d[ e.name.cssToJS() ] = e.options[ e.selectedIndex ].value;
255                    break;                       
256            }
257        }
258
259        return d;
260    },
261
262
263
264    /* style */
265   
266    getComputedStyle: function( e ) {
267        if( e.currentStyle )
268            return e.currentStyle;
269        var style = {};
270        var owner = DOM.getOwnerDocument( e );
271        if( owner && owner.defaultView && owner.defaultView.getComputedStyle ) {           
272            try {
273                style = owner.defaultView.getComputedStyle( e, null );
274            } catch( e ) {}
275        }
276        return style;
277    },
278
279
280    getStyle: function( e, p ) {
281        var s = DOM.getComputedStyle( e );
282        return s[ p ];
283    },
284
285
286    // given a window (or defaulting to current window), returns
287    // object with .x and .y of client's usable area
288    getClientDimensions: function( w ) {
289        w = w || window;
290        var d = {};
291       
292        // most browsers
293        if( w.innerHeight ) {
294            d.x = w.innerWidth;
295            d.y = w.innerHeight;
296            return d;
297        }
298
299        // IE6, strict
300        var de = w.document.documentElement;
301        if( de && de.clientHeight ) {
302            d.x = de.clientWidth;
303            d.y = de.clientHeight;
304            return d;
305        }
306
307        // IE, misc
308        if( document.body ) {
309            d.x = document.body.clientWidth;
310            d.y = document.body.clientHeight;
311            return d;
312        }
313       
314        return undefined;
315    },
316   
317   
318    getDocumentDimensions: function( d ) {
319        d = d || document;
320        if( d.body.scrollHeight > d.body.offsetHeight )
321                return {
322                    width: d.body.scrollWidth,
323                    height: d.body.scrollHeight
324            };
325        else
326                return {
327                    width: d.body.offsetWidth,
328                    height: d.body.offsetHeight
329            };
330    },
331
332
333    getDimensions: function( e ) {
334        if( !e )
335            return undefined;
336
337        var style = DOM.getComputedStyle( e );
338
339        return {
340            offsetLeft: e.offsetLeft,
341            offsetTop: e.offsetTop,
342            offsetWidth: e.offsetWidth,
343            offsetHeight: e.offsetHeight,
344            clientWidth: e.clientWidth,
345            clientHeight: e.clientHeight,
346           
347            offsetRight: e.offsetLeft + e.offsetWidth,
348            offsetBottom: e.offsetTop + e.offsetHeight,
349            clientLeft: finiteInt( style.borderLeftWidth ) + finiteInt( style.paddingLeft ),
350            clientTop: finiteInt( style.borderTopWidth ) + finiteInt( style.paddingTop ),
351            clientRight: e.clientLeft + e.clientWidth,
352            clientBottom: e.clientTop + e.clientHeight,
353           
354            marginLeft: style.marginLeft,
355            marginTop: style.marginTop,
356            marginRight: style.marginRight,
357            marginBottom: style.marginBottom
358        };
359    },
360
361
362    getAbsoluteDimensions: function( e ) {
363        var d = DOM.getDimensions( e );
364        if( !d )
365            return d;
366        d.absoluteLeft = d.offsetLeft;
367        d.absoluteTop = d.offsetTop;
368        d.absoluteRight = d.offsetRight;
369        d.absoluteBottom = d.offsetBottom;
370        var bork = 0;
371        while( e ) {
372            try { // IE 6 sometimes gives an unwarranted error ("htmlfile: Unspecified error").
373                e = e.offsetParent;
374            } catch ( err ) {
375                log( "In DOM.getAbsoluteDimensions: " + err.message ); 
376                if ( ++bork > 25 )
377                    return null;
378            }
379            if( !e )
380                return d;
381            d.absoluteLeft += e.offsetLeft;
382            d.absoluteTop += e.offsetTop;
383            d.absoluteRight += e.offsetLeft;
384            d.absoluteBottom += e.offsetTop;
385        }
386        return d;
387    },
388   
389   
390    getIframeAbsoluteDimensions: function( e ) {
391        var d = DOM.getAbsoluteDimensions( e );
392        if( !d )
393            return d;
394        var iframe = DOM.getOwnerIframe( e );
395        if( !defined( iframe ) )
396            return d;
397       
398        var d2 = DOM.getIframeAbsoluteDimensions( iframe );
399        var scroll = DOM.getWindowScroll( iframe.contentWindow );
400        var left = d2.absoluteLeft - scroll.left;
401        var top = d2.absoluteTop - scroll.top;
402       
403        d.absoluteLeft += left;
404        d.absoluteTop += top;
405        d.absoluteRight += left;
406        d.absoluteBottom += top;
407       
408        return d;
409    },
410   
411   
412    setLeft: function( e, v ) { e.style.left = finiteInt( v ) + "px"; },
413    setTop: function( e, v ) { e.style.top = finiteInt( v ) + "px"; },
414    setRight: function( e, v ) { e.style.right = finiteInt( v ) + "px"; },
415    setBottom: function( e, v ) { e.style.bottom = finiteInt( v ) + "px"; },
416    setWidth: function( e, v ) { e.style.width = max( 0, finiteInt( v ) ) + "px"; },
417    setHeight: function( e, v ) { e.style.height = max( 0, finiteInt( v ) ) + "px"; },
418    setZIndex: function( e, v ) { e.style.zIndex = finiteInt( v ); },
419
420   
421    getWindowScroll: function( w ) {
422        w = w || window;
423        var d = w.document,
424                        de = d.documentElement,
425                        b = d.body;
426       
427        return {
428            left: max( finiteInt( w.pageXOffset ), finiteInt( de.scrollLeft ), finiteInt( b.scrollLeft ), finiteInt( w.scrollX ) ),
429            top: max( finiteInt( w.pageYOffset ), finiteInt( de.scrollTop ), finiteInt( b.scrollTop ), finiteInt( w.scrollY ) )
430        };
431    },
432   
433   
434    getAbsoluteCursorPosition: function( ev ) {
435        ev = ev || window.event;
436        var pos = {
437            x: ev.clientX,
438            y: ev.clientY
439        };
440        /* window scroll is fixed in safari 3; devicePixelRatio is a safari 3 only object */
441        if ( window.devicePixelRatio || !navigator.userAgent.toLowerCase().match(/webkit/) ) {
442            var s = DOM.getWindowScroll( window );
443            pos.x += s.left;
444            pos.y += s.top;
445        }
446        return pos;
447    },
448   
449   
450    invisibleStyle: {
451        display: "block",
452        position: "absolute",
453        left: 0,
454        top: 0,
455        width: 0,
456        height: 0,
457        margin: 0,
458        border: 0,
459        padding: 0,
460        fontSize: "0.1px",
461        lineHeight: 0,
462        opacity: 0,
463        MozOpacity: 0,
464        filter: "alpha(opacity=0)"
465    },
466   
467   
468    makeInvisible: function( e ) {
469        for( var p in this.invisibleStyle )
470            if( this.invisibleStyle.hasOwnProperty( p ) )
471                e.style[ p ] = this.invisibleStyle[ p ];
472    },
473
474
475    /* text and selection related methods */
476   
477    getSelection: function( w, d ) {
478        if ( !w )
479            w = window;
480        return w.getSelection ?
481            w.getSelection() :
482            ( d ? d.selection : w.document.selection )
483    },
484
485
486    mergeTextNodes: function( n ) {
487        var c = 0;
488        while( n ) {
489            if( n.nodeType == Node.TEXT_NODE && n.nextSibling && n.nextSibling.nodeType == Node.TEXT_NODE ) {
490                n.nodeValue += n.nextSibling.nodeValue;
491                n.parentNode.removeChild( n.nextSibling );
492                c++;
493            } else {
494                if( n.firstChild )
495                    c += DOM.mergeTextNodes( n.firstChild );
496                n = n.nextSibling;
497            }
498        }
499        return c;
500    },
501   
502   
503    // XXX delete or make this function work everywhere
504    selectElement: function( e ) {
505        var d = e.ownerDocument; 
506       
507        // internet explorer 
508        if( d.body.createControlRange ) { 
509            var r = d.body.createControlRange(); 
510            r.addElement( e ); 
511            r.select(); 
512        } 
513    }, 
514   
515   
516    /* dom methods */
517   
518    isImmutable: function( n ) {
519        try {
520            if( n.getAttribute( "contenteditable" ) == "false" )
521                return true;
522        } catch( e ) {}
523        return false;
524    },
525   
526   
527    getImmutable: function( n ) {
528        var immutable = null;
529        while( n ) {
530            if( DOM.isImmutable( n ) )
531                immutable = n;
532            n = n.parentNode;
533        }
534        return immutable;
535    },
536
537
538    getOwnerDocument: function( n ) {
539        if( !n )
540            return document;
541        if( n.ownerDocument )
542            return n.ownerDocument;
543        if( n.getElementById )
544            return n;
545        return document;
546    },
547
548
549    getOwnerWindow: function( n ) {
550        if( !n )
551            return window;
552        if( n.parentWindow )
553            return n.parentWindow;
554        var doc = DOM.getOwnerDocument( n );
555        if( doc && doc.defaultView )
556            return doc.defaultView;
557        return window;
558    },
559   
560   
561    getOwnerIframe: function( n ) {
562        if( !n )
563            return undefined;
564        var nw = DOM.getOwnerWindow( n );
565        var nd = DOM.getOwnerDocument( n );
566        var pw = nw.parent || nw.parentWindow;
567        if( !pw )
568            return undefined;
569        var parentDocument = pw.document;
570        var es = parentDocument.getElementsByTagName( "iframe" );
571        //% for( var i = 0; i < es.length; i++ ) {
572        //%     var e = es[ i ];
573        for( var en = new Enumerator( es ); !en.atEnd(); en.moveNext() ) {
574            var e = en.item();
575            try {
576                var d = e.contentDocument || e.contentWindow.document;
577                if( d === nd )
578                    return e;
579            }catch(err) {};
580        }
581        return undefined;
582    },
583
584
585    filterElementsByClassName: function( es, cn ) {
586        var filtered = [];
587        //% for( var i = 0; i < es.length; i++ ) {
588        //%     var e = es[ i ];
589        for( var en = new Enumerator( es ); !en.atEnd(); en.moveNext() ) {
590            var e = en.item();
591            if( DOM.hasClassName( e, cn ) )
592                filtered.push( e );
593        }
594        return filtered;
595    },
596   
597   
598    filterElementsByAttribute: function( es, a ) {
599        if( !es )
600            return [];
601        if( !a )
602            return es;
603        var f = [];
604        //% for( var i = 0; i < es.length; i++ ) {
605        //%     var e = es[ i ];
606        for( var en = new Enumerator( es ); !en.atEnd(); en.moveNext() ) {
607            var e = en.item();
608            if( !e )
609                continue;
610            try {
611                if( e.getAttribute && e.getAttribute( a ) )
612                    f.push( e );
613            } catch( e ) {}
614        }
615        return f;
616    },
617
618
619    filterElementsByTagName: function( es, tn ) {
620        if( tn == "*" )
621            return es;
622        var f = [];
623        tn = tn.toLowerCase();
624        //% for( var i = 0; i < es.length; i++ ) {
625        //%    var e = es[ i ];
626        for( var en = new Enumerator( es ); !en.atEnd(); en.moveNext() ) {
627            var e = en.item();
628            if( e.tagName && e.tagName.toLowerCase() == tn )
629                f.push( e );
630        }
631        return f;
632    },
633
634
635    getElementsByTagAndAttribute: function( r, tn, a ) {
636        if( !r )
637            r = document;
638        var es = r.getElementsByTagName( tn );
639        return DOM.filterElementsByAttribute( es, a );
640    },
641   
642   
643    getElementsByAttribute: function( r, a ) {
644        return DOM.getElementsByTagAndAttribute( r, "*", a );
645    },
646
647
648    getElementsByAttributeAndValue: function( r, a, v ) {
649        var es = DOM.getElementsByTagAndAttribute( r, "*", a );
650        var filtered = [];
651        for ( var i = 0; i < es.length; i++ ) {
652            var e = es[ i ];
653            try {
654                if( e.getAttribute && e.getAttribute( a ) == v ) 
655                    filtered.push( es[ i ] );
656            } catch( e ) {}
657        }
658        return filtered;
659    },
660   
661
662    getElementsByTagAndClassName: function( r, tn, cn ) {
663        if( !r )
664            r = document;
665        var elements = r.getElementsByTagName( tn );
666        return DOM.filterElementsByClassName( elements, cn );
667    },
668
669
670    getElementsByClassName: function( r, cn ) {
671        return DOM.getElementsByTagAndClassName( r, "*", cn );
672    },
673   
674   
675    hasAncestor: function( n, a ) {
676        while( n ) {
677            if( n.parentNode === a )
678                return true;
679            n = n.parentNode;
680        }
681        return false;
682    },
683
684
685    getAncestors: function( n, s ) {
686        if( !n )
687            return [];
688        var as = s ? [ n ] : [];
689        n = n.parentNode;
690        while( n ) {
691            as.push( n );
692            n = n.parentNode;
693        }
694        return as;
695    },
696   
697   
698    getAncestorsByTagName: function( n, tn, s ) {
699        var es = DOM.getAncestors( n, s );
700        return DOM.filterElementsByTagName( es, tn );
701    },
702   
703   
704    getFirstAncestorByTagName: function( n, tn, s ) {
705        return DOM.getAncestorsByTagName( n, tn, s )[ 0 ];
706    },
707
708
709    getAncestorsByClassName: function( n, cn, s ) {
710        var es = DOM.getAncestors( n, s );
711        return DOM.filterElementsByClassName( es, cn );
712    },
713
714
715    getFirstAncestorByClassName: function( n, cn, s ) {
716        return DOM.getAncestorsByClassName( n, cn, s )[ 0 ];
717    },
718
719
720    getAncestorsByTagAndClassName: function( n, tn, cn, s ) {
721        var es = DOM.getAncestorsByTagName( n, tn, s );
722        return DOM.filterElementsByClassName( es, cn );
723    },
724
725
726    getFirstAncestorByTagAndClassName: function( n, tn, cn, s ) {
727        return DOM.getAncestorsByTagAndClassName( n, tn, cn, s )[ 0 ];
728    },
729
730
731    getAncestorsByAttribute: function( n, a, s ) {
732        var es = DOM.getAncestors( n, s );
733        return DOM.filterElementsByAttribute( es, a );
734    },
735
736
737    getFirstAncestorByAttribute: function( n, a, s ) {
738        return DOM.getAncestorsByAttribute( n, a, s )[ 0 ];
739    },
740
741
742    getPreviousElement: function( n, t ) {
743        if ( !t )
744            t = Node.ELEMENT_NODE;
745        n = n.previousSibling;
746        while( n ) {
747            if( n.nodeType == Node.ELEMENT_NODE )
748                return n;
749            n = n.previousSibling;
750        }
751        return null;
752    },
753
754
755    getNextElement: function( n, t ) {
756        if ( !t )
757            t = Node.ELEMENT_NODE;
758        n = n.nextSibling;
759        while( n ) {
760            if( n.nodeType == t )
761                return n;
762            n = n.nextSibling;
763        }
764        return null;
765    },
766
767
768    isInlineNode: function( n ) {
769        // text nodes are inline
770        if( n.nodeType == Node.TEXT_NODE )
771            return n;
772
773        // document nodes are non-inline
774        if( n.nodeType == Node.DOCUMENT_NODE )
775            return false;
776
777        // all nonelement nodes are inline
778        if( n.nodeType != Node.ELEMENT_NODE )
779            return n;
780
781        // br elements are not inline
782        if( n.tagName && n.tagName.toLowerCase() == "br" )
783            return false;
784
785        // examine the style property of the inline n
786        var display = DOM.getStyle( n, "display" ); 
787        if( display && display.indexOf( "inline" ) >= 0 ) 
788            return n;
789    },
790   
791   
792    isTextNode: function( n ) {
793        if( n.nodeType == Node.TEXT_NODE )
794            return n;
795    },
796   
797   
798    isInlineTextNode: function( n ) {
799        if( n.nodeType == Node.TEXT_NODE )
800            return n;
801        if( !DOM.isInlineNode( n ) )
802            return null;
803    },
804
805
806    /* this and the following classname functions honor w3c case-sensitive classnames */
807
808    getClassNames: function( e ) {
809        if( !e || !e.className )
810            return [];
811        return e.className.split( /\s+/g );
812    },
813
814
815    hasClassName: function( e, cn ) {
816        e = DOM.getElement( e );
817        if( !e || !e.className )
818            return false;
819        var cs = DOM.getClassNames( e );
820        for( var i = 0; i < cs.length; i++ ) {
821            if( cs[ i ] == cn )
822                return true;
823        }
824        return false;
825    },
826
827
828    addClassName: function( e, cn ) {
829        e = DOM.getElement( e );
830        if( !e || !cn )
831            return false;
832        var cs = DOM.getClassNames( e );
833        for( var i = 0; i < cs.length; i++ ) {
834            if( cs[ i ] == cn )
835                return true;
836        }
837        cs.push( cn );
838        e.className = cs.join( " " );
839        return false;
840    },
841
842
843    removeClassName: function( e, cn ) {
844        var r = false;
845        e = DOM.getElement( e );
846        if( !e || !e.className || !cn )
847            return r;
848        var cs = (e.className && e.className.length)
849            ? e.className.split( /\s+/g )
850            : [];
851        var ncs = [];
852        /* support regex */
853        if( cn instanceof RegExp ) {
854            for( var i = 0; i < cs.length; i++ ) {
855                if ( cn.test( cs[ i ] ) ) {
856                    r = true;
857                    continue;
858                }
859                ncs.push( cs[ i ] );
860            }
861        } else {
862            for( var i = 0; i < cs.length; i++ ) {
863                if( cs[ i ] == cn ) {
864                    r = true;
865                    continue;
866                }
867                ncs.push( cs[ i ] );
868            }
869        }
870        if( r )
871            e.className = ncs.join( " " );
872        return r;
873    },
874   
875   
876    /* tree manipulation methods */
877   
878    replaceWithChildNodes: function( n ) {
879        var firstChild = n.firstChild;
880        var parentNode = n.parentNode;
881        while( n.firstChild )
882            parentNode.insertBefore( n.removeChild( n.firstChild ), n );
883        parentNode.removeChild( n );
884        return firstChild;
885    },
886   
887   
888    replaceWithHTML: function( n, h ) {
889        var d = DOM.getOwnerDocument( n );
890        var e = d.createElement( "div" );
891        e.innerHTML = h;
892        var parentNode = n.parentNode;
893        var nextSibling = n.nextSibling;
894        parentNode.replaceChild( e.removeChild( e.firstChild ), n );
895        return;
896        while( e.firstChild )
897            parentNode.insertBefore( e.removeChild( e.firstChild ), nextSibling );
898    },
899   
900   
901    /* eolas patent */
902   
903    activateEmbeds: function( doc ) {
904        if( !defined( window.clipboardData ) )
905            return;
906        if( !doc ) 
907            doc = document;
908        var es = doc.getElementsByTagName( "embed" );
909        for ( var j = 0; j < es.length; j++ )
910           es[ j ].parentElement.innerHTML = es[ j ].parentElement.innerHTML;           
911    },
912   
913   
914    /* factory methods */
915   
916    createInvisibleInput: function( d ) {
917        if( !d )
918            d = window.document;
919        var e = document.createElement( "input" );
920        e.setAttribute( "autocomplete", "off" );
921        e.autocomplete = "off";
922        DOM.makeInvisible( e );
923        return e;
924    },
925
926   
927    /* attribute manipulation */
928   
929    getMouseEventAttribute: function( ev, a ) {
930        if( !a )
931            return;
932        var es = DOM.getAncestors( ev.target, true );
933        //% for( var i = 0; i < es.length; i++ ) {
934        //%     var e = es[ i ];
935        for( var en = new Enumerator( es ); !en.atEnd(); en.moveNext() ) {
936            var e = en.item();
937            try {
938                var v = e.getAttribute ? e.getAttribute( a ) : null;
939                if( v ) {
940                    ev.attributeElement = e;
941                    ev.attribute = v;
942                    return v;
943                }
944            } catch( e ) {}
945        }
946    },
947   
948
949    setElementAttribute: function( e, a, v ) {
950        /* safari workaround
951         * safari's setAttribute assumes you want to use a namespace
952         * when you have a colon in your attribute
953         */
954        if ( navigator.userAgent.toLowerCase().match(/webkit/) ) {
955            var at = e.attributes;
956            for ( var i = 0; i < at.length; i++ )
957                if ( at[ i ].name == a )
958                    return at[ i ].nodeValue = v;
959
960            /* fallback to setAttribute */
961        }
962       
963        e.setAttribute( a, v );
964    },
965
966
967    swapAttributes: function( e, tg, at ) {
968        var ar = e.getAttribute( tg );
969        if( !ar )
970            return false;
971       
972        /* clone the node with all children */
973        if ( e.tagName.toLowerCase() == 'script' ) {
974            /* only clone and replace script tags */
975            var cl = e.cloneNode( true );
976            if ( !cl )
977                return false;
978
979            DOM.setElementAttribute( cl, at, ar );
980            cl.removeAttribute( tg );
981       
982            /* replace new, old */
983            return e.parentNode.replaceChild( cl, e );
984        } else {
985            DOM.setElementAttribute( e, at, ar );
986            e.removeAttribute( tg );
987        }
988    }
989} );
990
991
992extend( DOM, {
993    _gE: DOM.getElement,
994    _aCN: DOM.addClassName,
995    _rCN: DOM.removeClassName
996} );
997
998
999$ = DOM.getElement;
Note: See TracBrowser for help on using the browser.