Ticket #330: trac-diff-display-switcher-r4282-for-0.10.3.patch

File trac-diff-display-switcher-r4282-for-0.10.3.patch, 59.8 kB (added by gotoh, 2 years ago)

comment:22 のdiff表示切り替え機能のtrac-0.10.3に対する差分

  • a/htdocs/css/diff.css

    old new  
    6969 margin: 0 auto; 
    7070 padding: .1em 0 .25em .5em; 
    7171} 
     72.diff h2 .switch { color: #999; float: right; font-size: 75%; 
     73  line-height: 1.6; 
     74} 
     75.diff h2 .switch span { border-left: 1px solid #ccc; cursor: pointer; 
     76  padding: 0 1em; 
     77} 
     78.diff h2 .switch span:first-child { border: none; } 
     79.diff h2 .switch span.active { color: #333; cursor: default; } 
    7280 
    7381/* Styles for the actual diff tables (side-by-side and inline) */ 
    7482.diff table { 
     
    161169.diff table.sidebyside tbody.mod del, .diff table.sidebyside tbody.mod ins { 
    162170 background: #fc0;  
    163171} 
     172 
     173/* Styles for the plain-text diff view */ 
     174.diff pre { background: #fff; border: 1px solid #ddd; font-size: 85%; 
     175  margin: 0; 
     176} 
  • /dev/null

    old new  
     1function escapeHTML(text) { 
     2  return text.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;"); 
     3} 
     4 
     5function convertDiff(name, table) { 
     6  var ths = table.tHead.rows[0].cells; 
     7  var lines = [ 
     8    "Index: " + name, 
     9    "===================================================================", 
     10    "--- " + ths[0].title.substr(5), 
     11    "+++ " + ths[1].title.substr(5), 
     12  ]; 
     13  var sepIndex = 0; 
     14  var oldOffset = 0, oldLength = 0, newOffset = 0, newLength = 0; 
     15 
     16  for (var i = 0; i < table.tBodies.length; i++) { 
     17    var tBody = table.tBodies[i]; 
     18    if (i == 0 || tBody.className == "skipped") { 
     19      if (i > 0) { 
     20        if (!oldOffset && oldLength) oldOffset = 1 
     21        if (!newOffset && newLength) newOffset = 1 
     22        lines[sepIndex] = lines[sepIndex] 
     23          .replace("{1}", oldOffset).replace("{2}", oldLength) 
     24          .replace("{3}", newOffset).replace("{4}", newLength); 
     25      } 
     26      sepIndex = lines.length; 
     27      lines.push("@@ -{1},{2}, +{3},{4} @@"); 
     28      oldOffset = 0, oldLength = 0, newOffset = 0, newLength = 0; 
     29      if (tBody.className == "skipped") continue; 
     30    } 
     31    for (var j = 0; j < tBody.rows.length; j++) { 
     32      var cells = tBody.rows[j].cells; 
     33      var oldLineNo = parseInt($(cells[0]).text()); 
     34      var newLineNo = parseInt($(cells[1]).text()); 
     35      var line = $(cells[2]).text(); 
     36      if (isNaN(oldLineNo)) { 
     37        lines.push("+ " + escapeHTML(line)); 
     38        newLength += 1; 
     39      } else if (isNaN(newLineNo)) { 
     40        lines.push("- " + escapeHTML(line)); 
     41        oldLength += 1; 
     42      } else { 
     43        lines.push("  " + escapeHTML(line)); 
     44        oldLength += 1; 
     45        newLength += 1; 
     46        if (!oldOffset) oldOffset = oldLineNo; 
     47        if (!newOffset) newOffset = newLineNo; 
     48      } 
     49    } 
     50  } 
     51 
     52  if (!oldOffset && oldLength) oldOffset = 1 
     53  if (!newOffset && newLength) newOffset = 1 
     54  lines[sepIndex] = lines[sepIndex] 
     55    .replace("{1}", oldOffset).replace("{2}", oldLength) 
     56    .replace("{3}", newOffset).replace("{4}", newLength); 
     57 
     58  return lines.join("<br />"); 
     59} 
     60 
     61$(document).ready(function() { 
     62  $("div.diff h2").each(function() { 
     63    var switcher = $("<span class='switch'></span>").prependTo(this); 
     64    var name = $.trim($(this).text()); 
     65    var table = $(this).next().get(0); 
     66    var pre = $("<pre></pre>").hide().insertAfter(table); 
     67    $("<span>Tabular</span>").click(function() { 
     68      $(pre).hide(); 
     69      $(table).show(); 
     70      $(this).addClass("active").siblings("span").removeClass("active"); 
     71      return false; 
     72    }).addClass("active").appendTo(switcher); 
     73    $("<span>Unified</span>").click(function() { 
     74      $(table).hide(); 
     75      if (!pre.get(0).firstChild) pre.html(convertDiff(name, table)); 
     76      $(pre).fadeIn("fast") 
     77      $(this).addClass("active").siblings("span").removeClass("active"); 
     78      return false; 
     79    }).appendTo(switcher); 
     80  }); 
     81}); 
  • /dev/null

    old new  
     1/* prevent execution of jQuery if included more then once */ 
     2if(typeof window.jQuery == "undefined") { 
     3/* 
     4 * jQuery 1.0.4 - New Wave Javascript 
     5 * 
     6 * Copyright (c) 2006 John Resig (jquery.com) 
     7 * Dual licensed under the MIT (MIT-LICENSE.txt) 
     8 * and GPL (GPL-LICENSE.txt) licenses. 
     9 * 
     10 * $Date: 2006-12-12 15:33:10 -0500 (Tue, 12 Dec 2006) $ 
     11 * $Rev: 696 $ 
     12 */ 
     13 
     14// Global undefined variable 
     15window.undefined = window.undefined; 
     16 
     17var jQuery = function(a,c) { 
     18 
     19        // Shortcut for document ready 
     20        if ( a && typeof a == "function" && jQuery.fn.ready && !a.nodeType && a[0] == undefined ) // Safari reports typeof on DOM NodeLists as a function 
     21                return jQuery(document).ready(a); 
     22 
     23        // Make sure that a selection was provided 
     24        a = a || document; 
     25 
     26        // Watch for when a jQuery object is passed as the selector 
     27        if ( a.jquery ) 
     28                return jQuery( jQuery.merge( a, [] ) ); 
     29 
     30        // Watch for when a jQuery object is passed at the context 
     31        if ( c && c.jquery ) 
     32                return jQuery( c ).find(a); 
     33 
     34        // If the context is global, return a new object 
     35        if ( window == this ) 
     36                return new jQuery(a,c); 
     37 
     38        // Handle HTML strings 
     39        if ( typeof a  == "string" ) { 
     40                var m = /^[^<]*(<.+>)[^>]*$/.exec(a); 
     41                if ( m ) a = jQuery.clean( [ m[1] ] ); 
     42        } 
     43 
     44        // Watch for when an array is passed in 
     45        this.set( a.constructor == Array || a.length && a != window && !a.nodeType && a[0] != undefined && a[0].nodeType ? 
     46                // Assume that it is an array of DOM Elements 
     47                jQuery.merge( a, [] ) : 
     48 
     49                // Find the matching elements and save them for later 
     50                jQuery.find( a, c ) ); 
     51 
     52        // See if an extra function was provided 
     53        var fn = arguments[ arguments.length - 1 ]; 
     54 
     55        // If so, execute it in context 
     56        if ( fn && typeof fn == "function" ) 
     57                this.each(fn); 
     58 
     59        return this; 
     60}; 
     61 
     62// Map over the $ in case of overwrite 
     63if ( typeof $ != "undefined" ) 
     64        jQuery._$ = $; 
     65         
     66// Map the jQuery namespace to the '$' one 
     67var $ = jQuery; 
     68 
     69 
     70 
     71jQuery.fn = jQuery.prototype = { 
     72 
     73        jquery: "1.0.4", 
     74 
     75 
     76        size: function() { 
     77                return this.length; 
     78        }, 
     79 
     80 
     81        get: function( num ) { 
     82                return num == undefined ? 
     83 
     84                        // Return a 'clean' array 
     85                        jQuery.merge( this, [] ) : 
     86 
     87                        // Return just the object 
     88                        this[num]; 
     89        }, 
     90 
     91        set: function( array ) { 
     92                // Use a tricky hack to make the jQuery object 
     93                // look and feel like an array 
     94                this.length = 0; 
     95                [].push.apply( this, array ); 
     96                return this; 
     97        }, 
     98 
     99        each: function( fn, args ) { 
     100                return jQuery.each( this, fn, args ); 
     101        }, 
     102 
     103        index: function( obj ) { 
     104                var pos = -1; 
     105                this.each(function(i){ 
     106                        if ( this == obj ) pos = i; 
     107                }); 
     108                return pos; 
     109        }, 
     110 
     111 
     112        attr: function( key, value, type ) { 
     113                // Check to see if we're setting style values 
     114                return key.constructor != String || value != undefined ? 
     115                        this.each(function(){ 
     116                                // See if we're setting a hash of styles 
     117                                if ( value == undefined ) 
     118                                        // Set all the styles 
     119                                        for ( var prop in key ) 
     120                                                jQuery.attr( 
     121                                                        type ? this.style : this, 
     122                                                        prop, key[prop] 
     123                                                ); 
     124 
     125                                // See if we're setting a single key/value style 
     126                                else 
     127                                        jQuery.attr( 
     128                                                type ? this.style : this, 
     129                                                key, value 
     130                                        ); 
     131                        }) : 
     132 
     133                        // Look for the case where we're accessing a style value 
     134                        jQuery[ type || "attr" ]( this[0], key ); 
     135        }, 
     136 
     137 
     138        css: function( key, value ) { 
     139                return this.attr( key, value, "curCSS" ); 
     140        }, 
     141 
     142        text: function(e) { 
     143                e = e || this; 
     144                var t = ""; 
     145                for ( var j = 0; j < e.length; j++ ) { 
     146                        var r = e[j].childNodes; 
     147                        for ( var i = 0; i < r.length; i++ ) 
     148                                if ( r[i].nodeType != 8 ) 
     149                                        t += r[i].nodeType != 1 ? 
     150                                                r[i].nodeValue : jQuery.fn.text([ r[i] ]); 
     151                } 
     152                return t; 
     153        }, 
     154 
     155 
     156        wrap: function() { 
     157                // The elements to wrap the target around 
     158                var a = jQuery.clean(arguments); 
     159 
     160                // Wrap each of the matched elements individually 
     161                return this.each(function(){ 
     162                        // Clone the structure that we're using to wrap 
     163                        var b = a[0].cloneNode(true); 
     164 
     165                        // Insert it before the element to be wrapped 
     166                        this.parentNode.insertBefore( b, this ); 
     167 
     168                        // Find the deepest point in the wrap structure 
     169                        while ( b.firstChild ) 
     170                                b = b.firstChild; 
     171 
     172                        // Move the matched element to within the wrap structure 
     173                        b.appendChild( this ); 
     174                }); 
     175        }, 
     176 
     177 
     178        append: function() { 
     179                return this.domManip(arguments, true, 1, function(a){ 
     180                        this.appendChild( a ); 
     181                }); 
     182        }, 
     183 
     184 
     185        prepend: function() { 
     186                return this.domManip(arguments, true, -1, function(a){ 
     187                        this.insertBefore( a, this.firstChild ); 
     188                }); 
     189        }, 
     190 
     191 
     192        before: function() { 
     193                return this.domManip(arguments, false, 1, function(a){ 
     194                        this.parentNode.insertBefore( a, this ); 
     195                }); 
     196        }, 
     197 
     198 
     199        after: function() { 
     200                return this.domManip(arguments, false, -1, function(a){ 
     201                        this.parentNode.insertBefore( a, this.nextSibling ); 
     202                }); 
     203        }, 
     204 
     205        end: function() { 
     206                if( !(this.stack && this.stack.length) ) 
     207                        return this; 
     208                return this.set( this.stack.pop() ); 
     209        }, 
     210 
     211        find: function(t) { 
     212                return this.pushStack( jQuery.map( this, function(a){ 
     213                        return jQuery.find(t,a); 
     214                }), arguments ); 
     215        }, 
     216 
     217        clone: function(deep) { 
     218                return this.pushStack( jQuery.map( this, function(a){ 
     219                        return a.cloneNode( deep != undefined ? deep : true ); 
     220                }), arguments ); 
     221        }, 
     222 
     223 
     224        filter: function(t) { 
     225                return this.pushStack( 
     226                        t.constructor == Array && 
     227                        jQuery.map(this,function(a){ 
     228                                for ( var i = 0; i < t.length; i++ ) 
     229                                        if ( jQuery.filter(t[i],[a]).r.length ) 
     230                                                return a; 
     231                                return null; 
     232                        }) || 
     233 
     234                        t.constructor == Boolean && 
     235                        ( t ? this.get() : [] ) || 
     236 
     237                        typeof t == "function" && 
     238                        jQuery.grep( this, t ) || 
     239 
     240                        jQuery.filter(t,this).r, arguments ); 
     241        }, 
     242 
     243 
     244        not: function(t) { 
     245                return this.pushStack( typeof t == "string" ? 
     246                        jQuery.filter(t,this,false).r : 
     247                        jQuery.grep(this,function(a){ return a != t; }), arguments ); 
     248        }, 
     249 
     250 
     251        add: function(t) { 
     252                return this.pushStack( jQuery.merge( this, typeof t == "string" ? 
     253                        jQuery.find(t) : t.constructor == Array ? t : [t] ), arguments ); 
     254        }, 
     255 
     256        is: function(expr) { 
     257                return expr ? jQuery.filter(expr,this).r.length > 0 : false; 
     258        }, 
     259 
     260        domManip: function(args, table, dir, fn){ 
     261                var clone = this.size() > 1; 
     262                var a = jQuery.clean(args); 
     263 
     264                return this.each(function(){ 
     265                        var obj = this; 
     266 
     267                        if ( table && this.nodeName.toUpperCase() == "TABLE" && a[0].nodeName.toUpperCase() != "THEAD" ) { 
     268                                var tbody = this.getElementsByTagName("tbody"); 
     269 
     270                                if ( !tbody.length ) { 
     271                                        obj = document.createElement("tbody"); 
     272                                        this.appendChild( obj ); 
     273                                } else 
     274                                        obj = tbody[0]; 
     275                        } 
     276 
     277                        for ( var i = ( dir < 0 ? a.length - 1 : 0 ); 
     278                                i != ( dir < 0 ? dir : a.length ); i += dir ) { 
     279                                        fn.apply( obj, [ clone ? a[i].cloneNode(true) : a[i] ] ); 
     280                        } 
     281                }); 
     282        }, 
     283 
     284        pushStack: function(a,args) { 
     285                var fn = args && args[args.length-1]; 
     286                var fn2 = args && args[args.length-2]; 
     287                 
     288                if ( fn && fn.constructor != Function ) fn = null; 
     289                if ( fn2 && fn2.constructor != Function ) fn2 = null; 
     290 
     291                if ( !fn ) { 
     292                        if ( !this.stack ) this.stack = []; 
     293                        this.stack.push( this.get() ); 
     294                        this.set( a ); 
     295                } else { 
     296                        var old = this.get(); 
     297                        this.set( a ); 
     298 
     299                        if ( fn2 && a.length || !fn2 ) 
     300                                this.each( fn2 || fn ).set( old ); 
     301                        else 
     302                                this.set( old ).each( fn ); 
     303                } 
     304 
     305                return this; 
     306        } 
     307}; 
     308 
     309 
     310jQuery.extend = jQuery.fn.extend = function() { 
     311        // copy reference to target object 
     312        var target = arguments[0], 
     313                a = 1; 
     314 
     315        // extend jQuery itself if only one argument is passed 
     316        if ( arguments.length == 1 ) { 
     317                target = this; 
     318                a = 0; 
     319        } 
     320        var prop; 
     321        while (prop = arguments[a++]) 
     322                // Extend the base object 
     323                for ( var i in prop ) target[i] = prop[i]; 
     324 
     325        // Return the modified object 
     326        return target; 
     327}; 
     328 
     329jQuery.extend({ 
     330 
     331        init: function(){ 
     332                jQuery.initDone = true; 
     333 
     334                jQuery.each( jQuery.macros.axis, function(i,n){ 
     335                        jQuery.fn[ i ] = function(a) { 
     336                                var ret = jQuery.map(this,n); 
     337                                if ( a && typeof a == "string" ) 
     338                                        ret = jQuery.filter(a,ret).r; 
     339                                return this.pushStack( ret, arguments ); 
     340                        }; 
     341                }); 
     342 
     343                jQuery.each( jQuery.macros.to, function(i,n){ 
     344                        jQuery.fn[ i ] = function(){ 
     345                                var a = arguments; 
     346                                return this.each(function(){ 
     347                                        for ( var j = 0; j < a.length; j++ ) 
     348                                                jQuery(a[j])[n]( this ); 
     349                                }); 
     350                        }; 
     351                }); 
     352 
     353                jQuery.each( jQuery.macros.each, function(i,n){ 
     354                        jQuery.fn[ i ] = function() { 
     355                                return this.each( n, arguments ); 
     356                        }; 
     357                }); 
     358 
     359                jQuery.each( jQuery.macros.filter, function(i,n){ 
     360                        jQuery.fn[ n ] = function(num,fn) { 
     361                                return this.filter( ":" + n + "(" + num + ")", fn ); 
     362                        }; 
     363                }); 
     364 
     365                jQuery.each( jQuery.macros.attr, function(i,n){ 
     366                        n = n || i; 
     367                        jQuery.fn[ i ] = function(h) { 
     368                                return h == undefined ? 
     369                                        this.length ? this[0][n] : null : 
     370                                        this.attr( n, h ); 
     371                        }; 
     372                }); 
     373 
     374                jQuery.each( jQuery.macros.css, function(i,n){ 
     375                        jQuery.fn[ n ] = function(h) { 
     376                                return h == undefined ? 
     377                                        ( this.length ? jQuery.css( this[0], n ) : null ) : 
     378                                        this.css( n, h ); 
     379                        }; 
     380                }); 
     381 
     382        }, 
     383 
     384        // args is for internal usage only 
     385        each: function( obj, fn, args ) { 
     386                if ( obj.length == undefined ) 
     387                        for ( var i in obj ) 
     388                                fn.apply( obj[i], args || [i, obj[i]] ); 
     389                else 
     390                        for ( var i = 0; i < obj.length; i++ ) 
     391                                if ( fn.apply( obj[i], args || [i, obj[i]] ) === false ) break; 
     392                return obj; 
     393        }, 
     394 
     395        className: { 
     396                add: function(o,c){ 
     397                        if (jQuery.className.has(o,c)) return; 
     398                        o.className += ( o.className ? " " : "" ) + c; 
     399                }, 
     400                remove: function(o,c){ 
     401                        if( !c ) { 
     402                                o.className = ""; 
     403                        } else { 
     404                                var classes = o.className.split(" "); 
     405                                for(var i=0; i<classes.length; i++) { 
     406                                        if(classes[i] == c) { 
     407                                                classes.splice(i, 1); 
     408                                                break; 
     409                                        } 
     410                                } 
     411                                o.className = classes.join(' '); 
     412                        } 
     413                }, 
     414                has: function(e,a) { 
     415                        if ( e.className != undefined ) 
     416                                e = e.className; 
     417                        return new RegExp("(^|\\s)" + a + "(\\s|$)").test(e); 
     418                } 
     419        }, 
     420 
     421        swap: function(e,o,f) { 
     422                for ( var i in o ) { 
     423                        e.style["old"+i] = e.style[i]; 
     424                        e.style[i] = o[i]; 
     425                } 
     426                f.apply( e, [] ); 
     427                for ( var i in o ) 
     428                        e.style[i] = e.style["old"+i]; 
     429        }, 
     430 
     431        css: function(e,p) { 
     432                if ( p == "height" || p == "width" ) { 
     433                        var old = {}, oHeight, oWidth, d = ["Top","Bottom","Right","Left"]; 
     434 
     435                        for ( var i=0; i<d.length; i++ ) { 
     436                                old["padding" + d[i]] = 0; 
     437                                old["border" + d[i] + "Width"] = 0; 
     438                        } 
     439 
     440                        jQuery.swap( e, old, function() { 
     441                                if (jQuery.css(e,"display") != "none") { 
     442                                        oHeight = e.offsetHeight; 
     443                                        oWidth = e.offsetWidth; 
     444                                } else { 
     445                                        e = jQuery(e.cloneNode(true)) 
     446                                                .find(":radio").removeAttr("checked").end() 
     447                                                .css({ 
     448                                                        visibility: "hidden", position: "absolute", display: "block", right: "0", left: "0" 
     449                                                }).appendTo(e.parentNode)[0]; 
     450 
     451                                        var parPos = jQuery.css(e.parentNode,"position"); 
     452                                        if ( parPos == "" || parPos == "static" ) 
     453                                                e.parentNode.style.position = "relative"; 
     454 
     455                                        oHeight = e.clientHeight; 
     456                                        oWidth = e.clientWidth; 
     457 
     458                                        if ( parPos == "" || parPos == "static" ) 
     459                                                e.parentNode.style.position = "static"; 
     460 
     461                                        e.parentNode.removeChild(e); 
     462                                } 
     463                        }); 
     464 
     465                        return p == "height" ? oHeight : oWidth; 
     466                } 
     467 
     468                return jQuery.curCSS( e, p ); 
     469        }, 
     470 
     471        curCSS: function(elem, prop, force) { 
     472                var ret; 
     473                 
     474                if (prop == 'opacity' && jQuery.browser.msie) 
     475                        return jQuery.attr(elem.style, 'opacity'); 
     476                         
     477                if (prop == "float" || prop == "cssFloat") 
     478                    prop = jQuery.browser.msie ? "styleFloat" : "cssFloat"; 
     479 
     480                if (!force && elem.style[prop]) { 
     481 
     482                        ret = elem.style[prop]; 
     483 
     484                } else if (document.defaultView && document.defaultView.getComputedStyle) { 
     485 
     486                        if (prop == "cssFloat" || prop == "styleFloat") 
     487                                prop = "float"; 
     488 
     489                        prop = prop.replace(/([A-Z])/g,"-$1").toLowerCase(); 
     490                        var cur = document.defaultView.getComputedStyle(elem, null); 
     491 
     492                        if ( cur ) 
     493                                ret = cur.getPropertyValue(prop); 
     494                        else if ( prop == 'display' ) 
     495                                ret = 'none'; 
     496                        else 
     497                                jQuery.swap(elem, { display: 'block' }, function() { 
     498                                    var c = document.defaultView.getComputedStyle(this, ''); 
     499                                    ret = c && c.getPropertyValue(prop) || ''; 
     500                                }); 
     501 
     502                } else if (elem.currentStyle) { 
     503 
     504                        var newProp = prop.replace(/\-(\w)/g,function(m,c){return c.toUpperCase();}); 
     505                        ret = elem.currentStyle[prop] || elem.currentStyle[newProp]; 
     506                         
     507                } 
     508 
     509                return ret; 
     510        }, 
     511         
     512        clean: function(a) { 
     513                var r = []; 
     514                for ( var i = 0; i < a.length; i++ ) { 
     515                        var arg = a[i]; 
     516                        if ( typeof arg == "string" ) { // Convert html string into DOM nodes 
     517                                // Trim whitespace, otherwise indexOf won't work as expected 
     518                                var s = jQuery.trim(arg), div = document.createElement("div"), wrap = [0,"",""]; 
     519 
     520                                if ( !s.indexOf("<opt") ) // option or optgroup 
     521                                        wrap = [1, "<select>", "</select>"]; 
     522                                else if ( !s.indexOf("<thead") || !s.indexOf("<tbody") ) 
     523                                        wrap = [1, "<table>", "</table>"]; 
     524                                else if ( !s.indexOf("<tr") ) 
     525                                        wrap = [2, "<table>", "</table>"];      // tbody auto-inserted 
     526                                else if ( !s.indexOf("<td") || !s.indexOf("<th") ) 
     527                                        wrap = [3, "<table><tbody><tr>", "</tr></tbody></table>"]; 
     528 
     529                                // Go to html and back, then peel off extra wrappers 
     530                                div.innerHTML = wrap[1] + s + wrap[2]; 
     531                                while ( wrap[0]-- ) div = div.firstChild; 
     532                                arg = div.childNodes; 
     533                        }  
     534                         
     535                         
     536                        if ( arg.length != undefined && ( (jQuery.browser.safari && typeof arg == 'function') || !arg.nodeType ) ) // Safari reports typeof on a DOM NodeList to be a function 
     537                                for ( var n = 0; n < arg.length; n++ ) // Handles Array, jQuery, DOM NodeList collections 
     538                                        r.push(arg[n]); 
     539                        else 
     540                                r.push( arg.nodeType ? arg : document.createTextNode(arg.toString()) ); 
     541                } 
     542 
     543                return r; 
     544        }, 
     545 
     546        expr: { 
     547                "": "m[2]== '*'||a.nodeName.toUpperCase()==m[2].toUpperCase()", 
     548                "#": "a.getAttribute('id')&&a.getAttribute('id')==m[2]", 
     549                ":": { 
     550                        // Position Checks 
     551                        lt: "i<m[3]-0", 
     552                        gt: "i>m[3]-0", 
     553                        nth: "m[3]-0==i", 
     554                        eq: "m[3]-0==i", 
     555                        first: "i==0", 
     556                        last: "i==r.length-1", 
     557                        even: "i%2==0", 
     558                        odd: "i%2", 
     559 
     560                        // Child Checks 
     561                        "nth-child": "jQuery.sibling(a,m[3]).cur", 
     562                        "first-child": "jQuery.sibling(a,0).cur", 
     563                        "last-child": "jQuery.sibling(a,0).last", 
     564                        "only-child": "jQuery.sibling(a).length==1", 
     565 
     566                        // Parent Checks 
     567                        parent: "a.childNodes.length", 
     568                        empty: "!a.childNodes.length", 
     569 
     570                        // Text Check 
     571                        contains: "jQuery.fn.text.apply([a]).indexOf(m[3])>=0", 
     572 
     573                        // Visibility 
     574                        visible: "a.type!='hidden'&&jQuery.css(a,'display')!='none'&&jQuery.css(a,'visibility')!='hidden'", 
     575                        hidden: "a.type=='hidden'||jQuery.css(a,'display')=='none'||jQuery.css(a,'visibility')=='hidden'", 
     576 
     577                        // Form attributes 
     578                        enabled: "!a.disabled", 
     579                        disabled: "a.disabled", 
     580                        checked: "a.checked", 
     581                        selected: "a.selected || jQuery.attr(a, 'selected')", 
     582 
     583                        // Form elements 
     584                        text: "a.type=='text'", 
     585                        radio: "a.type=='radio'", 
     586                        checkbox: "a.type=='checkbox'", 
     587                        file: "a.type=='file'", 
     588                        password: "a.type=='password'", 
     589                        submit: "a.type=='submit'", 
     590                        image: "a.type=='image'", 
     591                        reset: "a.type=='reset'", 
     592                        button: "a.type=='button'", 
     593                        input: "/input|select|textarea|button/i.test(a.nodeName)" 
     594                }, 
     595                ".": "jQuery.className.has(a,m[2])", 
     596                "@": { 
     597                        "=": "z==m[4]", 
     598                        "!=": "z!=m[4]", 
     599                        "^=": "z && !z.indexOf(m[4])", 
     600                        "$=": "z && z.substr(z.length - m[4].length,m[4].length)==m[4]", 
     601                        "*=": "z && z.indexOf(m[4])>=0", 
     602                        "": "z" 
     603                }, 
     604                "[": "jQuery.find(m[2],a).length" 
     605        }, 
     606 
     607        token: [ 
     608                "\\.\\.|/\\.\\.", "a.parentNode", 
     609                ">|/", "jQuery.sibling(a.firstChild)", 
     610                "\\+", "jQuery.sibling(a).next", 
     611                "~", function(a){ 
     612                        var s = jQuery.sibling(a); 
     613                        return s.n >= 0 ? s.slice(s.n+1) : []; 
     614                } 
     615        ], 
     616 
     617        find: function( t, context ) { 
     618                // Make sure that the context is a DOM Element 
     619                if ( context && context.nodeType == undefined ) 
     620                        context = null; 
     621 
     622                // Set the correct context (if none is provided) 
     623                context = context || document; 
     624 
     625                if ( t.constructor != String ) return [t]; 
     626 
     627                if ( !t.indexOf("//") ) { 
     628                        context = context.documentElement; 
     629                        t = t.substr(2,t.length); 
     630                } else if ( !t.indexOf("/") ) { 
     631                        context = context.documentElement; 
     632                        t = t.substr(1,t.length); 
     633                        // FIX Assume the root element is right :( 
     634                        if ( t.indexOf("/") >= 1 ) 
     635                                t = t.substr(t.indexOf("/"),t.length); 
     636                } 
     637 
     638                var ret = [context]; 
     639                var done = []; 
     640                var last = null; 
     641 
     642                while ( t.length > 0 && last != t ) { 
     643                        var r = []; 
     644                        last = t; 
     645 
     646                        t = jQuery.trim(t).replace( /^\/\//i, "" ); 
     647 
     648                        var foundToken = false; 
     649 
     650                        for ( var i = 0; i < jQuery.token.length; i += 2 ) { 
     651                                if ( foundToken ) continue; 
     652 
     653                                var re = new RegExp("^(" + jQuery.token[i] + ")"); 
     654                                var m = re.exec(t); 
     655 
     656                                if ( m ) { 
     657                                        r = ret = jQuery.map( ret, jQuery.token[i+1] ); 
     658                                        t = jQuery.trim( t.replace( re, "" ) ); 
     659                                        foundToken = true; 
     660                                } 
     661                        } 
     662 
     663                        if ( !foundToken ) { 
     664                                if ( !t.indexOf(",") || !t.indexOf("|") ) { 
     665                                        if ( ret[0] == context ) ret.shift(); 
     666                                        done = jQuery.merge( done, ret ); 
     667                                        r = ret = [context]; 
     668                                        t = " " + t.substr(1,t.length); 
     669                                } else { 
     670                                        var re2 = /^([#.]?)([a-z0-9\\*_-]*)/i; 
     671                                        var m = re2.exec(t); 
     672 
     673                                        if ( m[1] == "#" ) { 
     674                                                // Ummm, should make this work in all XML docs 
     675                                                var oid = document.getElementById(m[2]); 
     676                                                r = ret = oid ? [oid] : []; 
     677                                                t = t.replace( re2, "" ); 
     678                                        } else { 
     679                                                if ( !m[2] || m[1] == "." ) m[2] = "*"; 
     680 
     681                                                for ( var i = 0; i < ret.length; i++ ) 
     682                                                        r = jQuery.merge( r, 
     683                                                                m[2] == "*" ? 
     684                                                                        jQuery.getAll(ret[i]) : 
     685                                                                        ret[i].getElementsByTagName(m[2]) 
     686                                                        ); 
     687                                        } 
     688                                } 
     689 
     690                        } 
     691 
     692                        if ( t ) { 
     693                                var val = jQuery.filter(t,r); 
     694                                ret = r = val.r; 
     695                                t = jQuery.trim(val.t); 
     696                        } 
     697                } 
     698 
     699                if ( ret && ret[0] == context ) ret.shift(); 
     700                done = jQuery.merge( done, ret ); 
     701 
     702                return done; 
     703        }, 
     704 
     705        getAll: function(o,r) { 
     706                r = r || []; 
     707                var s = o.childNodes; 
     708                for ( var i = 0; i < s.length; i++ ) 
     709                        if ( s[i].nodeType == 1 ) { 
     710                                r.push( s[i] ); 
     711                                jQuery.getAll( s[i], r ); 
     712  &nb