Changeset 6651 for extensions/rv_gmaps


Ignore:
Timestamp:
Jul 2, 2010, 6:53:40 AM (14 years ago)
Author:
rvelices
Message:

rv_gmaps - start using google.maps JS namespace + upgrade prototype.js

Location:
extensions/rv_gmaps/trunk
Files:
7 edited

Legend:

Unmodified
Added
Removed
  • extensions/rv_gmaps/trunk/changelog.txt

    r6472 r6651  
    112.1.b
    22- fixed admin navigation bar
     3- compatible with extended description
     4- upgrade prototype
    35
    462.1.a
  • extensions/rv_gmaps/trunk/template/data_handler.js

    r6245 r6651  
    1010                , opts || {} );
    1111
    12         GEvent.addListener( map, "infowindowclose", function() {map.getInfoWindow().pwgMarker=null;} );
     12        google.maps.Event.addListener( map, "infowindowclose", function() {map.getInfoWindow().pwgMarker=null;} );
    1313}
    1414
     
    8383                        {
    8484                                this._map.removeOverlay( marker );
    85                                 GEvent.clearListeners(marker, "click" );
    86                                 GEvent.clearListeners(marker, "dblclick" );
     85                                google.maps.Event.clearListeners(marker, "click" );
     86                                google.maps.Event.clearListeners(marker, "dblclick" );
    8787                                this._map.getInfoWindow().pwgMarker = infoWindowMarker = null;
    88                                 if (document.is_debug) GLog.write('removed marker with infoWindow');
     88                                if (document.is_debug) google.maps.Log.write('removed marker with infoWindow');
    8989                                marker = this._markers.pop();
    9090                        }
     
    9292                        if (!marker)
    9393                        {
    94                                 marker = new GMarker( cluster.position, {title:  theTitle, icon: this.options.icon } );
    95                                 GEvent.addListener( marker, "click", this._onMarkerClick.bind(this, marker) );
    96                                 GEvent.addListener( marker, "dblclick", this._onMarkerDblClick.bind(this, marker) );
     94                                marker = new google.maps.Marker( cluster.position, {title:  theTitle, icon: this.options.icon } );
     95                                google.maps.Event.addListener( marker, "click", this._onMarkerClick.bind(this, marker) );
     96                                google.maps.Event.addListener( marker, "dblclick", this._onMarkerDblClick.bind(this, marker) );
    9797                                this._map.addOverlay( marker );
    9898                        }
     
    144144                {
    145145                        this._map.removeOverlay( this._markers[i] );
    146                         GEvent.clearListeners(this._markers[i], "click" );
    147                         GEvent.clearListeners(this._markers[i], "dblclick" );
     146                        google.maps.Event.clearListeners(this._markers[i], "click" );
     147                        google.maps.Event.clearListeners(this._markers[i], "dblclick" );
    148148                }
    149149
     
    160160        if (this._map.getInfoWindow().pwgMarker == marker )
    161161                return; // already open
    162   var content = "";
    163   if ( !marker.currentImageIndex )
    164     marker.currentImageIndex = 0;
    165   content += '<div class="gmiw_header" style="' + (marker.pwg.images.length>1 ? '': 'display:none')+ '">';
    166   content += '<span id="pwgImageCounters">'+this.buildCurrentPictureCounterHtml(marker)+'</span> ';
    167   content += '<a href="javascript:void(0);" id="'+this._navHtmlIds[0]+'">';
    168   content +=    '<span>'+ "&laquo; " + Localization.get('Prev') + '</span>';
    169   content += '</a>';
    170   content += " ";
    171   content += '<a href="javascript:void(0);" id="'+this._navHtmlIds[1]+'">';
    172   content +=    '<span>'+Localization.get('Next') + " &raquo;"+'</span>';
    173   content += '</a>';
    174   content += " ";
    175   var imgShowAll = '';
    176   if (this.options.show_all_img_src)
    177     imgShowAll = '<img src="'+this.options.show_all_img_src+'" alt="" style="border:0" /> ';
    178   content += '<a id="pwgImageBlowup" href="'+marker.pwg.blowup_url+'" onclick="return PwgDataHandler.blowupUrl(this.href);" title='+Localization.getQ('show all pictures around this location')+'>'+
    179             imgShowAll+ '<span>'+Localization.get('Show all')+'</span>'+
    180           '</a>';
    181   content += '</div>';
    182   content += '<div id="pwgImageDetail">' + this.buildCurrentPictureHtml( marker ) + '</div>';
    183 
    184   marker.openInfoWindowHtml( content );
    185 
    186   // bind to next / prev a little later because sometimes the nodes are not immediately created
    187   if (this._timerBindPictureNavigation) clearTimeout(this._timerBindPictureNavigation);
    188   this._timerBindPictureNavigation = null;
    189   if (marker.pwg.images.length>1)
    190     this._timerBindPictureNavigation = setTimeout( this._onTimeoutBindPictureNavigation.bind(this, marker), 250 );
     162        var content = "";
     163        if ( !marker.currentImageIndex )
     164                marker.currentImageIndex = 0;
     165        content += '<div class="gmiw_header" style="' + (marker.pwg.images.length>1 ? '': 'display:none')+ '">';
     166        content += '<span id="pwgImageCounters">'+this.buildCurrentPictureCounterHtml(marker)+'</span> ';
     167        content += '<a href="javascript:void(0);" id="'+this._navHtmlIds[0]+'">';
     168        content +=    '<span>'+ "&laquo; " + Localization.get('Prev') + '</span>';
     169        content += '</a>';
     170        content += " ";
     171        content += '<a href="javascript:void(0);" id="'+this._navHtmlIds[1]+'">';
     172        content +=    '<span>'+Localization.get('Next') + " &raquo;"+'</span>';
     173        content += '</a>';
     174        content += " ";
     175        var imgShowAll = '';
     176        if (this.options.show_all_img_src)
     177                imgShowAll = '<img src="'+this.options.show_all_img_src+'" alt="" style="border:0" /> ';
     178        content += '<a id="pwgImageBlowup" href="'+marker.pwg.blowup_url+'" onclick="return PwgDataHandler.blowupUrl(this.href);" title='+Localization.getQ('show all pictures around this location')+'>'+
     179                                                imgShowAll+ '<span>'+Localization.get('Show all')+'</span>'+
     180                                        '</a>';
     181        content += '</div>';
     182        content += '<div id="pwgImageDetail">' + this.buildCurrentPictureHtml( marker ) + '</div>';
     183
     184        marker.openInfoWindowHtml( content );
     185
     186        // bind to next / prev a little later because sometimes the nodes are not immediately created
     187        if (this._timerBindPictureNavigation) clearTimeout(this._timerBindPictureNavigation);
     188        this._timerBindPictureNavigation = null;
     189        if (marker.pwg.images.length>1)
     190                this._timerBindPictureNavigation = setTimeout( this._onTimeoutBindPictureNavigation.bind(this, marker), 250 );
    191191},
    192192
    193193_onMarkerDblClick: function( marker )
    194194{
    195   this._map.setCenter( marker.pwg.bounds.getCenter(), this._map.getBoundsZoomLevel( marker.pwg.bounds ) );
     195        this._map.setCenter( marker.pwg.bounds.getCenter(), this._map.getBoundsZoomLevel( marker.pwg.bounds ) );
    196196},
    197197
    198198buildCurrentPictureHtml: function( marker )
    199199{
    200   var imageDetail = marker.pwg.images[marker.currentImageIndex];
    201   var res = "";
    202   res += '<div class="gmiw_imageTitle">' + imageDetail.name + "</div>";
    203   res +=
     200        var imageDetail = marker.pwg.images[marker.currentImageIndex];
     201        var res = "";
     202        res += '<div class="gmiw_imageTitle">' + imageDetail.name + "</div>";
     203        res +=
    204204'<div class="gmiw_imageContent">' +
    205205'<div class="gmiw_imageWrap">'+
     
    209209'<div class="gmiw_imageComment">' + imageDetail.comment + '</div>' +
    210210'</div>';
    211   return res;
     211        return res;
    212212},
    213213
    214214buildCurrentPictureCounterHtml: function( marker )
    215215{
    216   var res =
    217     '<b>'+(marker.currentImageIndex+1)+'</b>'+
    218     '/' +
    219     '<b>'+marker.pwg.images.length+'</b>';
    220   if (marker.pwg.nb_items>marker.pwg.images.length)
    221     res+= " "+Localization.fmt1("out of %d", marker.pwg.nb_items );
    222   return res;
     216        var res =
     217                '<b>'+(marker.currentImageIndex+1)+'</b>'+
     218                '/' +
     219                '<b>'+marker.pwg.images.length+'</b>';
     220        if (marker.pwg.nb_items>marker.pwg.images.length)
     221                res+= " "+Localization.fmt1("out of %d", marker.pwg.nb_items );
     222        return res;
    223223},
    224224
     
    226226_onTimeoutBindPictureNavigation: function( marker )
    227227{
    228   clearTimeout(this._timerBindPictureNavigation);
    229   this._timerBindPictureNavigation = null;
    230   this._map.getInfoWindow().pwgMarker = marker;
    231   for (var i=0; i< this._navHtmlIds.length; i++)
    232   {
    233     var elt = document.getElementById( this._navHtmlIds[i] );
    234     if (elt)
    235       GEvent.addDomListener(elt, "click", this._onPictureNavigate.bind(this, marker, i) );
    236   }
     228        clearTimeout(this._timerBindPictureNavigation);
     229        this._timerBindPictureNavigation = null;
     230        this._map.getInfoWindow().pwgMarker = marker;
     231        for (var i=0; i< this._navHtmlIds.length; i++)
     232        {
     233                var elt = document.getElementById( this._navHtmlIds[i] );
     234                if (elt)
     235                        google.maps.Event.addDomListener(elt, "click", this._onPictureNavigate.bind(this, marker, i) );
     236        }
    237237},
    238238
    239239_onPictureNavigate: function(marker, dir )
    240240{
    241   if (dir==0) dir=-1;
    242   marker.currentImageIndex += dir;
    243   if (marker.currentImageIndex<0)
    244     marker.currentImageIndex = marker.pwg.images.length-1;
    245   else if (marker.currentImageIndex >= marker.pwg.images.length)
    246     marker.currentImageIndex = 0;
    247 
    248   try {
    249     var elt = document.getElementById( "pwgImageDetail" );
    250     elt.innerHTML = this.buildCurrentPictureHtml( marker );
    251   }
    252   catch (e)
    253   {
    254     alert (e.message);
    255   }
    256 
    257   try {
    258     var elt = document.getElementById( "pwgImageCounters" );
    259     elt.innerHTML = this.buildCurrentPictureCounterHtml( marker );
    260   }
    261   catch (e)
    262   {
    263     alert (e.message);
    264   }
    265   return false;
     241        if (dir==0) dir=-1;
     242        marker.currentImageIndex += dir;
     243        if (marker.currentImageIndex<0)
     244                marker.currentImageIndex = marker.pwg.images.length-1;
     245        else if (marker.currentImageIndex >= marker.pwg.images.length)
     246                marker.currentImageIndex = 0;
     247
     248        try {
     249                var elt = document.getElementById( "pwgImageDetail" );
     250                elt.innerHTML = this.buildCurrentPictureHtml( marker );
     251        }
     252        catch (e)
     253        {
     254                alert (e.message);
     255        }
     256
     257        try {
     258                var elt = document.getElementById( "pwgImageCounters" );
     259                elt.innerHTML = this.buildCurrentPictureCounterHtml( marker );
     260        }
     261        catch (e)
     262        {
     263                alert (e.message);
     264        }
     265        return false;
    266266}
    267267
     
    270270PwgDataHandler.blowupUrl = function(theUrl)
    271271{
    272   var win = new Window({
    273     title: document.title,
    274     url: theUrl,
    275     classname: "alphacube",
    276     left: 0, top: 0,
    277     width:"640", height:"480",
    278     minimizable: false,
    279     maximizable: false,
    280     draggable: false,
    281     resizable: false,
    282     destroyOnClose: true,
    283     hideEffect: Element.hide,
    284     showEffectOptions: {duration:1.5}
    285   });
    286 
    287   win.setConstraint(true, {top:20, left:20, bottom:30, right:20} );
    288   win.maximize();
    289   win.showCenter(true, 20, 20);
    290   return false;
     272        var win = new Window({
     273                title: document.title,
     274                url: theUrl,
     275                classname: "alphacube",
     276                left: 0, top: 0,
     277                width:"640", height:"480",
     278                minimizable: false,
     279                maximizable: false,
     280                draggable: false,
     281                resizable: false,
     282                destroyOnClose: true,
     283                hideEffect: Element.hide,
     284                showEffectOptions: {duration:1.5}
     285        });
     286
     287        win.setConstraint(true, {top:20, left:20, bottom:30, right:20} );
     288        win.maximize();
     289        win.showCenter(true, 20, 20);
     290        return false;
    291291}
    292292
     
    294294String.prototype.urlNoHtm = function()
    295295{
    296   return this.replace( "&amp;", "&" );
    297 }
     296        return this.replace( "&amp;", "&" );
     297}
  • extensions/rv_gmaps/trunk/template/data_loader.js

    r6400 r6651  
    88                }
    99                , opts || {} );
    10         this.options.rectangle_of_confusion = new GSize( this.options.rectangle_of_confusion.width, this.options.rectangle_of_confusion.height );
     10        this.options.rectangle_of_confusion = new google.maps.Size( this.options.rectangle_of_confusion.width, this.options.rectangle_of_confusion.height );
    1111        if (this.options.rectangle_of_confusion.width<16) this.options.rectangle_of_confusion.width=16;
    1212        if (this.options.rectangle_of_confusion.height<16) this.options.rectangle_of_confusion.height=16;
     
    3737{
    3838        this._urlMapData = urlMapData;
    39         GEvent.bind( this._map, "movestart", this, this.clearTimerReloadData );
    40         GEvent.bind( this._map, "moveend", this, this._onMapMoveEnd );
     39        google.maps.Event.bind( this._map, "movestart", this, this.clearTimerReloadData );
     40        google.maps.Event.bind( this._map, "moveend", this, this._onMapMoveEnd );
    4141        this._loadData();
    4242},
     
    7777        var bounds = this._map.getBounds();
    7878
    79         // BEGIN BUG in maps api 2.185 up to "today" 2.193 - when map wraps horizontally more than 360 deg - the getBounds is wrong
    80         /*if ( this._map.getZoom() <= 2 || this._map.getZoom() == 3 && this._map.getSize().width > 1000 )
    81         {
    82                 bounds = new GLatLngBounds(
    83                                 new GLatLng( bounds.getSouthWest().lat(),  -180 ),
    84                                 new GLatLng( bounds.getNorthEast().lat(),  180 )
    85                         );
    86         }*/
    87         // END BUG
    8879        var latRange = bounds.toSpan().lat();
    8980        var latPrec = latRange * this.options.rectangle_of_confusion.height / this._map.getSize().height;
     
    10798                                        )
    10899                                {
    109                                         if (document.is_debug) GLog.write('no load: zoom crt: '+this._map.getZoom()+'; prev: '+this._previousLoadDataReq.zoom+'; target: '+this._map.getBoundsZoomLevel(this._previousLoadDataReq.resultBounds));
     100                                        if (document.is_debug) google.maps.Log.write('no load: zoom crt: '+this._map.getZoom()+'; prev: '+this._previousLoadDataReq.zoom+'; target: '+this._map.getBoundsZoomLevel(this._previousLoadDataReq.resultBounds));
    110101                                        return;
    111102                                }
     
    129120        }
    130121        var digits = Math.max( getLatLonDigits(latRange,4,2), getLatLonDigits(lonRange,4,2) );
    131         var box = new GLatLngBounds(
    132                         new GLatLng( Math.roundN(bounds.getSouthWest().lat()-sd,digits), Math.roundN( bounds.getSouthWest().lng()-wd,digits ) ),
    133                         new GLatLng( Math.roundN(bounds.getNorthEast().lat()+nd,digits), Math.roundN( bounds.getNorthEast().lng()+ed,digits) )
    134                 );
     122        /*var box = new google.maps.LatLngBounds(
     123                        new google.maps.LatLng( Math.roundN(bounds.getSouthWest().lat()-sd,digits), Math.roundN( bounds.getSouthWest().lng()-wd,digits ) ),
     124                        new google.maps.LatLng( Math.roundN(bounds.getNorthEast().lat()+nd,digits), Math.roundN( bounds.getNorthEast().lng()+ed,digits) )
     125                );*/
     126        var box = new google.maps.LatLngBounds( bounds.getSouthWest(), bounds.getNorthEast() );
     127        box.extend( new google.maps.LatLng( Math.roundN(bounds.getSouthWest().lat()-sd,digits), Math.roundN( bounds.getSouthWest().lng()-wd,digits ) ) );
     128        box.extend( new google.maps.LatLng( Math.roundN(bounds.getNorthEast().lat()+nd,digits), Math.roundN( bounds.getNorthEast().lng()+ed,digits) ) );
    135129
    136130        var url = this._urlMapData;
     
    140134
    141135        if (document.is_debug) {
    142                 GLog.write( "bounds: " + this._map.getBounds().getSouthWest().toUrlValue() + " " + this._map.getBounds().getNorthEast().toUrlValue() +"; zoom: "+this._map.getZoom() +"; size: "+this._map.getSize().toString() +"; c: "+this._map.getCenter().toUrlValue() );
    143                 GLog.writeUrl( url );
     136                google.maps.Log.write("sd="+sd+" wd="+wd+" nd="+nd+" ed="+ed);
     137                google.maps.Log.write( "bounds: " + this._map.getBounds().getSouthWest().toUrlValue() + " " + this._map.getBounds().getNorthEast().toUrlValue() +"; zoom: "+this._map.getZoom() +"; size: "+this._map.getSize().toString() +"; c: "+this._map.getCenter().toUrlValue() );
     138                google.maps.Log.writeUrl( url );
    144139        }
    145140
     
    150145
    151146        try {
    152                 GEvent.trigger( this, "dataloading" );
     147                google.maps.Event.trigger( this, "dataloading" );
    153148                GDownloadUrl(url, this._onDataReceived.bind(this) );
    154149        }
     
    156151                this._dataLoading = false;
    157152                this._previousLoadDataReq.box=null;
    158                 GEvent.trigger( this, "dataloadfailed", 600, e );
     153                google.maps.Event.trigger( this, "dataloadfailed", 600, e );
    159154        }
    160155},
     
    168163                {
    169164                        this._previousLoadDataReq.box=null;
    170                         GEvent.trigger( this, "dataloadfailed", responseCode, null );
     165                        google.maps.Event.trigger( this, "dataloadfailed", responseCode, null );
    171166                }
    172167                else
     
    178173
    179174                        this._previousLoadDataReq.resultBounds = resp.bounds;
    180                         if (document.is_debug && resp.debug) GLog.write( resp.debug );
    181                         GEvent.trigger( this, "dataloaded", resp );
     175                        if (document.is_debug && resp.debug) google.maps.Log.write( resp.debug );
     176                        google.maps.Event.trigger( this, "dataloaded", resp );
    182177                }
    183178                catch (e)       {
    184179                        this._previousLoadDataReq.box=null;
    185                         GEvent.trigger( this, "dataloadfailed", responseCode, e );
     180                        google.maps.Event.trigger( this, "dataloadfailed", responseCode, e );
    186181                        var s = e.message;
    187182                        s += '\n' + data.substr(0,1000);
  • extensions/rv_gmaps/trunk/template/map.tpl

    r6609 r6651  
    2424<script src="{$PLUGIN_ROOT_URL}/template/page_linker.js?v={$RVM_PLUGIN_VERSION}" type="text/javascript"></script>
    2525
    26 <script src="{$PLUGIN_ROOT_URL}/template/windows_13/javascripts/prototype.js" type="text/javascript"></script>
     26{* <script src="{$PLUGIN_ROOT_URL}/template/windows_13/javascripts/prototype.js" type="text/javascript"></script> *}
     27<script src="http://ajax.googleapis.com/ajax/libs/prototype/1.6.1.0/prototype.js" type="text/javascript"></script>
    2728<link href="{$PLUGIN_ROOT_URL}/template/windows_13/themes/default.css" rel="stylesheet" type="text/css" />
    2829<link href="{$PLUGIN_ROOT_URL}/template/windows_13/themes/alphacube.css" rel="stylesheet" type="text/css" />
  • extensions/rv_gmaps/trunk/template/page_linker.js

    r3447 r6651  
    66  PageLinker.url2Map( map );
    77 
    8   GEvent.bind( this._map, "maptypechanged", this, this._regenerateUrl );
    9   GEvent.bind( this._map, "moveend", this, this._regenerateUrl );
     8  google.maps.Event.bind( this._map, "maptypechanged", this, this._regenerateUrl );
     9  google.maps.Event.bind( this._map, "moveend", this, this._regenerateUrl );
    1010  if ( this._map.isLoaded() )
    1111    this._regenerateUrl();
     
    7070    if (ll.length==2)
    7171    {
    72       var center = new GLatLng( ll[0], ll[1] );
     72      var center = new google.maps.LatLng( ll[0], ll[1] );
    7373      map.setCenter( center, zoom, mapType );
    7474    }
  • extensions/rv_gmaps/trunk/template/picture_map_content.tpl

    r6245 r6651  
    11{html_head}
    22<script src="http://maps.google.com/maps?file=api&amp;v=2&amp;key={$GMAPS_API_KEY}&amp;hl={$lang_info.code}" type="text/javascript"></script>
    3 <script src="{$PLUGIN_ROOT_URL}/template/windows_13/javascripts/prototype.js" type="text/javascript"></script>
     3{* <script src="{$PLUGIN_ROOT_URL}/template/windows_13/javascripts/prototype.js" type="text/javascript"></script> *}
     4<script src="http://ajax.googleapis.com/ajax/libs/prototype/1.6.1.0/prototype.js" type="text/javascript"></script>
    45<script src="{$PLUGIN_ROOT_URL}/template/windows_13/javascripts/window.js" type="text/javascript" defer="defer"></script>
    56<link href="{$PLUGIN_ROOT_URL}/template/windows_13/themes/default.css" rel="stylesheet" type="text/css">
     
    4041function onLoad()
    4142{
    42   if (!GBrowserIsCompatible())
    43     return;
     43        if (!GBrowserIsCompatible())
     44                return;
    4445
    45   var mapElement = document.getElementById("map");
    46   var map = new GMap2( mapElement );
    47  
    48   map.addControl(new GLargeMapControl());
    49   map.addControl(new GMapTypeControl());
    50   map.addControl(new GScaleControl());
    51 {/literal}{if isset($coordinates)}
    52   var coord = new GLatLng( {$coordinates.LAT}, {$coordinates.LON} );
    53   map.setCenter( coord, 12 );
    54   var marker = new GMarker(coord);
    55   map.addOverlay(marker);
    56 {/if}{literal}
    57   if ( !map.isLoaded() )
    58     map.setCenter( new GLatLng(0,0), 2);
    59   try {
    60     // the overview must be added after setting map center
    61     var ovcontrol = new GOverviewMapControl(new GSize(165,165));
     46        var mapElement = document.getElementById("map");
     47        var map = new GMap2( mapElement );
     48
     49        map.addControl(new GLargeMapControl());
     50        map.addControl(new GMapTypeControl());
     51        map.addControl(new GScaleControl());
     52        {/literal}{if isset($coordinates)}
     53        var coord = new google.maps.LatLng( {$coordinates.LAT}, {$coordinates.LON} );
     54        map.setCenter( coord, 12 );
     55        var marker = new google.maps.Marker(coord);
     56        map.addOverlay(marker);
     57        {/if}{literal}
     58        if ( !map.isLoaded() )
     59                map.setCenter( new google.maps.LatLng(0,0), 2);
     60        try {
     61                // the overview must be added after setting map center
     62                var ovcontrol = new GOverviewMapControl(new GSize(165,165));
    6263                map.addControl(ovcontrol);
    6364                var ov_map = ovcontrol.getOverviewMap();
    64                 GEvent.addListener(map, 'maptypechanged', function(){
     65                google.maps.Event.addListener(map, 'maptypechanged', function(){
    6566                        ov_map.setMapType(G_NORMAL_MAP);
    6667                });
    6768  }
    68   catch(e){ alert( e.message ); }
    69  
    70   map.enableDoubleClickZoom();
     69        catch(e){ alert( e.message ); }
     70
     71        map.enableDoubleClickZoom();
    7172}
    7273
    7374function blowupUrl(theUrl)
    7475{
    75   var win = new Window({
    76     title: document.title,
    77     url: theUrl,
    78     classname: "alphacube",
    79     left: 0, top: 0,
    80     width:"640", height:"480",
    81     minimizable: false,
    82     maximizable: false,
    83     draggable: false,
    84     resizable: false,
    85     destroyOnClose: true,
    86     hideEffect: Element.hide,
    87     showEffectOptions: {duration:1.5}
    88   });
     76        var win = new Window({
     77                title: document.title,
     78                url: theUrl,
     79                classname: "alphacube",
     80                left: 0, top: 0,
     81                width:"640", height:"480",
     82                minimizable: false,
     83                maximizable: false,
     84                draggable: false,
     85                resizable: false,
     86                destroyOnClose: true,
     87                hideEffect: Element.hide,
     88                showEffectOptions: {duration:1.5}
     89        });
    8990
    90   win.setConstraint(true, {top:20, left:20, bottom:30, right:20} );
    91   win.maximize();
    92   win.showCenter(true, 20, 20);
    93   return false;
     91        win.setConstraint(true, {top:20, left:20, bottom:30, right:20} );
     92        win.maximize();
     93        win.showCenter(true, 20, 20);
     94        return false;
    9495}
    9596
  • extensions/rv_gmaps/trunk/template/windows_13/javascripts/prototype.js

    r3447 r6651  
    1 /*  Prototype JavaScript framework, version 1.6.0.2
    2  *  (c) 2005-2008 Sam Stephenson
     1/*  Prototype JavaScript framework, version 1.6.1
     2 *  (c) 2005-2009 Sam Stephenson
    33 *
    44 *  Prototype is freely distributable under the terms of an MIT-style license.
     
    88
    99var Prototype = {
    10   Version: '1.6.0.2',
    11 
    12   Browser: {
    13     IE:     !!(window.attachEvent && !window.opera),
    14     Opera:  !!window.opera,
    15     WebKit: navigator.userAgent.indexOf('AppleWebKit/') > -1,
    16     Gecko:  navigator.userAgent.indexOf('Gecko') > -1 && navigator.userAgent.indexOf('KHTML') == -1,
    17     MobileSafari: !!navigator.userAgent.match(/Apple.*Mobile.*Safari/)
    18   },
     10  Version: '1.6.1',
     11
     12  Browser: (function(){
     13    var ua = navigator.userAgent;
     14    var isOpera = Object.prototype.toString.call(window.opera) == '[object Opera]';
     15    return {
     16      IE:             !!window.attachEvent && !isOpera,
     17      Opera:          isOpera,
     18      WebKit:         ua.indexOf('AppleWebKit/') > -1,
     19      Gecko:          ua.indexOf('Gecko') > -1 && ua.indexOf('KHTML') === -1,
     20      MobileSafari:   /Apple.*Mobile.*Safari/.test(ua)
     21    }
     22  })(),
    1923
    2024  BrowserFeatures: {
    2125    XPath: !!document.evaluate,
    22     ElementExtensions: !!window.HTMLElement,
    23     SpecificElementExtensions:
    24       document.createElement('div').__proto__ &&
    25       document.createElement('div').__proto__ !==
    26         document.createElement('form').__proto__
     26    SelectorsAPI: !!document.querySelector,
     27    ElementExtensions: (function() {
     28      var constructor = window.Element || window.HTMLElement;
     29      return !!(constructor && constructor.prototype);
     30    })(),
     31    SpecificElementExtensions: (function() {
     32      if (typeof window.HTMLDivElement !== 'undefined')
     33        return true;
     34
     35      var div = document.createElement('div');
     36      var form = document.createElement('form');
     37      var isSupported = false;
     38
     39      if (div['__proto__'] && (div['__proto__'] !== form['__proto__'])) {
     40        isSupported = true;
     41      }
     42
     43      div = form = null;
     44
     45      return isSupported;
     46    })()
    2747  },
    2848
     
    3858
    3959
     60var Abstract = { };
     61
     62
     63var Try = {
     64  these: function() {
     65    var returnValue;
     66
     67    for (var i = 0, length = arguments.length; i < length; i++) {
     68      var lambda = arguments[i];
     69      try {
     70        returnValue = lambda();
     71        break;
     72      } catch (e) { }
     73    }
     74
     75    return returnValue;
     76  }
     77};
     78
    4079/* Based on Alex Arnell's inheritance implementation. */
    41 var Class = {
    42   create: function() {
     80
     81var Class = (function() {
     82  function subclass() {};
     83  function create() {
    4384    var parent = null, properties = $A(arguments);
    4485    if (Object.isFunction(properties[0]))
     
    5495
    5596    if (parent) {
    56       var subclass = function() { };
    5797      subclass.prototype = parent.prototype;
    5898      klass.prototype = new subclass;
     
    67107
    68108    klass.prototype.constructor = klass;
    69 
    70109    return klass;
    71110  }
    72 };
    73 
    74 Class.Methods = {
    75   addMethods: function(source) {
     111
     112  function addMethods(source) {
    76113    var ancestor   = this.superclass && this.superclass.prototype;
    77114    var properties = Object.keys(source);
    78115
    79     if (!Object.keys({ toString: true }).length)
    80       properties.push("toString", "valueOf");
     116    if (!Object.keys({ toString: true }).length) {
     117      if (source.toString != Object.prototype.toString)
     118        properties.push("toString");
     119      if (source.valueOf != Object.prototype.valueOf)
     120        properties.push("valueOf");
     121    }
    81122
    82123    for (var i = 0, length = properties.length; i < length; i++) {
     
    84125      if (ancestor && Object.isFunction(value) &&
    85126          value.argumentNames().first() == "$super") {
    86         var method = value, value = Object.extend((function(m) {
    87           return function() { return ancestor[m].apply(this, arguments) };
    88         })(property).wrap(method), {
    89           valueOf:  function() { return method },
    90           toString: function() { return method.toString() }
    91         });
     127        var method = value;
     128        value = (function(m) {
     129          return function() { return ancestor[m].apply(this, arguments); };
     130        })(property).wrap(method);
     131
     132        value.valueOf = method.valueOf.bind(method);
     133        value.toString = method.toString.bind(method);
    92134      }
    93135      this.prototype[property] = value;
     
    96138    return this;
    97139  }
    98 };
    99 
    100 var Abstract = { };
    101 
    102 Object.extend = function(destination, source) {
    103   for (var property in source)
    104     destination[property] = source[property];
    105   return destination;
    106 };
    107 
    108 Object.extend(Object, {
    109   inspect: function(object) {
     140
     141  return {
     142    create: create,
     143    Methods: {
     144      addMethods: addMethods
     145    }
     146  };
     147})();
     148(function() {
     149
     150  var _toString = Object.prototype.toString;
     151
     152  function extend(destination, source) {
     153    for (var property in source)
     154      destination[property] = source[property];
     155    return destination;
     156  }
     157
     158  function inspect(object) {
    110159    try {
    111       if (Object.isUndefined(object)) return 'undefined';
     160      if (isUndefined(object)) return 'undefined';
    112161      if (object === null) return 'null';
    113162      return object.inspect ? object.inspect() : String(object);
     
    116165      throw e;
    117166    }
    118   },
    119 
    120   toJSON: function(object) {
     167  }
     168
     169  function toJSON(object) {
    121170    var type = typeof object;
    122171    switch (type) {
     
    129178    if (object === null) return 'null';
    130179    if (object.toJSON) return object.toJSON();
    131     if (Object.isElement(object)) return;
     180    if (isElement(object)) return;
    132181
    133182    var results = [];
    134183    for (var property in object) {
    135       var value = Object.toJSON(object[property]);
    136       if (!Object.isUndefined(value))
     184      var value = toJSON(object[property]);
     185      if (!isUndefined(value))
    137186        results.push(property.toJSON() + ': ' + value);
    138187    }
    139188
    140189    return '{' + results.join(', ') + '}';
    141   },
    142 
    143   toQueryString: function(object) {
     190  }
     191
     192  function toQueryString(object) {
    144193    return $H(object).toQueryString();
    145   },
    146 
    147   toHTML: function(object) {
     194  }
     195
     196  function toHTML(object) {
    148197    return object && object.toHTML ? object.toHTML() : String.interpret(object);
    149   },
    150 
    151   keys: function(object) {
    152     var keys = [];
     198  }
     199
     200  function keys(object) {
     201    var results = [];
    153202    for (var property in object)
    154       keys.push(property);
    155     return keys;
    156   },
    157 
    158   values: function(object) {
    159     var values = [];
     203      results.push(property);
     204    return results;
     205  }
     206
     207  function values(object) {
     208    var results = [];
    160209    for (var property in object)
    161       values.push(object[property]);
    162     return values;
    163   },
    164 
    165   clone: function(object) {
    166     return Object.extend({ }, object);
    167   },
    168 
    169   isElement: function(object) {
    170     return object && object.nodeType == 1;
    171   },
    172 
    173   isArray: function(object) {
    174     return object != null && typeof object == "object" &&
    175       'splice' in object && 'join' in object;
    176   },
    177 
    178   isHash: function(object) {
     210      results.push(object[property]);
     211    return results;
     212  }
     213
     214  function clone(object) {
     215    return extend({ }, object);
     216  }
     217
     218  function isElement(object) {
     219    return !!(object && object.nodeType == 1);
     220  }
     221
     222  function isArray(object) {
     223    return _toString.call(object) == "[object Array]";
     224  }
     225
     226
     227  function isHash(object) {
    179228    return object instanceof Hash;
    180   },
    181 
    182   isFunction: function(object) {
    183     return typeof object == "function";
    184   },
    185 
    186   isString: function(object) {
    187     return typeof object == "string";
    188   },
    189 
    190   isNumber: function(object) {
    191     return typeof object == "number";
    192   },
    193 
    194   isUndefined: function(object) {
    195     return typeof object == "undefined";
    196   }
    197 });
    198 
    199 Object.extend(Function.prototype, {
    200   argumentNames: function() {
    201     var names = this.toString().match(/^[\s\(]*function[^(]*\((.*?)\)/)[1].split(",").invoke("strip");
     229  }
     230
     231  function isFunction(object) {
     232    return typeof object === "function";
     233  }
     234
     235  function isString(object) {
     236    return _toString.call(object) == "[object String]";
     237  }
     238
     239  function isNumber(object) {
     240    return _toString.call(object) == "[object Number]";
     241  }
     242
     243  function isUndefined(object) {
     244    return typeof object === "undefined";
     245  }
     246
     247  extend(Object, {
     248    extend:        extend,
     249    inspect:       inspect,
     250    toJSON:        toJSON,
     251    toQueryString: toQueryString,
     252    toHTML:        toHTML,
     253    keys:          keys,
     254    values:        values,
     255    clone:         clone,
     256    isElement:     isElement,
     257    isArray:       isArray,
     258    isHash:        isHash,
     259    isFunction:    isFunction,
     260    isString:      isString,
     261    isNumber:      isNumber,
     262    isUndefined:   isUndefined
     263  });
     264})();
     265Object.extend(Function.prototype, (function() {
     266  var slice = Array.prototype.slice;
     267
     268  function update(array, args) {
     269    var arrayLength = array.length, length = args.length;
     270    while (length--) array[arrayLength + length] = args[length];
     271    return array;
     272  }
     273
     274  function merge(array, args) {
     275    array = slice.call(array, 0);
     276    return update(array, args);
     277  }
     278
     279  function argumentNames() {
     280    var names = this.toString().match(/^[\s\(]*function[^(]*\(([^)]*)\)/)[1]
     281      .replace(/\/\/.*?[\r\n]|\/\*(?:.|[\r\n])*?\*\//g, '')
     282      .replace(/\s+/g, '').split(',');
    202283    return names.length == 1 && !names[0] ? [] : names;
    203   },
    204 
    205   bind: function() {
     284  }
     285
     286  function bind(context) {
    206287    if (arguments.length < 2 && Object.isUndefined(arguments[0])) return this;
    207     var __method = this, args = $A(arguments), object = args.shift();
     288    var __method = this, args = slice.call(arguments, 1);
    208289    return function() {
    209       return __method.apply(object, args.concat($A(arguments)));
    210     }
    211   },
    212 
    213   bindAsEventListener: function() {
    214     var __method = this, args = $A(arguments), object = args.shift();
     290      var a = merge(args, arguments);
     291      return __method.apply(context, a);
     292    }
     293  }
     294
     295  function bindAsEventListener(context) {
     296    var __method = this, args = slice.call(arguments, 1);
    215297    return function(event) {
    216       return __method.apply(object, [event || window.event].concat(args));
    217     }
    218   },
    219 
    220   curry: function() {
     298      var a = update([event || window.event], args);
     299      return __method.apply(context, a);
     300    }
     301  }
     302
     303  function curry() {
    221304    if (!arguments.length) return this;
    222     var __method = this, args = $A(arguments);
     305    var __method = this, args = slice.call(arguments, 0);
    223306    return function() {
    224       return __method.apply(this, args.concat($A(arguments)));
    225     }
    226   },
    227 
    228   delay: function() {
    229     var __method = this, args = $A(arguments), timeout = args.shift() * 1000;
     307      var a = merge(args, arguments);
     308      return __method.apply(this, a);
     309    }
     310  }
     311
     312  function delay(timeout) {
     313    var __method = this, args = slice.call(arguments, 1);
     314    timeout = timeout * 1000
    230315    return window.setTimeout(function() {
    231316      return __method.apply(__method, args);
    232317    }, timeout);
    233   },
    234 
    235   wrap: function(wrapper) {
     318  }
     319
     320  function defer() {
     321    var args = update([0.01], arguments);
     322    return this.delay.apply(this, args);
     323  }
     324
     325  function wrap(wrapper) {
    236326    var __method = this;
    237327    return function() {
    238       return wrapper.apply(this, [__method.bind(this)].concat($A(arguments)));
    239     }
    240   },
    241 
    242   methodize: function() {
     328      var a = update([__method.bind(this)], arguments);
     329      return wrapper.apply(this, a);
     330    }
     331  }
     332
     333  function methodize() {
    243334    if (this._methodized) return this._methodized;
    244335    var __method = this;
    245336    return this._methodized = function() {
    246       return __method.apply(null, [this].concat($A(arguments)));
     337      var a = update([this], arguments);
     338      return __method.apply(null, a);
    247339    };
    248340  }
    249 });
    250 
    251 Function.prototype.defer = Function.prototype.delay.curry(0.01);
     341
     342  return {
     343    argumentNames:       argumentNames,
     344    bind:                bind,
     345    bindAsEventListener: bindAsEventListener,
     346    curry:               curry,
     347    delay:               delay,
     348    defer:               defer,
     349    wrap:                wrap,
     350    methodize:           methodize
     351  }
     352})());
     353
    252354
    253355Date.prototype.toJSON = function() {
     
    260362};
    261363
    262 var Try = {
    263   these: function() {
    264     var returnValue;
    265 
    266     for (var i = 0, length = arguments.length; i < length; i++) {
    267       var lambda = arguments[i];
    268       try {
    269         returnValue = lambda();
    270         break;
    271       } catch (e) { }
    272     }
    273 
    274     return returnValue;
    275   }
    276 };
    277364
    278365RegExp.prototype.match = RegExp.prototype.test;
     
    281368  return String(str).replace(/([.*+?^=!:${}()|[\]\/\\])/g, '\\$1');
    282369};
    283 
    284 /*--------------------------------------------------------------------------*/
    285 
    286370var PeriodicalExecuter = Class.create({
    287371  initialize: function(callback, frequency) {
     
    312396        this.currentlyExecuting = true;
    313397        this.execute();
    314       } finally {
    315398        this.currentlyExecuting = false;
     399      } catch(e) {
     400        this.currentlyExecuting = false;
     401        throw e;
    316402      }
    317403    }
     
    332418});
    333419
    334 Object.extend(String.prototype, {
    335   gsub: function(pattern, replacement) {
     420Object.extend(String.prototype, (function() {
     421
     422  function prepareReplacement(replacement) {
     423    if (Object.isFunction(replacement)) return replacement;
     424    var template = new Template(replacement);
     425    return function(match) { return template.evaluate(match) };
     426  }
     427
     428  function gsub(pattern, replacement) {
    336429    var result = '', source = this, match;
    337     replacement = arguments.callee.prepareReplacement(replacement);
     430    replacement = prepareReplacement(replacement);
     431
     432    if (Object.isString(pattern))
     433      pattern = RegExp.escape(pattern);
     434
     435    if (!(pattern.length || pattern.source)) {
     436      replacement = replacement('');
     437      return replacement + source.split('').join(replacement) + replacement;
     438    }
    338439
    339440    while (source.length > 0) {
     
    347448    }
    348449    return result;
    349   },
    350 
    351   sub: function(pattern, replacement, count) {
    352     replacement = this.gsub.prepareReplacement(replacement);
     450  }
     451
     452  function sub(pattern, replacement, count) {
     453    replacement = prepareReplacement(replacement);
    353454    count = Object.isUndefined(count) ? 1 : count;
    354455
     
    357458      return replacement(match);
    358459    });
    359   },
    360 
    361   scan: function(pattern, iterator) {
     460  }
     461
     462  function scan(pattern, iterator) {
    362463    this.gsub(pattern, iterator);
    363464    return String(this);
    364   },
    365 
    366   truncate: function(length, truncation) {
     465  }
     466
     467  function truncate(length, truncation) {
    367468    length = length || 30;
    368469    truncation = Object.isUndefined(truncation) ? '...' : truncation;
    369470    return this.length > length ?
    370471      this.slice(0, length - truncation.length) + truncation : String(this);
    371   },
    372 
    373   strip: function() {
     472  }
     473
     474  function strip() {
    374475    return this.replace(/^\s+/, '').replace(/\s+$/, '');
    375   },
    376 
    377   stripTags: function() {
    378     return this.replace(/<\/?[^>]+>/gi, '');
    379   },
    380 
    381   stripScripts: function() {
     476  }
     477
     478  function stripTags() {
     479    return this.replace(/<\w+(\s+("[^"]*"|'[^']*'|[^>])+)?>|<\/\w+>/gi, '');
     480  }
     481
     482  function stripScripts() {
    382483    return this.replace(new RegExp(Prototype.ScriptFragment, 'img'), '');
    383   },
    384 
    385   extractScripts: function() {
     484  }
     485
     486  function extractScripts() {
    386487    var matchAll = new RegExp(Prototype.ScriptFragment, 'img');
    387488    var matchOne = new RegExp(Prototype.ScriptFragment, 'im');
     
    389490      return (scriptTag.match(matchOne) || ['', ''])[1];
    390491    });
    391   },
    392 
    393   evalScripts: function() {
     492  }
     493
     494  function evalScripts() {
    394495    return this.extractScripts().map(function(script) { return eval(script) });
    395   },
    396 
    397   escapeHTML: function() {
    398     var self = arguments.callee;
    399     self.text.data = this;
    400     return self.div.innerHTML;
    401   },
    402 
    403   unescapeHTML: function() {
    404     var div = new Element('div');
    405     div.innerHTML = this.stripTags();
    406     return div.childNodes[0] ? (div.childNodes.length > 1 ?
    407       $A(div.childNodes).inject('', function(memo, node) { return memo+node.nodeValue }) :
    408       div.childNodes[0].nodeValue) : '';
    409   },
    410 
    411   toQueryParams: function(separator) {
     496  }
     497
     498  function escapeHTML() {
     499    return this.replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;');
     500  }
     501
     502  function unescapeHTML() {
     503    return this.stripTags().replace(/&lt;/g,'<').replace(/&gt;/g,'>').replace(/&amp;/g,'&');
     504  }
     505
     506
     507  function toQueryParams(separator) {
    412508    var match = this.strip().match(/([^?#]*)(#.*)?$/);
    413509    if (!match) return { };
     
    427523      return hash;
    428524    });
    429   },
    430 
    431   toArray: function() {
     525  }
     526
     527  function toArray() {
    432528    return this.split('');
    433   },
    434 
    435   succ: function() {
     529  }
     530
     531  function succ() {
    436532    return this.slice(0, this.length - 1) +
    437533      String.fromCharCode(this.charCodeAt(this.length - 1) + 1);
    438   },
    439 
    440   times: function(count) {
     534  }
     535
     536  function times(count) {
    441537    return count < 1 ? '' : new Array(count + 1).join(this);
    442   },
    443 
    444   camelize: function() {
     538  }
     539
     540  function camelize() {
    445541    var parts = this.split('-'), len = parts.length;
    446542    if (len == 1) return parts[0];
     
    454550
    455551    return camelized;
    456   },
    457 
    458   capitalize: function() {
     552  }
     553
     554  function capitalize() {
    459555    return this.charAt(0).toUpperCase() + this.substring(1).toLowerCase();
    460   },
    461 
    462   underscore: function() {
    463     return this.gsub(/::/, '/').gsub(/([A-Z]+)([A-Z][a-z])/,'#{1}_#{2}').gsub(/([a-z\d])([A-Z])/,'#{1}_#{2}').gsub(/-/,'_').toLowerCase();
    464   },
    465 
    466   dasherize: function() {
    467     return this.gsub(/_/,'-');
    468   },
    469 
    470   inspect: function(useDoubleQuotes) {
    471     var escapedString = this.gsub(/[\x00-\x1f\\]/, function(match) {
    472       var character = String.specialChar[match[0]];
    473       return character ? character : '\\u00' + match[0].charCodeAt().toPaddedString(2, 16);
     556  }
     557
     558  function underscore() {
     559    return this.replace(/::/g, '/')
     560               .replace(/([A-Z]+)([A-Z][a-z])/g, '$1_$2')
     561               .replace(/([a-z\d])([A-Z])/g, '$1_$2')
     562               .replace(/-/g, '_')
     563               .toLowerCase();
     564  }
     565
     566  function dasherize() {
     567    return this.replace(/_/g, '-');
     568  }
     569
     570  function inspect(useDoubleQuotes) {
     571    var escapedString = this.replace(/[\x00-\x1f\\]/g, function(character) {
     572      if (character in String.specialChar) {
     573        return String.specialChar[character];
     574      }
     575      return '\\u00' + character.charCodeAt().toPaddedString(2, 16);
    474576    });
    475577    if (useDoubleQuotes) return '"' + escapedString.replace(/"/g, '\\"') + '"';
    476578    return "'" + escapedString.replace(/'/g, '\\\'') + "'";
    477   },
    478 
    479   toJSON: function() {
     579  }
     580
     581  function toJSON() {
    480582    return this.inspect(true);
    481   },
    482 
    483   unfilterJSON: function(filter) {
    484     return this.sub(filter || Prototype.JSONFilter, '#{1}');
    485   },
    486 
    487   isJSON: function() {
     583  }
     584
     585  function unfilterJSON(filter) {
     586    return this.replace(filter || Prototype.JSONFilter, '$1');
     587  }
     588
     589  function isJSON() {
    488590    var str = this;
    489591    if (str.blank()) return false;
    490592    str = this.replace(/\\./g, '@').replace(/"[^"\\\n\r]*"/g, '');
    491593    return (/^[,:{}\[\]0-9.\-+Eaeflnr-u \n\r\t]*$/).test(str);
    492   },
    493 
    494   evalJSON: function(sanitize) {
     594  }
     595
     596  function evalJSON(sanitize) {
    495597    var json = this.unfilterJSON();
    496598    try {
     
    498600    } catch (e) { }
    499601    throw new SyntaxError('Badly formed JSON string: ' + this.inspect());
    500   },
    501 
    502   include: function(pattern) {
     602  }
     603
     604  function include(pattern) {
    503605    return this.indexOf(pattern) > -1;
    504   },
    505 
    506   startsWith: function(pattern) {
     606  }
     607
     608  function startsWith(pattern) {
    507609    return this.indexOf(pattern) === 0;
    508   },
    509 
    510   endsWith: function(pattern) {
     610  }
     611
     612  function endsWith(pattern) {
    511613    var d = this.length - pattern.length;
    512614    return d >= 0 && this.lastIndexOf(pattern) === d;
    513   },
    514 
    515   empty: function() {
     615  }
     616
     617  function empty() {
    516618    return this == '';
    517   },
    518 
    519   blank: function() {
     619  }
     620
     621  function blank() {
    520622    return /^\s*$/.test(this);
    521   },
    522 
    523   interpolate: function(object, pattern) {
     623  }
     624
     625  function interpolate(object, pattern) {
    524626    return new Template(this, pattern).evaluate(object);
    525627  }
    526 });
    527 
    528 if (Prototype.Browser.WebKit || Prototype.Browser.IE) Object.extend(String.prototype, {
    529   escapeHTML: function() {
    530     return this.replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;');
    531   },
    532   unescapeHTML: function() {
    533     return this.replace(/&amp;/g,'&').replace(/&lt;/g,'<').replace(/&gt;/g,'>');
    534   }
    535 });
    536 
    537 String.prototype.gsub.prepareReplacement = function(replacement) {
    538   if (Object.isFunction(replacement)) return replacement;
    539   var template = new Template(replacement);
    540   return function(match) { return template.evaluate(match) };
    541 };
    542 
    543 String.prototype.parseQuery = String.prototype.toQueryParams;
    544 
    545 Object.extend(String.prototype.escapeHTML, {
    546   div:  document.createElement('div'),
    547   text: document.createTextNode('')
    548 });
    549 
    550 with (String.prototype.escapeHTML) div.appendChild(text);
     628
     629  return {
     630    gsub:           gsub,
     631    sub:            sub,
     632    scan:           scan,
     633    truncate:       truncate,
     634    strip:          String.prototype.trim ? String.prototype.trim : strip,
     635    stripTags:      stripTags,
     636    stripScripts:   stripScripts,
     637    extractScripts: extractScripts,
     638    evalScripts:    evalScripts,
     639    escapeHTML:     escapeHTML,
     640    unescapeHTML:   unescapeHTML,
     641    toQueryParams:  toQueryParams,
     642    parseQuery:     toQueryParams,
     643    toArray:        toArray,
     644    succ:           succ,
     645    times:          times,
     646    camelize:       camelize,
     647    capitalize:     capitalize,
     648    underscore:     underscore,
     649    dasherize:      dasherize,
     650    inspect:        inspect,
     651    toJSON:         toJSON,
     652    unfilterJSON:   unfilterJSON,
     653    isJSON:         isJSON,
     654    evalJSON:       evalJSON,
     655    include:        include,
     656    startsWith:     startsWith,
     657    endsWith:       endsWith,
     658    empty:          empty,
     659    blank:          blank,
     660    interpolate:    interpolate
     661  };
     662})());
    551663
    552664var Template = Class.create({
     
    557669
    558670  evaluate: function(object) {
    559     if (Object.isFunction(object.toTemplateReplacements))
     671    if (object && Object.isFunction(object.toTemplateReplacements))
    560672      object = object.toTemplateReplacements();
    561673
    562674    return this.template.gsub(this.pattern, function(match) {
    563       if (object == null) return '';
     675      if (object == null) return (match[1] + '');
    564676
    565677      var before = match[1] || '';
     
    572684
    573685      while (match != null) {
    574         var comp = match[1].startsWith('[') ? match[2].gsub('\\\\]', ']') : match[1];
     686        var comp = match[1].startsWith('[') ? match[2].replace(/\\\\]/g, ']') : match[1];
    575687        ctx = ctx[comp];
    576688        if (null == ctx || '' == match[3]) break;
     
    587699var $break = { };
    588700
    589 var Enumerable = {
    590   each: function(iterator, context) {
     701var Enumerable = (function() {
     702  function each(iterator, context) {
    591703    var index = 0;
    592     iterator = iterator.bind(context);
    593704    try {
    594705      this._each(function(value) {
    595         iterator(value, index++);
     706        iterator.call(context, value, index++);
    596707      });
    597708    } catch (e) {
     
    599710    }
    600711    return this;
    601   },
    602 
    603   eachSlice: function(number, iterator, context) {
    604     iterator = iterator ? iterator.bind(context) : Prototype.K;
     712  }
     713
     714  function eachSlice(number, iterator, context) {
    605715    var index = -number, slices = [], array = this.toArray();
     716    if (number < 1) return array;
    606717    while ((index += number) < array.length)
    607718      slices.push(array.slice(index, index+number));
    608719    return slices.collect(iterator, context);
    609   },
    610 
    611   all: function(iterator, context) {
    612     iterator = iterator ? iterator.bind(context) : Prototype.K;
     720  }
     721
     722  function all(iterator, context) {
     723    iterator = iterator || Prototype.K;
    613724    var result = true;
    614725    this.each(function(value, index) {
    615       result = result && !!iterator(value, index);
     726      result = result && !!iterator.call(context, value, index);
    616727      if (!result) throw $break;
    617728    });
    618729    return result;
    619   },
    620 
    621   any: function(iterator, context) {
    622     iterator = iterator ? iterator.bind(context) : Prototype.K;
     730  }
     731
     732  function any(iterator, context) {
     733    iterator = iterator || Prototype.K;
    623734    var result = false;
    624735    this.each(function(value, index) {
    625       if (result = !!iterator(value, index))
     736      if (result = !!iterator.call(context, value, index))
    626737        throw $break;
    627738    });
    628739    return result;
    629   },
    630 
    631   collect: function(iterator, context) {
    632     iterator = iterator ? iterator.bind(context) : Prototype.K;
     740  }
     741
     742  function collect(iterator, context) {
     743    iterator = iterator || Prototype.K;
    633744    var results = [];
    634745    this.each(function(value, index) {
    635       results.push(iterator(value, index));
     746      results.push(iterator.call(context, value, index));
    636747    });
    637748    return results;
    638   },
    639 
    640   detect: function(iterator, context) {
    641     iterator = iterator.bind(context);
     749  }
     750
     751  function detect(iterator, context) {
    642752    var result;
    643753    this.each(function(value, index) {
    644       if (iterator(value, index)) {
     754      if (iterator.call(context, value, index)) {
    645755        result = value;
    646756        throw $break;
     
    648758    });
    649759    return result;
    650   },
    651 
    652   findAll: function(iterator, context) {
    653     iterator = iterator.bind(context);
     760  }
     761
     762  function findAll(iterator, context) {
    654763    var results = [];
    655764    this.each(function(value, index) {
    656       if (iterator(value, index))
     765      if (iterator.call(context, value, index))
    657766        results.push(value);
    658767    });
    659768    return results;
    660   },
    661 
    662   grep: function(filter, iterator, context) {
    663     iterator = iterator ? iterator.bind(context) : Prototype.K;
     769  }
     770
     771  function grep(filter, iterator, context) {
     772    iterator = iterator || Prototype.K;
    664773    var results = [];
    665774
    666775    if (Object.isString(filter))
    667       filter = new RegExp(filter);
     776      filter = new RegExp(RegExp.escape(filter));
    668777
    669778    this.each(function(value, index) {
    670779      if (filter.match(value))
    671         results.push(iterator(value, index));
     780        results.push(iterator.call(context, value, index));
    672781    });
    673782    return results;
    674   },
    675 
    676   include: function(object) {
     783  }
     784
     785  function include(object) {
    677786    if (Object.isFunction(this.indexOf))
    678787      if (this.indexOf(object) != -1) return true;
     
    686795    });
    687796    return found;
    688   },
    689 
    690   inGroupsOf: function(number, fillWith) {
     797  }
     798
     799  function inGroupsOf(number, fillWith) {
    691800    fillWith = Object.isUndefined(fillWith) ? null : fillWith;
    692801    return this.eachSlice(number, function(slice) {
     
    694803      return slice;
    695804    });
    696   },
    697 
    698   inject: function(memo, iterator, context) {
    699     iterator = iterator.bind(context);
     805  }
     806
     807  function inject(memo, iterator, context) {
    700808    this.each(function(value, index) {
    701       memo = iterator(memo, value, index);
     809      memo = iterator.call(context, memo, value, index);
    702810    });
    703811    return memo;
    704   },
    705 
    706   invoke: function(method) {
     812  }
     813
     814  function invoke(method) {
    707815    var args = $A(arguments).slice(1);
    708816    return this.map(function(value) {
    709817      return value[method].apply(value, args);
    710818    });
    711   },
    712 
    713   max: function(iterator, context) {
    714     iterator = iterator ? iterator.bind(context) : Prototype.K;
     819  }
     820
     821  function max(iterator, context) {
     822    iterator = iterator || Prototype.K;
    715823    var result;
    716824    this.each(function(value, index) {
    717       value = iterator(value, index);
     825      value = iterator.call(context, value, index);
    718826      if (result == null || value >= result)
    719827        result = value;
    720828    });
    721829    return result;
    722   },
    723 
    724   min: function(iterator, context) {
    725     iterator = iterator ? iterator.bind(context) : Prototype.K;
     830  }
     831
     832  function min(iterator, context) {
     833    iterator = iterator || Prototype.K;
    726834    var result;
    727835    this.each(function(value, index) {
    728       value = iterator(value, index);
     836      value = iterator.call(context, value, index);
    729837      if (result == null || value < result)
    730838        result = value;
    731839    });
    732840    return result;
    733   },
    734 
    735   partition: function(iterator, context) {
    736     iterator = iterator ? iterator.bind(context) : Prototype.K;
     841  }
     842
     843  function partition(iterator, context) {
     844    iterator = iterator || Prototype.K;
    737845    var trues = [], falses = [];
    738846    this.each(function(value, index) {
    739       (iterator(value, index) ?
     847      (iterator.call(context, value, index) ?
    740848        trues : falses).push(value);
    741849    });
    742850    return [trues, falses];
    743   },
    744 
    745   pluck: function(property) {
     851  }
     852
     853  function pluck(property) {
    746854    var results = [];
    747855    this.each(function(value) {
     
    749857    });
    750858    return results;
    751   },
    752 
    753   reject: function(iterator, context) {
    754     iterator = iterator.bind(context);
     859  }
     860
     861  function reject(iterator, context) {
    755862    var results = [];
    756863    this.each(function(value, index) {
    757       if (!iterator(value, index))
     864      if (!iterator.call(context, value, index))
    758865        results.push(value);
    759866    });
    760867    return results;
    761   },
    762 
    763   sortBy: function(iterator, context) {
    764     iterator = iterator.bind(context);
     868  }
     869
     870  function sortBy(iterator, context) {
    765871    return this.map(function(value, index) {
    766       return {value: value, criteria: iterator(value, index)};
     872      return {
     873        value: value,
     874        criteria: iterator.call(context, value, index)
     875      };
    767876    }).sort(function(left, right) {
    768877      var a = left.criteria, b = right.criteria;
    769878      return a < b ? -1 : a > b ? 1 : 0;
    770879    }).pluck('value');
    771   },
    772 
    773   toArray: function() {
     880  }
     881
     882  function toArray() {
    774883    return this.map();
    775   },
    776 
    777   zip: function() {
     884  }
     885
     886  function zip() {
    778887    var iterator = Prototype.K, args = $A(arguments);
    779888    if (Object.isFunction(args.last()))
     
    784893      return iterator(collections.pluck(index));
    785894    });
    786   },
    787 
    788   size: function() {
     895  }
     896
     897  function size() {
    789898    return this.toArray().length;
    790   },
    791 
    792   inspect: function() {
     899  }
     900
     901  function inspect() {
    793902    return '#<Enumerable:' + this.toArray().inspect() + '>';
    794903  }
    795 };
    796 
    797 Object.extend(Enumerable, {
    798   map:     Enumerable.collect,
    799   find:    Enumerable.detect,
    800   select:  Enumerable.findAll,
    801   filter:  Enumerable.findAll,
    802   member:  Enumerable.include,
    803   entries: Enumerable.toArray,
    804   every:   Enumerable.all,
    805   some:    Enumerable.any
    806 });
     904
     905
     906
     907
     908
     909
     910
     911
     912
     913  return {
     914    each:       each,
     915    eachSlice:  eachSlice,
     916    all:        all,
     917    every:      all,
     918    any:        any,
     919    some:       any,
     920    collect:    collect,
     921    map:        collect,
     922    detect:     detect,
     923    findAll:    findAll,
     924    select:     findAll,
     925    filter:     findAll,
     926    grep:       grep,
     927    include:    include,
     928    member:     include,
     929    inGroupsOf: inGroupsOf,
     930    inject:     inject,
     931    invoke:     invoke,
     932    max:        max,
     933    min:        min,
     934    partition:  partition,
     935    pluck:      pluck,
     936    reject:     reject,
     937    sortBy:     sortBy,
     938    toArray:    toArray,
     939    entries:    toArray,
     940    zip:        zip,
     941    size:       size,
     942    inspect:    inspect,
     943    find:       detect
     944  };
     945})();
    807946function $A(iterable) {
    808947  if (!iterable) return [];
    809   if (iterable.toArray) return iterable.toArray();
     948  if ('toArray' in Object(iterable)) return iterable.toArray();
    810949  var length = iterable.length || 0, results = new Array(length);
    811950  while (length--) results[length] = iterable[length];
     
    813952}
    814953
    815 if (Prototype.Browser.WebKit) {
    816   $A = function(iterable) {
    817     if (!iterable) return [];
    818     if (!(Object.isFunction(iterable) && iterable == '[object NodeList]') &&
    819         iterable.toArray) return iterable.toArray();
    820     var length = iterable.length || 0, results = new Array(length);
    821     while (length--) results[length] = iterable[length];
    822     return results;
    823   };
     954function $w(string) {
     955  if (!Object.isString(string)) return [];
     956  string = string.strip();
     957  return string ? string.split(/\s+/) : [];
    824958}
    825959
    826960Array.from = $A;
    827961
    828 Object.extend(Array.prototype, Enumerable);
    829 
    830 if (!Array.prototype._reverse) Array.prototype._reverse = Array.prototype.reverse;
    831 
    832 Object.extend(Array.prototype, {
    833   _each: function(iterator) {
     962
     963(function() {
     964  var arrayProto = Array.prototype,
     965      slice = arrayProto.slice,
     966      _each = arrayProto.forEach; // use native browser JS 1.6 implementation if available
     967
     968  function each(iterator) {
    834969    for (var i = 0, length = this.length; i < length; i++)
    835970      iterator(this[i]);
    836   },
    837 
    838   clear: function() {
     971  }
     972  if (!_each) _each = each;
     973
     974  function clear() {
    839975    this.length = 0;
    840976    return this;
    841   },
    842 
    843   first: function() {
     977  }
     978
     979  function first() {
    844980    return this[0];
    845   },
    846 
    847   last: function() {
     981  }
     982
     983  function last() {
    848984    return this[this.length - 1];
    849   },
    850 
    851   compact: function() {
     985  }
     986
     987  function compact() {
    852988    return this.select(function(value) {
    853989      return value != null;
    854990    });
    855   },
    856 
    857   flatten: function() {
     991  }
     992
     993  function flatten() {
    858994    return this.inject([], function(array, value) {
    859       return array.concat(Object.isArray(value) ?
    860         value.flatten() : [value]);
     995      if (Object.isArray(value))
     996        return array.concat(value.flatten());
     997      array.push(value);
     998      return array;
    861999    });
    862   },
    863 
    864   without: function() {
    865     var values = $A(arguments);
     1000  }
     1001
     1002  function without() {
     1003    var values = slice.call(arguments, 0);
    8661004    return this.select(function(value) {
    8671005      return !values.include(value);
    8681006    });
    869   },
    870 
    871   reverse: function(inline) {
     1007  }
     1008
     1009  function reverse(inline) {
    8721010    return (inline !== false ? this : this.toArray())._reverse();
    873   },
    874 
    875   reduce: function() {
    876     return this.length > 1 ? this : this[0];
    877   },
    878 
    879   uniq: function(sorted) {
     1011  }
     1012
     1013  function uniq(sorted) {
    8801014    return this.inject([], function(array, value, index) {
    8811015      if (0 == index || (sorted ? array.last() != value : !array.include(value)))
     
    8831017      return array;
    8841018    });
    885   },
    886 
    887   intersect: function(array) {
     1019  }
     1020
     1021  function intersect(array) {
    8881022    return this.uniq().findAll(function(item) {
    8891023      return array.detect(function(value) { return item === value });
    8901024    });
    891   },
    892 
    893   clone: function() {
    894     return [].concat(this);
    895   },
    896 
    897   size: function() {
     1025  }
     1026
     1027
     1028  function clone() {
     1029    return slice.call(this, 0);
     1030  }
     1031
     1032  function size() {
    8981033    return this.length;
    899   },
    900 
    901   inspect: function() {
     1034  }
     1035
     1036  function inspect() {
    9021037    return '[' + this.map(Object.inspect).join(', ') + ']';
    903   },
    904 
    905   toJSON: function() {
     1038  }
     1039
     1040  function toJSON() {
    9061041    var results = [];
    9071042    this.each(function(object) {
     
    9111046    return '[' + results.join(', ') + ']';
    9121047  }
    913 });
    914 
    915 // use native browser JS 1.6 implementation if available
    916 if (Object.isFunction(Array.prototype.forEach))
    917   Array.prototype._each = Array.prototype.forEach;
    918 
    919 if (!Array.prototype.indexOf) Array.prototype.indexOf = function(item, i) {
    920   i || (i = 0);
    921   var length = this.length;
    922   if (i < 0) i = length + i;
    923   for (; i < length; i++)
    924     if (this[i] === item) return i;
    925   return -1;
    926 };
    927 
    928 if (!Array.prototype.lastIndexOf) Array.prototype.lastIndexOf = function(item, i) {
    929   i = isNaN(i) ? this.length : (i < 0 ? this.length + i : i) + 1;
    930   var n = this.slice(0, i).reverse().indexOf(item);
    931   return (n < 0) ? n : i - n - 1;
    932 };
    933 
    934 Array.prototype.toArray = Array.prototype.clone;
    935 
    936 function $w(string) {
    937   if (!Object.isString(string)) return [];
    938   string = string.strip();
    939   return string ? string.split(/\s+/) : [];
    940 }
    941 
    942 if (Prototype.Browser.Opera){
    943   Array.prototype.concat = function() {
    944     var array = [];
    945     for (var i = 0, length = this.length; i < length; i++) array.push(this[i]);
     1048
     1049  function indexOf(item, i) {
     1050    i || (i = 0);
     1051    var length = this.length;
     1052    if (i < 0) i = length + i;
     1053    for (; i < length; i++)
     1054      if (this[i] === item) return i;
     1055    return -1;
     1056  }
     1057
     1058  function lastIndexOf(item, i) {
     1059    i = isNaN(i) ? this.length : (i < 0 ? this.length + i : i) + 1;
     1060    var n = this.slice(0, i).reverse().indexOf(item);
     1061    return (n < 0) ? n : i - n - 1;
     1062  }
     1063
     1064  function concat() {
     1065    var array = slice.call(this, 0), item;
    9461066    for (var i = 0, length = arguments.length; i < length; i++) {
    947       if (Object.isArray(arguments[i])) {
    948         for (var j = 0, arrayLength = arguments[i].length; j < arrayLength; j++)
    949           array.push(arguments[i][j]);
     1067      item = arguments[i];
     1068      if (Object.isArray(item) && !('callee' in item)) {
     1069        for (var j = 0, arrayLength = item.length; j < arrayLength; j++)
     1070          array.push(item[j]);
    9501071      } else {
    951         array.push(arguments[i]);
     1072        array.push(item);
    9521073      }
    9531074    }
    9541075    return array;
    955   };
    956 }
    957 Object.extend(Number.prototype, {
    958   toColorPart: function() {
    959     return this.toPaddedString(2, 16);
    960   },
    961 
    962   succ: function() {
    963     return this + 1;
    964   },
    965 
    966   times: function(iterator) {
    967     $R(0, this, true).each(iterator);
    968     return this;
    969   },
    970 
    971   toPaddedString: function(length, radix) {
    972     var string = this.toString(radix || 10);
    973     return '0'.times(length - string.length) + string;
    974   },
    975 
    976   toJSON: function() {
    977     return isFinite(this) ? this.toString() : 'null';
    978   }
    979 });
    980 
    981 $w('abs round ceil floor').each(function(method){
    982   Number.prototype[method] = Math[method].methodize();
    983 });
     1076  }
     1077
     1078  Object.extend(arrayProto, Enumerable);
     1079
     1080  if (!arrayProto._reverse)
     1081    arrayProto._reverse = arrayProto.reverse;
     1082
     1083  Object.extend(arrayProto, {
     1084    _each:     _each,
     1085    clear:     clear,
     1086    first:     first,
     1087    last:      last,
     1088    compact:   compact,
     1089    flatten:   flatten,
     1090    without:   without,
     1091    reverse:   reverse,
     1092    uniq:      uniq,
     1093    intersect: intersect,
     1094    clone:     clone,
     1095    toArray:   clone,
     1096    size:      size,
     1097    inspect:   inspect,
     1098    toJSON:    toJSON
     1099  });
     1100
     1101  var CONCAT_ARGUMENTS_BUGGY = (function() {
     1102    return [].concat(arguments)[0][0] !== 1;
     1103  })(1,2)
     1104
     1105  if (CONCAT_ARGUMENTS_BUGGY) arrayProto.concat = concat;
     1106
     1107  if (!arrayProto.indexOf) arrayProto.indexOf = indexOf;
     1108  if (!arrayProto.lastIndexOf) arrayProto.lastIndexOf = lastIndexOf;
     1109})();
    9841110function $H(object) {
    9851111  return new Hash(object);
     
    9871113
    9881114var Hash = Class.create(Enumerable, (function() {
     1115  function initialize(object) {
     1116    this._object = Object.isHash(object) ? object.toObject() : Object.clone(object);
     1117  }
     1118
     1119  function _each(iterator) {
     1120    for (var key in this._object) {
     1121      var value = this._object[key], pair = [key, value];
     1122      pair.key = key;
     1123      pair.value = value;
     1124      iterator(pair);
     1125    }
     1126  }
     1127
     1128  function set(key, value) {
     1129    return this._object[key] = value;
     1130  }
     1131
     1132  function get(key) {
     1133    if (this._object[key] !== Object.prototype[key])
     1134      return this._object[key];
     1135  }
     1136
     1137  function unset(key) {
     1138    var value = this._object[key];
     1139    delete this._object[key];
     1140    return value;
     1141  }
     1142
     1143  function toObject() {
     1144    return Object.clone(this._object);
     1145  }
     1146
     1147  function keys() {
     1148    return this.pluck('key');
     1149  }
     1150
     1151  function values() {
     1152    return this.pluck('value');
     1153  }
     1154
     1155  function index(value) {
     1156    var match = this.detect(function(pair) {
     1157      return pair.value === value;
     1158    });
     1159    return match && match.key;
     1160  }
     1161
     1162  function merge(object) {
     1163    return this.clone().update(object);
     1164  }
     1165
     1166  function update(object) {
     1167    return new Hash(object).inject(this, function(result, pair) {
     1168      result.set(pair.key, pair.value);
     1169      return result;
     1170    });
     1171  }
    9891172
    9901173  function toQueryPair(key, value) {
     
    9931176  }
    9941177
     1178  function toQueryString() {
     1179    return this.inject([], function(results, pair) {
     1180      var key = encodeURIComponent(pair.key), values = pair.value;
     1181
     1182      if (values && typeof values == 'object') {
     1183        if (Object.isArray(values))
     1184          return results.concat(values.map(toQueryPair.curry(key)));
     1185      } else results.push(toQueryPair(key, values));
     1186      return results;
     1187    }).join('&');
     1188  }
     1189
     1190  function inspect() {
     1191    return '#<Hash:{' + this.map(function(pair) {
     1192      return pair.map(Object.inspect).join(': ');
     1193    }).join(', ') + '}>';
     1194  }
     1195
     1196  function toJSON() {
     1197    return Object.toJSON(this.toObject());
     1198  }
     1199
     1200  function clone() {
     1201    return new Hash(this);
     1202  }
     1203
    9951204  return {
    996     initialize: function(object) {
    997       this._object = Object.isHash(object) ? object.toObject() : Object.clone(object);
    998     },
    999 
    1000     _each: function(iterator) {
    1001       for (var key in this._object) {
    1002         var value = this._object[key], pair = [key, value];
    1003         pair.key = key;
    1004         pair.value = value;
    1005         iterator(pair);
    1006       }
    1007     },
    1008 
    1009     set: function(key, value) {
    1010       return this._object[key] = value;
    1011     },
    1012 
    1013     get: function(key) {
    1014       return this._object[key];
    1015     },
    1016 
    1017     unset: function(key) {
    1018       var value = this._object[key];
    1019       delete this._object[key];
    1020       return value;
    1021     },
    1022 
    1023     toObject: function() {
    1024       return Object.clone(this._object);
    1025     },
    1026 
    1027     keys: function() {
    1028       return this.pluck('key');
    1029     },
    1030 
    1031     values: function() {
    1032       return this.pluck('value');
    1033     },
    1034 
    1035     index: function(value) {
    1036       var match = this.detect(function(pair) {
    1037         return pair.value === value;
    1038       });
    1039       return match && match.key;
    1040     },
    1041 
    1042     merge: function(object) {
    1043       return this.clone().update(object);
    1044     },
    1045 
    1046     update: function(object) {
    1047       return new Hash(object).inject(this, function(result, pair) {
    1048         result.set(pair.key, pair.value);
    1049         return result;
    1050       });
    1051     },
    1052 
    1053     toQueryString: function() {
    1054       return this.map(function(pair) {
    1055         var key = encodeURIComponent(pair.key), values = pair.value;
    1056 
    1057         if (values && typeof values == 'object') {
    1058           if (Object.isArray(values))
    1059             return values.map(toQueryPair.curry(key)).join('&');
    1060         }
    1061         return toQueryPair(key, values);
    1062       }).join('&');
    1063     },
    1064 
    1065     inspect: function() {
    1066       return '#<Hash:{' + this.map(function(pair) {
    1067         return pair.map(Object.inspect).join(': ');
    1068       }).join(', ') + '}>';
    1069     },
    1070 
    1071     toJSON: function() {
    1072       return Object.toJSON(this.toObject());
    1073     },
    1074 
    1075     clone: function() {
    1076       return new Hash(this);
    1077     }
    1078   }
     1205    initialize:             initialize,
     1206    _each:                  _each,
     1207    set:                    set,
     1208    get:                    get,
     1209    unset:                  unset,
     1210    toObject:               toObject,
     1211    toTemplateReplacements: toObject,
     1212    keys:                   keys,
     1213    values:                 values,
     1214    index:                  index,
     1215    merge:                  merge,
     1216    update:                 update,
     1217    toQueryString:          toQueryString,
     1218    inspect:                inspect,
     1219    toJSON:                 toJSON,
     1220    clone:                  clone
     1221  };
    10791222})());
    10801223
    1081 Hash.prototype.toTemplateReplacements = Hash.prototype.toObject;
    10821224Hash.from = $H;
    1083 var ObjectRange = Class.create(Enumerable, {
    1084   initialize: function(start, end, exclusive) {
     1225Object.extend(Number.prototype, (function() {
     1226  function toColorPart() {
     1227    return this.toPaddedString(2, 16);
     1228  }
     1229
     1230  function succ() {
     1231    return this + 1;
     1232  }
     1233
     1234  function times(iterator, context) {
     1235    $R(0, this, true).each(iterator, context);
     1236    return this;
     1237  }
     1238
     1239  function toPaddedString(length, radix) {
     1240    var string = this.toString(radix || 10);
     1241    return '0'.times(length - string.length) + string;
     1242  }
     1243
     1244  function toJSON() {
     1245    return isFinite(this) ? this.toString() : 'null';
     1246  }
     1247
     1248  function abs() {
     1249    return Math.abs(this);
     1250  }
     1251
     1252  function round() {
     1253    return Math.round(this);
     1254  }
     1255
     1256  function ceil() {
     1257    return Math.ceil(this);
     1258  }
     1259
     1260  function floor() {
     1261    return Math.floor(this);
     1262  }
     1263
     1264  return {
     1265    toColorPart:    toColorPart,
     1266    succ:           succ,
     1267    times:          times,
     1268    toPaddedString: toPaddedString,
     1269    toJSON:         toJSON,
     1270    abs:            abs,
     1271    round:          round,
     1272    ceil:           ceil,
     1273    floor:          floor
     1274  };
     1275})());
     1276
     1277function $R(start, end, exclusive) {
     1278  return new ObjectRange(start, end, exclusive);
     1279}
     1280
     1281var ObjectRange = Class.create(Enumerable, (function() {
     1282  function initialize(start, end, exclusive) {
    10851283    this.start = start;
    10861284    this.end = end;
    10871285    this.exclusive = exclusive;
    1088   },
    1089 
    1090   _each: function(iterator) {
     1286  }
     1287
     1288  function _each(iterator) {
    10911289    var value = this.start;
    10921290    while (this.include(value)) {
     
    10941292      value = value.succ();
    10951293    }
    1096   },
    1097 
    1098   include: function(value) {
     1294  }
     1295
     1296  function include(value) {
    10991297    if (value < this.start)
    11001298      return false;
     
    11031301    return value <= this.end;
    11041302  }
    1105 });
    1106 
    1107 var $R = function(start, end, exclusive) {
    1108   return new ObjectRange(start, end, exclusive);
    1109 };
     1303
     1304  return {
     1305    initialize: initialize,
     1306    _each:      _each,
     1307    include:    include
     1308  };
     1309})());
     1310
     1311
    11101312
    11111313var Ajax = {
     
    11541356  onComplete: function() { Ajax.activeRequestCount-- }
    11551357});
    1156 
    11571358Ajax.Base = Class.create({
    11581359  initialize: function(options) {
     
    11761377  }
    11771378});
    1178 
    11791379Ajax.Request = Class.create(Ajax.Base, {
    11801380  _complete: false,
     
    11921392
    11931393    if (!['get', 'post'].include(this.method)) {
    1194       // simulate other verbs over post
    11951394      params['_method'] = this.method;
    11961395      this.method = 'post';
     
    12001399
    12011400    if (params = Object.toQueryString(params)) {
    1202       // when GET, append parameters to URL
    12031401      if (this.method == 'get')
    12041402        this.url += (this.url.include('?') ? '&' : '?') + params;
     
    12591457    }
    12601458
    1261     // user-defined headers
    12621459    if (typeof this.options.requestHeaders == 'object') {
    12631460      var extras = this.options.requestHeaders;
     
    13131510
    13141511    if (state == 'Complete') {
    1315       // avoid memory leak in MSIE: clean up
    13161512      this.transport.onreadystatechange = Prototype.emptyFunction;
    13171513    }
     
    13301526    try {
    13311527      return this.transport.getResponseHeader(name) || null;
    1332     } catch (e) { return null }
     1528    } catch (e) { return null; }
    13331529  },
    13341530
     
    13501546  ['Uninitialized', 'Loading', 'Loaded', 'Interactive', 'Complete'];
    13511547
     1548
     1549
     1550
     1551
     1552
     1553
     1554
    13521555Ajax.Response = Class.create({
    13531556  initialize: function(request){
     
    13711574
    13721575  status:      0,
     1576
    13731577  statusText: '',
    13741578
     
    15001704  }
    15011705});
     1706
     1707
     1708
    15021709function $(element) {
    15031710  if (arguments.length > 1) {
     
    15271734
    15281735if (!Node.ELEMENT_NODE) {
    1529   // DOM level 2 ECMAScript Language Binding
    15301736  Object.extend(Node, {
    15311737    ELEMENT_NODE: 1,
     
    15441750}
    15451751
    1546 (function() {
    1547   var element = this.Element;
    1548   this.Element = function(tagName, attributes) {
     1752
     1753(function(global) {
     1754
     1755  var SETATTRIBUTE_IGNORES_NAME = (function(){
     1756    var elForm = document.createElement("form");
     1757    var elInput = document.createElement("input");
     1758    var root = document.documentElement;
     1759    elInput.setAttribute("name", "test");
     1760    elForm.appendChild(elInput);
     1761    root.appendChild(elForm);
     1762    var isBuggy = elForm.elements
     1763      ? (typeof elForm.elements.test == "undefined")
     1764      : null;
     1765    root.removeChild(elForm);
     1766    elForm = elInput = null;
     1767    return isBuggy;
     1768  })();
     1769
     1770  var element = global.Element;
     1771  global.Element = function(tagName, attributes) {
    15491772    attributes = attributes || { };
    15501773    tagName = tagName.toLowerCase();
    15511774    var cache = Element.cache;
    1552     if (Prototype.Browser.IE && attributes.name) {
     1775    if (SETATTRIBUTE_IGNORES_NAME && attributes.name) {
    15531776      tagName = '<' + tagName + ' name="' + attributes.name + '">';
    15541777      delete attributes.name;
     
    15581781    return Element.writeAttribute(cache[tagName].cloneNode(false), attributes);
    15591782  };
    1560   Object.extend(this.Element, element || { });
    1561 }).call(window);
     1783  Object.extend(global.Element, element || { });
     1784  if (element) global.Element.prototype = element.prototype;
     1785})(this);
    15621786
    15631787Element.cache = { };
     1788Element.idCounter = 1;
    15641789
    15651790Element.Methods = {
     
    15741799  },
    15751800
     1801
    15761802  hide: function(element) {
    1577     $(element).style.display = 'none';
     1803    element = $(element);
     1804    element.style.display = 'none';
    15781805    return element;
    15791806  },
    15801807
    15811808  show: function(element) {
    1582     $(element).style.display = '';
     1809    element = $(element);
     1810    element.style.display = '';
    15831811    return element;
    15841812  },
     
    15901818  },
    15911819
    1592   update: function(element, content) {
    1593     element = $(element);
    1594     if (content && content.toElement) content = content.toElement();
    1595     if (Object.isElement(content)) return element.update().insert(content);
    1596     content = Object.toHTML(content);
    1597     element.innerHTML = content.stripScripts();
    1598     content.evalScripts.bind(content).defer();
    1599     return element;
    1600   },
     1820  update: (function(){
     1821
     1822    var SELECT_ELEMENT_INNERHTML_BUGGY = (function(){
     1823      var el = document.createElement("select"),
     1824          isBuggy = true;
     1825      el.innerHTML = "<option value=\"test\">test</option>";
     1826      if (el.options && el.options[0]) {
     1827        isBuggy = el.options[0].nodeName.toUpperCase() !== "OPTION";
     1828      }
     1829      el = null;
     1830      return isBuggy;
     1831    })();
     1832
     1833    var TABLE_ELEMENT_INNERHTML_BUGGY = (function(){
     1834      try {
     1835        var el = document.createElement("table");
     1836        if (el && el.tBodies) {
     1837          el.innerHTML = "<tbody><tr><td>test</td></tr></tbody>";
     1838          var isBuggy = typeof el.tBodies[0] == "undefined";
     1839          el = null;
     1840          return isBuggy;
     1841        }
     1842      } catch (e) {
     1843        return true;
     1844      }
     1845    })();
     1846
     1847    var SCRIPT_ELEMENT_REJECTS_TEXTNODE_APPENDING = (function () {
     1848      var s = document.createElement("script"),
     1849          isBuggy = false;
     1850      try {
     1851        s.appendChild(document.createTextNode(""));
     1852        isBuggy = !s.firstChild ||
     1853          s.firstChild && s.firstChild.nodeType !== 3;
     1854      } catch (e) {
     1855        isBuggy = true;
     1856      }
     1857      s = null;
     1858      return isBuggy;
     1859    })();
     1860
     1861    function update(element, content) {
     1862      element = $(element);
     1863
     1864      if (content && content.toElement)
     1865        content = content.toElement();
     1866
     1867      if (Object.isElement(content))
     1868        return element.update().insert(content);
     1869
     1870      content = Object.toHTML(content);
     1871
     1872      var tagName = element.tagName.toUpperCase();
     1873
     1874      if (tagName === 'SCRIPT' && SCRIPT_ELEMENT_REJECTS_TEXTNODE_APPENDING) {
     1875        element.text = content;
     1876        return element;
     1877      }
     1878
     1879      if (SELECT_ELEMENT_INNERHTML_BUGGY || TABLE_ELEMENT_INNERHTML_BUGGY) {
     1880        if (tagName in Element._insertionTranslations.tags) {
     1881          while (element.firstChild) {
     1882            element.removeChild(element.firstChild);
     1883          }
     1884          Element._getContentFromAnonymousElement(tagName, content.stripScripts())
     1885            .each(function(node) {
     1886              element.appendChild(node)
     1887            });
     1888        }
     1889        else {
     1890          element.innerHTML = content.stripScripts();
     1891        }
     1892      }
     1893      else {
     1894        element.innerHTML = content.stripScripts();
     1895      }
     1896
     1897      content.evalScripts.bind(content).defer();
     1898      return element;
     1899    }
     1900
     1901    return update;
     1902  })(),
    16011903
    16021904  replace: function(element, content) {
     
    16831985
    16841986  ancestors: function(element) {
    1685     return $(element).recursivelyCollect('parentNode');
     1987    return Element.recursivelyCollect(element, 'parentNode');
    16861988  },
    16871989
    16881990  descendants: function(element) {
    1689     return $(element).select("*");
     1991    return Element.select(element, "*");
    16901992  },
    16911993
     
    17042006
    17052007  previousSiblings: function(element) {
    1706     return $(element).recursivelyCollect('previousSibling');
     2008    return Element.recursivelyCollect(element, 'previousSibling');
    17072009  },
    17082010
    17092011  nextSiblings: function(element) {
    1710     return $(element).recursivelyCollect('nextSibling');
     2012    return Element.recursivelyCollect(element, 'nextSibling');
    17112013  },
    17122014
    17132015  siblings: function(element) {
    17142016    element = $(element);
    1715     return element.previousSiblings().reverse().concat(element.nextSiblings());
     2017    return Element.previousSiblings(element).reverse()
     2018      .concat(Element.nextSiblings(element));
    17162019  },
    17172020
     
    17252028    element = $(element);
    17262029    if (arguments.length == 1) return $(element.parentNode);
    1727     var ancestors = element.ancestors();
     2030    var ancestors = Element.ancestors(element);
    17282031    return Object.isNumber(expression) ? ancestors[expression] :
    17292032      Selector.findElement(ancestors, expression, index);
     
    17322035  down: function(element, expression, index) {
    17332036    element = $(element);
    1734     if (arguments.length == 1) return element.firstDescendant();
    1735     return Object.isNumber(expression) ? element.descendants()[expression] :
    1736       element.select(expression)[index || 0];
     2037    if (arguments.length == 1) return Element.firstDescendant(element);
     2038    return Object.isNumber(expression) ? Element.descendants(element)[expression] :
     2039      Element.select(element, expression)[index || 0];
    17372040  },
    17382041
     
    17402043    element = $(element);
    17412044    if (arguments.length == 1) return $(Selector.handlers.previousElementSibling(element));
    1742     var previousSiblings = element.previousSiblings();
     2045    var previousSiblings = Element.previousSiblings(element);
    17432046    return Object.isNumber(expression) ? previousSiblings[expression] :
    17442047      Selector.findElement(previousSiblings, expression, index);
     
    17482051    element = $(element);
    17492052    if (arguments.length == 1) return $(Selector.handlers.nextElementSibling(element));
    1750     var nextSiblings = element.nextSiblings();
     2053    var nextSiblings = Element.nextSiblings(element);
    17512054    return Object.isNumber(expression) ? nextSiblings[expression] :
    17522055      Selector.findElement(nextSiblings, expression, index);
    17532056  },
    17542057
    1755   select: function() {
    1756     var args = $A(arguments), element = $(args.shift());
     2058
     2059  select: function(element) {
     2060    var args = Array.prototype.slice.call(arguments, 1);
    17572061    return Selector.findChildElements(element, args);
    17582062  },
    17592063
    1760   adjacent: function() {
    1761     var args = $A(arguments), element = $(args.shift());
     2064  adjacent: function(element) {
     2065    var args = Array.prototype.slice.call(arguments, 1);
    17622066    return Selector.findChildElements(element.parentNode, args).without(element);
    17632067  },
     
    17652069  identify: function(element) {
    17662070    element = $(element);
    1767     var id = element.readAttribute('id'), self = arguments.callee;
     2071    var id = Element.readAttribute(element, 'id');
    17682072    if (id) return id;
    1769     do { id = 'anonymous_element_' + self.counter++ } while ($(id));
    1770     element.writeAttribute('id', id);
     2073    do { id = 'anonymous_element_' + Element.idCounter++ } while ($(id));
     2074    Element.writeAttribute(element, 'id', id);
    17712075    return id;
    17722076  },
     
    18072111
    18082112  getHeight: function(element) {
    1809     return $(element).getDimensions().height;
     2113    return Element.getDimensions(element).height;
    18102114  },
    18112115
    18122116  getWidth: function(element) {
    1813     return $(element).getDimensions().width;
     2117    return Element.getDimensions(element).width;
    18142118  },
    18152119
     
    18272131  addClassName: function(element, className) {
    18282132    if (!(element = $(element))) return;
    1829     if (!element.hasClassName(className))
     2133    if (!Element.hasClassName(element, className))
    18302134      element.className += (element.className ? ' ' : '') + className;
    18312135    return element;
     
    18412145  toggleClassName: function(element, className) {
    18422146    if (!(element = $(element))) return;
    1843     return element[element.hasClassName(className) ?
    1844       'removeClassName' : 'addClassName'](className);
    1845   },
    1846 
    1847   // removes whitespace-only text node children
     2147    return Element[Element.hasClassName(element, className) ?
     2148      'removeClassName' : 'addClassName'](element, className);
     2149  },
     2150
    18482151  cleanWhitespace: function(element) {
    18492152    element = $(element);
     
    18642167  descendantOf: function(element, ancestor) {
    18652168    element = $(element), ancestor = $(ancestor);
    1866     var originalAncestor = ancestor;
    18672169
    18682170    if (element.compareDocumentPosition)
    18692171      return (element.compareDocumentPosition(ancestor) & 8) === 8;
    18702172
    1871     if (element.sourceIndex && !Prototype.Browser.Opera) {
    1872       var e = element.sourceIndex, a = ancestor.sourceIndex,
    1873        nextAncestor = ancestor.nextSibling;
    1874       if (!nextAncestor) {
    1875         do { ancestor = ancestor.parentNode; }
    1876         while (!(nextAncestor = ancestor.nextSibling) && ancestor.parentNode);
    1877       }
    1878       if (nextAncestor && nextAncestor.sourceIndex)
    1879        return (e > a && e < nextAncestor.sourceIndex);
    1880     }
     2173    if (ancestor.contains)
     2174      return ancestor.contains(element) && ancestor !== element;
    18812175
    18822176    while (element = element.parentNode)
    1883       if (element == originalAncestor) return true;
     2177      if (element == ancestor) return true;
     2178
    18842179    return false;
    18852180  },
     
    18872182  scrollTo: function(element) {
    18882183    element = $(element);
    1889     var pos = element.cumulativeOffset();
     2184    var pos = Element.cumulativeOffset(element);
    18902185    window.scrollTo(pos[0], pos[1]);
    18912186    return element;
     
    18962191    style = style == 'float' ? 'cssFloat' : style.camelize();
    18972192    var value = element.style[style];
    1898     if (!value) {
     2193    if (!value || value == 'auto') {
    18992194      var css = document.defaultView.getComputedStyle(element, null);
    19002195      value = css ? css[style] : null;
     
    19352230  getDimensions: function(element) {
    19362231    element = $(element);
    1937     var display = $(element).getStyle('display');
     2232    var display = Element.getStyle(element, 'display');
    19382233    if (display != 'none' && display != null) // Safari bug
    19392234      return {width: element.offsetWidth, height: element.offsetHeight};
    19402235
    1941     // All *Width and *Height properties give 0 on elements with display none,
    1942     // so enable the element temporarily
    19432236    var els = element.style;
    19442237    var originalVisibility = els.visibility;
     
    19462239    var originalDisplay = els.display;
    19472240    els.visibility = 'hidden';
    1948     els.position = 'absolute';
     2241    if (originalPosition != 'fixed') // Switching fixed to absolute causes issues in Safari
     2242      els.position = 'absolute';
    19492243    els.display = 'block';
    19502244    var originalWidth = element.clientWidth;
     
    19622256      element._madePositioned = true;
    19632257      element.style.position = 'relative';
    1964       // Opera returns the offset relative to the positioning context, when an
    1965       // element is position relative but top and left have not been defined
    1966       if (window.opera) {
     2258      if (Prototype.Browser.Opera) {
    19672259        element.style.top = 0;
    19682260        element.style.left = 0;
     
    20192311      element = element.offsetParent;
    20202312      if (element) {
    2021         if (element.tagName == 'BODY') break;
     2313        if (element.tagName.toUpperCase() == 'BODY') break;
    20222314        var p = Element.getStyle(element, 'position');
    20232315        if (p !== 'static') break;
     
    20292321  absolutize: function(element) {
    20302322    element = $(element);
    2031     if (element.getStyle('position') == 'absolute') return;
    2032     // Position.prepare(); // To be done manually by Scripty when it needs it.
    2033 
    2034     var offsets = element.positionedOffset();
     2323    if (Element.getStyle(element, 'position') == 'absolute') return element;
     2324
     2325    var offsets = Element.positionedOffset(element);
    20352326    var top     = offsets[1];
    20362327    var left    = offsets[0];
     
    20532344  relativize: function(element) {
    20542345    element = $(element);
    2055     if (element.getStyle('position') == 'relative') return;
    2056     // Position.prepare(); // To be done manually by Scripty when it needs it.
     2346    if (Element.getStyle(element, 'position') == 'relative') return element;
    20572347
    20582348    element.style.position = 'relative';
     
    20962386      valueL += element.offsetLeft || 0;
    20972387
    2098       // Safari fix
    20992388      if (element.offsetParent == document.body &&
    21002389        Element.getStyle(element, 'position') == 'absolute') break;
     
    21042393    element = forElement;
    21052394    do {
    2106       if (!Prototype.Browser.Opera || element.tagName == 'BODY') {
     2395      if (!Prototype.Browser.Opera || (element.tagName && (element.tagName.toUpperCase() == 'BODY'))) {
    21072396        valueT -= element.scrollTop  || 0;
    21082397        valueL -= element.scrollLeft || 0;
     
    21232412    }, arguments[2] || { });
    21242413
    2125     // find page position of source
    21262414    source = $(source);
    2127     var p = source.viewportOffset();
    2128 
    2129     // find coordinate system to use
     2415    var p = Element.viewportOffset(source);
     2416
    21302417    element = $(element);
    21312418    var delta = [0, 0];
    21322419    var parent = null;
    2133     // delta [0,0] will do fine with position: fixed elements,
    2134     // position:absolute needs offsetParent deltas
    21352420    if (Element.getStyle(element, 'position') == 'absolute') {
    2136       parent = element.getOffsetParent();
    2137       delta = parent.viewportOffset();
    2138     }
    2139 
    2140     // correct by body offsets (fixes Safari)
     2421      parent = Element.getOffsetParent(element);
     2422      delta = Element.viewportOffset(parent);
     2423    }
     2424
    21412425    if (parent == document.body) {
    21422426      delta[0] -= document.body.offsetLeft;
     
    21442428    }
    21452429
    2146     // set position
    21472430    if (options.setLeft)   element.style.left  = (p[0] - delta[0] + options.offsetLeft) + 'px';
    21482431    if (options.setTop)    element.style.top   = (p[1] - delta[1] + options.offsetTop) + 'px';
     
    21532436};
    21542437
    2155 Element.Methods.identify.counter = 1;
    2156 
    21572438Object.extend(Element.Methods, {
    21582439  getElementsBySelector: Element.Methods.select,
     2440
    21592441  childElements: Element.Methods.immediateDescendants
    21602442});
     
    21772459          if (proceed(element, 'position') === 'static') return null;
    21782460        case 'height': case 'width':
    2179           // returns '0px' for hidden elements; we want it to return null
    21802461          if (!Element.visible(element)) return null;
    21812462
    2182           // returns the border-box dimensions rather than the content-box
    2183           // dimensions, so we subtract padding and borders from the value
    21842463          var dim = parseInt(proceed(element, style), 10);
    21852464
     
    22142493
    22152494else if (Prototype.Browser.IE) {
    2216   // IE doesn't report offsets correctly for static elements, so we change them
    2217   // to "relative" to get the values, then change them back.
    22182495  Element.Methods.getOffsetParent = Element.Methods.getOffsetParent.wrap(
    22192496    function(proceed, element) {
    22202497      element = $(element);
     2498      try { element.offsetParent }
     2499      catch(e) { return $(document.body) }
    22212500      var position = element.getStyle('position');
    22222501      if (position !== 'static') return proceed(element);
     
    22322511      function(proceed, element) {
    22332512        element = $(element);
     2513        try { element.offsetParent }
     2514        catch(e) { return Element._returnOffset(0,0) }
    22342515        var position = element.getStyle('position');
    22352516        if (position !== 'static') return proceed(element);
    2236         // Trigger hasLayout on the offset parent so that IE6 reports
    2237         // accurate offsetTop and offsetLeft values for position: fixed.
    22382517        var offsetParent = element.getOffsetParent();
    22392518        if (offsetParent && offsetParent.getStyle('position') === 'fixed')
     
    22462525    );
    22472526  });
     2527
     2528  Element.Methods.cumulativeOffset = Element.Methods.cumulativeOffset.wrap(
     2529    function(proceed, element) {
     2530      try { element.offsetParent }
     2531      catch(e) { return Element._returnOffset(0,0) }
     2532      return proceed(element);
     2533    }
     2534  );
    22482535
    22492536  Element.Methods.getStyle = function(element, style) {
     
    22882575  };
    22892576
    2290   Element._attributeTranslations = {
    2291     read: {
    2292       names: {
    2293         'class': 'className',
    2294         'for':   'htmlFor'
    2295       },
    2296       values: {
    2297         _getAttr: function(element, attribute) {
    2298           return element.getAttribute(attribute, 2);
     2577  Element._attributeTranslations = (function(){
     2578
     2579    var classProp = 'className';
     2580    var forProp = 'for';
     2581
     2582    var el = document.createElement('div');
     2583
     2584    el.setAttribute(classProp, 'x');
     2585
     2586    if (el.className !== 'x') {
     2587      el.setAttribute('class', 'x');
     2588      if (el.className === 'x') {
     2589        classProp = 'class';
     2590      }
     2591    }
     2592    el = null;
     2593
     2594    el = document.createElement('label');
     2595    el.setAttribute(forProp, 'x');
     2596    if (el.htmlFor !== 'x') {
     2597      el.setAttribute('htmlFor', 'x');
     2598      if (el.htmlFor === 'x') {
     2599        forProp = 'htmlFor';
     2600      }
     2601    }
     2602    el = null;
     2603
     2604    return {
     2605      read: {
     2606        names: {
     2607          'class':      classProp,
     2608          'className':  classProp,
     2609          'for':        forProp,
     2610          'htmlFor':    forProp
    22992611        },
    2300         _getAttrNode: function(element, attribute) {
    2301           var node = element.getAttributeNode(attribute);
    2302           return node ? node.value : "";
    2303         },
    2304         _getEv: function(element, attribute) {
    2305           attribute = element.getAttribute(attribute);
    2306           return attribute ? attribute.toString().slice(23, -2) : null;
    2307         },
    2308         _flag: function(element, attribute) {
    2309           return $(element).hasAttribute(attribute) ? attribute : null;
    2310         },
    2311         style: function(element) {
    2312           return element.style.cssText.toLowerCase();
    2313         },
    2314         title: function(element) {
    2315           return element.title;
     2612        values: {
     2613          _getAttr: function(element, attribute) {
     2614            return element.getAttribute(attribute);
     2615          },
     2616          _getAttr2: function(element, attribute) {
     2617            return element.getAttribute(attribute, 2);
     2618          },
     2619          _getAttrNode: function(element, attribute) {
     2620            var node = element.getAttributeNode(attribute);
     2621            return node ? node.value : "";
     2622          },
     2623          _getEv: (function(){
     2624
     2625            var el = document.createElement('div');
     2626            el.onclick = Prototype.emptyFunction;
     2627            var value = el.getAttribute('onclick');
     2628            var f;
     2629
     2630            if (String(value).indexOf('{') > -1) {
     2631              f = function(element, attribute) {
     2632                attribute = element.getAttribute(attribute);
     2633                if (!attribute) return null;
     2634                attribute = attribute.toString();
     2635                attribute = attribute.split('{')[1];
     2636                attribute = attribute.split('}')[0];
     2637                return attribute.strip();
     2638              };
     2639            }
     2640            else if (value === '') {
     2641              f = function(element, attribute) {
     2642                attribute = element.getAttribute(attribute);
     2643                if (!attribute) return null;
     2644                return attribute.strip();
     2645              };
     2646            }
     2647            el = null;
     2648            return f;
     2649          })(),
     2650          _flag: function(element, attribute) {
     2651            return $(element).hasAttribute(attribute) ? attribute : null;
     2652          },
     2653          style: function(element) {
     2654            return element.style.cssText.toLowerCase();
     2655          },
     2656          title: function(element) {
     2657            return element.title;
     2658          }
    23162659        }
    23172660      }
    23182661    }
    2319   };
     2662  })();
    23202663
    23212664  Element._attributeTranslations.write = {
     
    23382681
    23392682  $w('colSpan rowSpan vAlign dateTime accessKey tabIndex ' +
    2340       'encType maxLength readOnly longDesc').each(function(attr) {
     2683      'encType maxLength readOnly longDesc frameBorder').each(function(attr) {
    23412684    Element._attributeTranslations.write.names[attr.toLowerCase()] = attr;
    23422685    Element._attributeTranslations.has[attr.toLowerCase()] = attr;
     
    23452688  (function(v) {
    23462689    Object.extend(v, {
    2347       href:        v._getAttr,
    2348       src:         v._getAttr,
     2690      href:        v._getAttr2,
     2691      src:         v._getAttr2,
    23492692      type:        v._getAttr,
    23502693      action:      v._getAttrNode,
     
    23732716    });
    23742717  })(Element._attributeTranslations.read.values);
     2718
     2719  if (Prototype.BrowserFeatures.ElementExtensions) {
     2720    (function() {
     2721      function _descendants(element) {
     2722        var nodes = element.getElementsByTagName('*'), results = [];
     2723        for (var i = 0, node; node = nodes[i]; i++)
     2724          if (node.tagName !== "!") // Filter out comment nodes.
     2725            results.push(node);
     2726        return results;
     2727      }
     2728
     2729      Element.Methods.down = function(element, expression, index) {
     2730        element = $(element);
     2731        if (arguments.length == 1) return element.firstDescendant();
     2732        return Object.isNumber(expression) ? _descendants(element)[expression] :
     2733          Element.select(element, expression)[index || 0];
     2734      }
     2735    })();
     2736  }
     2737
    23752738}
    23762739
     
    23912754
    23922755    if (value == 1)
    2393       if(element.tagName == 'IMG' && element.width) {
     2756      if(element.tagName.toUpperCase() == 'IMG' && element.width) {
    23942757        element.width++; element.width--;
    23952758      } else try {
     
    24022765  };
    24032766
    2404   // Safari returns margins on body which is incorrect if the child is absolutely
    2405   // positioned.  For performance reasons, redefine Element#cumulativeOffset for
    2406   // KHTML/WebKit only.
    24072767  Element.Methods.cumulativeOffset = function(element) {
    24082768    var valueT = 0, valueL = 0;
     
    24202780}
    24212781
    2422 if (Prototype.Browser.IE || Prototype.Browser.Opera) {
    2423   // IE and Opera are missing .innerHTML support for TABLE-related and SELECT elements
    2424   Element.Methods.update = function(element, content) {
    2425     element = $(element);
    2426 
    2427     if (content && content.toElement) content = content.toElement();
    2428     if (Object.isElement(content)) return element.update().insert(content);
    2429 
    2430     content = Object.toHTML(content);
    2431     var tagName = element.tagName.toUpperCase();
    2432 
    2433     if (tagName in Element._insertionTranslations.tags) {
    2434       $A(element.childNodes).each(function(node) { element.removeChild(node) });
    2435       Element._getContentFromAnonymousElement(tagName, content.stripScripts())
    2436         .each(function(node) { element.appendChild(node) });
    2437     }
    2438     else element.innerHTML = content.stripScripts();
    2439 
    2440     content.evalScripts.bind(content).defer();
    2441     return element;
    2442   };
    2443 }
    2444 
    2445 if ('outerHTML' in document.createElement('div')) {
     2782if ('outerHTML' in document.documentElement) {
    24462783  Element.Methods.replace = function(element, content) {
    24472784    element = $(element);
     
    25112848
    25122849(function() {
    2513   Object.extend(this.tags, {
    2514     THEAD: this.tags.TBODY,
    2515     TFOOT: this.tags.TBODY,
    2516     TH:    this.tags.TD
     2850  var tags = Element._insertionTranslations.tags;
     2851  Object.extend(tags, {
     2852    THEAD: tags.TBODY,
     2853    TFOOT: tags.TBODY,
     2854    TH:    tags.TD
    25172855  });
    2518 }).call(Element._insertionTranslations);
     2856})();
    25192857
    25202858Element.Methods.Simulated = {
     
    25222860    attribute = Element._attributeTranslations.has[attribute] || attribute;
    25232861    var node = $(element).getAttributeNode(attribute);
    2524     return node && node.specified;
     2862    return !!(node && node.specified);
    25252863  }
    25262864};
     
    25302868Object.extend(Element, Element.Methods);
    25312869
    2532 if (!Prototype.BrowserFeatures.ElementExtensions &&
    2533     document.createElement('div').__proto__) {
    2534   window.HTMLElement = { };
    2535   window.HTMLElement.prototype = document.createElement('div').__proto__;
    2536   Prototype.BrowserFeatures.ElementExtensions = true;
    2537 }
     2870(function(div) {
     2871
     2872  if (!Prototype.BrowserFeatures.ElementExtensions && div['__proto__']) {
     2873    window.HTMLElement = { };
     2874    window.HTMLElement.prototype = div['__proto__'];
     2875    Prototype.BrowserFeatures.ElementExtensions = true;
     2876  }
     2877
     2878  div = null;
     2879
     2880})(document.createElement('div'))
    25382881
    25392882Element.extend = (function() {
    2540   if (Prototype.BrowserFeatures.SpecificElementExtensions)
    2541     return Prototype.K;
    2542 
    2543   var Methods = { }, ByTag = Element.Methods.ByTag;
    2544 
    2545   var extend = Object.extend(function(element) {
    2546     if (!element || element._extendedByPrototype ||
    2547         element.nodeType != 1 || element == window) return element;
    2548 
    2549     var methods = Object.clone(Methods),
    2550       tagName = element.tagName, property, value;
    2551 
    2552     // extend methods for specific tags
    2553     if (ByTag[tagName]) Object.extend(methods, ByTag[tagName]);
    2554 
    2555     for (property in methods) {
    2556       value = methods[property];
     2883
     2884  function checkDeficiency(tagName) {
     2885    if (typeof window.Element != 'undefined') {
     2886      var proto = window.Element.prototype;
     2887      if (proto) {
     2888        var id = '_' + (Math.random()+'').slice(2);
     2889        var el = document.createElement(tagName);
     2890        proto[id] = 'x';
     2891        var isBuggy = (el[id] !== 'x');
     2892        delete proto[id];
     2893        el = null;
     2894        return isBuggy;
     2895      }
     2896    }
     2897    return false;
     2898  }
     2899
     2900  function extendElementWith(element, methods) {
     2901    for (var property in methods) {
     2902      var value = methods[property];
    25572903      if (Object.isFunction(value) && !(property in element))
    25582904        element[property] = value.methodize();
    25592905    }
     2906  }
     2907
     2908  var HTMLOBJECTELEMENT_PROTOTYPE_BUGGY = checkDeficiency('object');
     2909
     2910  if (Prototype.BrowserFeatures.SpecificElementExtensions) {
     2911    if (HTMLOBJECTELEMENT_PROTOTYPE_BUGGY) {
     2912      return function(element) {
     2913        if (element && typeof element._extendedByPrototype == 'undefined') {
     2914          var t = element.tagName;
     2915          if (t && (/^(?:object|applet|embed)$/i.test(t))) {
     2916            extendElementWith(element, Element.Methods);
     2917            extendElementWith(element, Element.Methods.Simulated);
     2918            extendElementWith(element, Element.Methods.ByTag[t.toUpperCase()]);
     2919          }
     2920        }
     2921        return element;
     2922      }
     2923    }
     2924    return Prototype.K;
     2925  }
     2926
     2927  var Methods = { }, ByTag = Element.Methods.ByTag;
     2928
     2929  var extend = Object.extend(function(element) {
     2930    if (!element || typeof element._extendedByPrototype != 'undefined' ||
     2931        element.nodeType != 1 || element == window) return element;
     2932
     2933    var methods = Object.clone(Methods),
     2934        tagName = element.tagName.toUpperCase();
     2935
     2936    if (ByTag[tagName]) Object.extend(methods, ByTag[tagName]);
     2937
     2938    extendElementWith(element, methods);
    25602939
    25612940    element._extendedByPrototype = Prototype.emptyFunction;
     
    25642943  }, {
    25652944    refresh: function() {
    2566       // extend methods for all tags (Safari doesn't need this)
    25672945      if (!Prototype.BrowserFeatures.ElementExtensions) {
    25682946        Object.extend(Methods, Element.Methods);
     
    26433021    if (window[klass]) return window[klass];
    26443022
    2645     window[klass] = { };
    2646     window[klass].prototype = document.createElement(tagName).__proto__;
    2647     return window[klass];
    2648   }
     3023    var element = document.createElement(tagName);
     3024    var proto = element['__proto__'] || element.constructor.prototype;
     3025    element = null;
     3026    return proto;
     3027  }
     3028
     3029  var elementPrototype = window.HTMLElement ? HTMLElement.prototype :
     3030   Element.prototype;
    26493031
    26503032  if (F.ElementExtensions) {
    2651     copy(Element.Methods, HTMLElement.prototype);
    2652     copy(Element.Methods.Simulated, HTMLElement.prototype, true);
     3033    copy(Element.Methods, elementPrototype);
     3034    copy(Element.Methods.Simulated, elementPrototype, true);
    26533035  }
    26543036
     
    26683050};
    26693051
     3052
    26703053document.viewport = {
     3054
    26713055  getDimensions: function() {
    2672     var dimensions = { };
    2673     var B = Prototype.Browser;
    2674     $w('width height').each(function(d) {
    2675       var D = d.capitalize();
    2676       dimensions[d] = (B.WebKit && !document.evaluate) ? self['inner' + D] :
    2677         (B.Opera) ? document.body['client' + D] : document.documentElement['client' + D];
    2678     });
    2679     return dimensions;
    2680   },
    2681 
    2682   getWidth: function() {
    2683     return this.getDimensions().width;
    2684   },
    2685 
    2686   getHeight: function() {
    2687     return this.getDimensions().height;
     3056    return { width: this.getWidth(), height: this.getHeight() };
    26883057  },
    26893058
     
    26913060    return Element._returnOffset(
    26923061      window.pageXOffset || document.documentElement.scrollLeft || document.body.scrollLeft,
    2693       window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop);
     3062      window.pageYOffset || document.documentElement.scrollTop  || document.body.scrollTop);
    26943063  }
    26953064};
    2696 /* Portions of the Selector class are derived from Jack Slocum’s DomQuery,
     3065
     3066(function(viewport) {
     3067  var B = Prototype.Browser, doc = document, element, property = {};
     3068
     3069  function getRootElement() {
     3070    if (B.WebKit && !doc.evaluate)
     3071      return document;
     3072
     3073    if (B.Opera && window.parseFloat(window.opera.version()) < 9.5)
     3074      return document.body;
     3075
     3076    return document.documentElement;
     3077  }
     3078
     3079  function define(D) {
     3080    if (!element) element = getRootElement();
     3081
     3082    property[D] = 'client' + D;
     3083
     3084    viewport['get' + D] = function() { return element[property[D]] };
     3085    return viewport['get' + D]();
     3086  }
     3087
     3088  viewport.getWidth  = define.curry('Width');
     3089
     3090  viewport.getHeight = define.curry('Height');
     3091})(document.viewport);
     3092
     3093
     3094Element.Storage = {
     3095  UID: 1
     3096};
     3097
     3098Element.addMethods({
     3099  getStorage: function(element) {
     3100    if (!(element = $(element))) return;
     3101
     3102    var uid;
     3103    if (element === window) {
     3104      uid = 0;
     3105    } else {
     3106      if (typeof element._prototypeUID === "undefined")
     3107        element._prototypeUID = [Element.Storage.UID++];
     3108      uid = element._prototypeUID[0];
     3109    }
     3110
     3111    if (!Element.Storage[uid])
     3112      Element.Storage[uid] = $H();
     3113
     3114    return Element.Storage[uid];
     3115  },
     3116
     3117  store: function(element, key, value) {
     3118    if (!(element = $(element))) return;
     3119
     3120    if (arguments.length === 2) {
     3121      Element.getStorage(element).update(key);
     3122    } else {
     3123      Element.getStorage(element).set(key, value);
     3124    }
     3125
     3126    return element;
     3127  },
     3128
     3129  retrieve: function(element, key, defaultValue) {
     3130    if (!(element = $(element))) return;
     3131    var hash = Element.getStorage(element), value = hash.get(key);
     3132
     3133    if (Object.isUndefined(value)) {
     3134      hash.set(key, defaultValue);
     3135      value = defaultValue;
     3136    }
     3137
     3138    return value;
     3139  },
     3140
     3141  clone: function(element, deep) {
     3142    if (!(element = $(element))) return;
     3143    var clone = element.cloneNode(deep);
     3144    clone._prototypeUID = void 0;
     3145    if (deep) {
     3146      var descendants = Element.select(clone, '*'),
     3147          i = descendants.length;
     3148      while (i--) {
     3149        descendants[i]._prototypeUID = void 0;
     3150      }
     3151    }
     3152    return Element.extend(clone);
     3153  }
     3154});
     3155/* Portions of the Selector class are derived from Jack Slocum's DomQuery,
    26973156 * part of YUI-Ext version 0.40, distributed under the terms of an MIT-style
    26983157 * license.  Please see http://www.yui-ext.com/ for more information. */
     
    27013160  initialize: function(expression) {
    27023161    this.expression = expression.strip();
    2703     this.compileMatcher();
    2704   },
    2705 
    2706   shouldUseXPath: function() {
    2707     if (!Prototype.BrowserFeatures.XPath) return false;
    2708 
    2709     var e = this.expression;
    2710 
    2711     // Safari 3 chokes on :*-of-type and :empty
    2712     if (Prototype.Browser.WebKit &&
    2713      (e.include("-of-type") || e.include(":empty")))
     3162
     3163    if (this.shouldUseSelectorsAPI()) {
     3164      this.mode = 'selectorsAPI';
     3165    } else if (this.shouldUseXPath()) {
     3166      this.mode = 'xpath';
     3167      this.compileXPathMatcher();
     3168    } else {
     3169      this.mode = "normal";
     3170      this.compileMatcher();
     3171    }
     3172
     3173  },
     3174
     3175  shouldUseXPath: (function() {
     3176
     3177    var IS_DESCENDANT_SELECTOR_BUGGY = (function(){
     3178      var isBuggy = false;
     3179      if (document.evaluate && window.XPathResult) {
     3180        var el = document.createElement('div');
     3181        el.innerHTML = '<ul><li></li></ul><div><ul><li></li></ul></div>';
     3182
     3183        var xpath = ".//*[local-name()='ul' or local-name()='UL']" +
     3184          "//*[local-name()='li' or local-name()='LI']";
     3185
     3186        var result = document.evaluate(xpath, el, null,
     3187          XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);
     3188
     3189        isBuggy = (result.snapshotLength !== 2);
     3190        el = null;
     3191      }
     3192      return isBuggy;
     3193    })();
     3194
     3195    return function() {
     3196      if (!Prototype.BrowserFeatures.XPath) return false;
     3197
     3198      var e = this.expression;
     3199
     3200      if (Prototype.Browser.WebKit &&
     3201       (e.include("-of-type") || e.include(":empty")))
     3202        return false;
     3203
     3204      if ((/(\[[\w-]*?:|:checked)/).test(e))
     3205        return false;
     3206
     3207      if (IS_DESCENDANT_SELECTOR_BUGGY) return false;
     3208
     3209      return true;
     3210    }
     3211
     3212  })(),
     3213
     3214  shouldUseSelectorsAPI: function() {
     3215    if (!Prototype.BrowserFeatures.SelectorsAPI) return false;
     3216
     3217    if (Selector.CASE_INSENSITIVE_CLASS_NAMES) return false;
     3218
     3219    if (!Selector._div) Selector._div = new Element('div');
     3220
     3221    try {
     3222      Selector._div.querySelector(this.expression);
     3223    } catch(e) {
    27143224      return false;
    2715 
    2716     // XPath can't do namespaced attributes, nor can it read
    2717     // the "checked" property from DOM nodes
    2718     if ((/(\[[\w-]*?:|:checked)/).test(this.expression))
    2719       return false;
     3225    }
    27203226
    27213227    return true;
     
    27233229
    27243230  compileMatcher: function() {
    2725     if (this.shouldUseXPath())
    2726       return this.compileXPathMatcher();
    2727 
    27283231    var e = this.expression, ps = Selector.patterns, h = Selector.handlers,
    2729         c = Selector.criteria, le, p, m;
     3232        c = Selector.criteria, le, p, m, len = ps.length, name;
    27303233
    27313234    if (Selector._cache[e]) {
     
    27393242    while (e && le != e && (/\S/).test(e)) {
    27403243      le = e;
    2741       for (var i in ps) {
    2742         p = ps[i];
     3244      for (var i = 0; i<len; i++) {
     3245        p = ps[i].re;
     3246        name = ps[i].name;
    27433247        if (m = e.match(p)) {
    2744           this.matcher.push(Object.isFunction(c[i]) ? c[i](m) :
    2745               new Template(c[i]).evaluate(m));
     3248          this.matcher.push(Object.isFunction(c[name]) ? c[name](m) :
     3249            new Template(c[name]).evaluate(m));
    27463250          e = e.replace(m[0], '');
    27473251          break;
     
    27573261  compileXPathMatcher: function() {
    27583262    var e = this.expression, ps = Selector.patterns,
    2759         x = Selector.xpath, le, m;
     3263        x = Selector.xpath, le, m, len = ps.length, name;
    27603264
    27613265    if (Selector._cache[e]) {
     
    27663270    while (e && le != e && (/\S/).test(e)) {
    27673271      le = e;
    2768       for (var i in ps) {
    2769         if (m = e.match(ps[i])) {
    2770           this.matcher.push(Object.isFunction(x[i]) ? x[i](m) :
    2771             new Template(x[i]).evaluate(m));
     3272      for (var i = 0; i<len; i++) {
     3273        name = ps[i].name;
     3274        if (m = e.match(ps[i].re)) {
     3275          this.matcher.push(Object.isFunction(x[name]) ? x[name](m) :
     3276            new Template(x[name]).evaluate(m));
    27723277          e = e.replace(m[0], '');
    27733278          break;
     
    27823287  findElements: function(root) {
    27833288    root = root || document;
    2784     if (this.xpath) return document._getElementsByXPath(this.xpath, root);
    2785     return this.matcher(root);
     3289    var e = this.expression, results;
     3290
     3291    switch (this.mode) {
     3292      case 'selectorsAPI':
     3293        if (root !== document) {
     3294          var oldId = root.id, id = $(root).identify();
     3295          id = id.replace(/([\.:])/g, "\\$1");
     3296          e = "#" + id + " " + e;
     3297        }
     3298
     3299        results = $A(root.querySelectorAll(e)).map(Element.extend);
     3300        root.id = oldId;
     3301
     3302        return results;
     3303      case 'xpath':
     3304        return document._getElementsByXPath(this.xpath, root);
     3305      default:
     3306       return this.matcher(root);
     3307    }
    27863308  },
    27873309
     
    27903312
    27913313    var e = this.expression, ps = Selector.patterns, as = Selector.assertions;
    2792     var le, p, m;
     3314    var le, p, m, len = ps.length, name;
    27933315
    27943316    while (e && le !== e && (/\S/).test(e)) {
    27953317      le = e;
    2796       for (var i in ps) {
    2797         p = ps[i];
     3318      for (var i = 0; i<len; i++) {
     3319        p = ps[i].re;
     3320        name = ps[i].name;
    27983321        if (m = e.match(p)) {
    2799           // use the Selector.assertions methods unless the selector
    2800           // is too complex.
    2801           if (as[i]) {
    2802             this.tokens.push([i, Object.clone(m)]);
     3322          if (as[name]) {
     3323            this.tokens.push([name, Object.clone(m)]);
    28033324            e = e.replace(m[0], '');
    28043325          } else {
    2805             // reluctantly do a document-wide search
    2806             // and look for a match in the array
    28073326            return this.findElements(document).include(element);
    28083327          }
     
    28303349  }
    28313350});
     3351
     3352if (Prototype.BrowserFeatures.SelectorsAPI &&
     3353 document.compatMode === 'BackCompat') {
     3354  Selector.CASE_INSENSITIVE_CLASS_NAMES = (function(){
     3355    var div = document.createElement('div'),
     3356     span = document.createElement('span');
     3357
     3358    div.id = "prototype_test_id";
     3359    span.className = 'Test';
     3360    div.appendChild(span);
     3361    var isIgnored = (div.querySelector('#prototype_test_id .test') !== null);
     3362    div = span = null;
     3363    return isIgnored;
     3364  })();
     3365}
    28323366
    28333367Object.extend(Selector, {
     
    28743408      'last-child':  '[not(following-sibling::*)]',
    28753409      'only-child':  '[not(preceding-sibling::* or following-sibling::*)]',
    2876       'empty':       "[count(*) = 0 and (count(text()) = 0 or translate(text(), ' \t\r\n', '') = '')]",
     3410      'empty':       "[count(*) = 0 and (count(text()) = 0)]",
    28773411      'checked':     "[@checked]",
    2878       'disabled':    "[@disabled]",
    2879       'enabled':     "[not(@disabled)]",
     3412      'disabled':    "[(@disabled) and (@type!='hidden')]",
     3413      'enabled':     "[not(@disabled) and (@type!='hidden')]",
    28803414      'not': function(m) {
    28813415        var e = m[6], p = Selector.patterns,
    2882             x = Selector.xpath, le, v;
     3416            x = Selector.xpath, le, v, len = p.length, name;
    28833417
    28843418        var exclusion = [];
    28853419        while (e && le != e && (/\S/).test(e)) {
    28863420          le = e;
    2887           for (var i in p) {
    2888             if (m = e.match(p[i])) {
    2889               v = Object.isFunction(x[i]) ? x[i](m) : new Template(x[i]).evaluate(m);
     3421          for (var i = 0; i<len; i++) {
     3422            name = p[i].name
     3423            if (m = e.match(p[i].re)) {
     3424              v = Object.isFunction(x[name]) ? x[name](m) : new Template(x[name]).evaluate(m);
    28903425              exclusion.push("(" + v.substring(1, v.length - 1) + ")");
    28913426              e = e.replace(m[0], '');
     
    29553490  },
    29563491
    2957   patterns: {
    2958     // combinators must be listed first
    2959     // (and descendant needs to be last combinator)
    2960     laterSibling: /^\s*~\s*/,
    2961     child:        /^\s*>\s*/,
    2962     adjacent:     /^\s*\+\s*/,
    2963     descendant:   /^\s/,
    2964 
    2965     // selectors follow
    2966     tagName:      /^\s*(\*|[\w\-]+)(\b|$)?/,
    2967     id:           /^#([\w\-\*]+)(\b|$)/,
    2968     className:    /^\.([\w\-\*]+)(\b|$)/,
    2969     pseudo:
    2970 /^:((first|last|nth|nth-last|only)(-child|-of-type)|empty|checked|(en|dis)abled|not)(\((.*?)\))?(\b|$|(?=\s|[:+~>]))/,
    2971     attrPresence: /^\[([\w]+)\]/,
    2972     attr:         /\[((?:[\w-]*:)?[\w-]+)\s*(?:([!^$*~|]?=)\s*((['"])([^\4]*?)\4|([^'"][^\]]*?)))?\]/
    2973   },
    2974 
    2975   // for Selector.match and Element#match
     3492  patterns: [
     3493    { name: 'laterSibling', re: /^\s*~\s*/ },
     3494    { name: 'child',        re: /^\s*>\s*/ },
     3495    { name: 'adjacent',     re: /^\s*\+\s*/ },
     3496    { name: 'descendant',   re: /^\s/ },
     3497
     3498    { name: 'tagName',      re: /^\s*(\*|[\w\-]+)(\b|$)?/ },
     3499    { name: 'id',           re: /^#([\w\-\*]+)(\b|$)/ },
     3500    { name: 'className',    re: /^\.([\w\-\*]+)(\b|$)/ },
     3501    { name: 'pseudo',       re: /^:((first|last|nth|nth-last|only)(-child|-of-type)|empty|checked|(en|dis)abled|not)(\((.*?)\))?(\b|$|(?=\s|[:+~>]))/ },
     3502    { name: 'attrPresence', re: /^\[((?:[\w-]+:)?[\w-]+)\]/ },
     3503    { name: 'attr',         re: /\[((?:[\w-]*:)?[\w-]+)\s*(?:([!^$*~|]?=)\s*((['"])([^\4]*?)\4|([^'"][^\]]*?)))?\]/ }
     3504  ],
     3505
    29763506  assertions: {
    29773507    tagName: function(element, matches) {
     
    29983528
    29993529  handlers: {
    3000     // UTILITY FUNCTIONS
    3001     // joins two collections
    30023530    concat: function(a, b) {
    30033531      for (var i = 0, node; node = b[i]; i++)
     
    30063534    },
    30073535
    3008     // marks an array of nodes for counting
    30093536    mark: function(nodes) {
    30103537      var _true = Prototype.emptyFunction;
     
    30143541    },
    30153542
    3016     unmark: function(nodes) {
    3017       for (var i = 0, node; node = nodes[i]; i++)
    3018         node._countedByPrototype = undefined;
    3019       return nodes;
    3020     },
    3021 
    3022     // mark each child node with its position (for nth calls)
    3023     // "ofType" flag indicates whether we're indexing for nth-of-type
    3024     // rather than nth-child
     3543    unmark: (function(){
     3544
     3545      var PROPERTIES_ATTRIBUTES_MAP = (function(){
     3546        var el = document.createElement('div'),
     3547            isBuggy = false,
     3548            propName = '_countedByPrototype',
     3549            value = 'x'
     3550        el[propName] = value;
     3551        isBuggy = (el.getAttribute(propName) === value);
     3552        el = null;
     3553        return isBuggy;
     3554      })();
     3555
     3556      return PROPERTIES_ATTRIBUTES_MAP ?
     3557        function(nodes) {
     3558          for (var i = 0, node; node = nodes[i]; i++)
     3559            node.removeAttribute('_countedByPrototype');
     3560          return nodes;
     3561        } :
     3562        function(nodes) {
     3563          for (var i = 0, node; node = nodes[i]; i++)
     3564            node._countedByPrototype = void 0;
     3565          return nodes;
     3566        }
     3567    })(),
     3568
    30253569    index: function(parentNode, reverse, ofType) {
    30263570      parentNode._countedByPrototype = Prototype.emptyFunction;
     
    30363580    },
    30373581
    3038     // filters out duplicates and extends all nodes
    30393582    unique: function(nodes) {
    30403583      if (nodes.length == 0) return nodes;
    30413584      var results = [], n;
    30423585      for (var i = 0, l = nodes.length; i < l; i++)
    3043         if (!(n = nodes[i])._countedByPrototype) {
     3586        if (typeof (n = nodes[i])._countedByPrototype == 'undefined') {
    30443587          n._countedByPrototype = Prototype.emptyFunction;
    30453588          results.push(Element.extend(n));
     
    30483591    },
    30493592
    3050     // COMBINATOR FUNCTIONS
    30513593    descendant: function(nodes) {
    30523594      var h = Selector.handlers;
     
    30823624    nextElementSibling: function(node) {
    30833625      while (node = node.nextSibling)
    3084               if (node.nodeType == 1) return node;
     3626        if (node.nodeType == 1) return node;
    30853627      return null;
    30863628    },
     
    30923634    },
    30933635
    3094     // TOKEN FUNCTIONS
    30953636    tagName: function(nodes, root, tagName, combinator) {
    30963637      var uTagName = tagName.toUpperCase();
     
    30983639      if (nodes) {
    30993640        if (combinator) {
    3100           // fastlane for ordinary descendant combinators
    31013641          if (combinator == "descendant") {
    31023642            for (var i = 0, node; node = nodes[i]; i++)
     
    31143654    id: function(nodes, root, id, combinator) {
    31153655      var targetNode = $(id), h = Selector.handlers;
    3116       if (!targetNode) return [];
    3117       if (!nodes && root == document) return [targetNode];
     3656
     3657      if (root == document) {
     3658        if (!targetNode) return [];
     3659        if (!nodes) return [targetNode];
     3660      } else {
     3661        if (!root.sourceIndex || root.sourceIndex < 1) {
     3662          var nodes = root.getElementsByTagName('*');
     3663          for (var j = 0, node; node = nodes[j]; j++) {
     3664            if (node.id === id) return [node];
     3665          }
     3666        }
     3667      }
     3668
    31183669      if (nodes) {
    31193670        if (combinator) {
     
    32273778    },
    32283779
    3229     // handles the an+b logic
    32303780    getIndices: function(a, b, total) {
    32313781      if (a == 0) return b > 0 ? [b] : [];
     
    32363786    },
    32373787
    3238     // handles nth(-last)-child, nth(-last)-of-type, and (first|last)-of-type
    32393788    nth: function(nodes, formula, root, reverse, ofType) {
    32403789      if (nodes.length == 0) return [];
     
    32703819    'empty': function(nodes, value, root) {
    32713820      for (var i = 0, results = [], node; node = nodes[i]; i++) {
    3272         // IE treats comments as element nodes
    3273         if (node.tagName == '!' || (node.firstChild && !node.innerHTML.match(/^\s*$/))) continue;
     3821        if (node.tagName == '!' || node.firstChild) continue;
    32743822        results.push(node);
    32753823      }
     
    32893837    'enabled': function(nodes, value, root) {
    32903838      for (var i = 0, results = [], node; node = nodes[i]; i++)
    3291         if (!node.disabled) results.push(node);
     3839        if (!node.disabled && (!node.type || node.type !== 'hidden'))
     3840          results.push(node);
    32923841      return results;
    32933842    },
     
    33093858    '=':  function(nv, v) { return nv == v; },
    33103859    '!=': function(nv, v) { return nv != v; },
    3311     '^=': function(nv, v) { return nv.startsWith(v); },
    3312     '$=': function(nv, v) { return nv.endsWith(v); },
    3313     '*=': function(nv, v) { return nv.include(v); },
     3860    '^=': function(nv, v) { return nv == v || nv && nv.startsWith(v); },
     3861    '$=': function(nv, v) { return nv == v || nv && nv.endsWith(v); },
     3862    '*=': function(nv, v) { return nv == v || nv && nv.include(v); },
    33143863    '~=': function(nv, v) { return (' ' + nv + ' ').include(' ' + v + ' '); },
    3315     '|=': function(nv, v) { return ('-' + nv.toUpperCase() + '-').include('-' + v.toUpperCase() + '-'); }
     3864    '|=': function(nv, v) { return ('-' + (nv || "").toUpperCase() +
     3865     '-').include('-' + (v || "").toUpperCase() + '-'); }
    33163866  },
    33173867
     
    33533903if (Prototype.Browser.IE) {
    33543904  Object.extend(Selector.handlers, {
    3355     // IE returns comment nodes on getElementsByTagName("*").
    3356     // Filter them out.
    33573905    concat: function(a, b) {
    33583906      for (var i = 0, node; node = b[i]; i++)
    33593907        if (node.tagName !== "!") a.push(node);
    33603908      return a;
    3361     },
    3362 
    3363     // IE improperly serializes _countedByPrototype in (inner|outer)HTML.
    3364     unmark: function(nodes) {
    3365       for (var i = 0, node; node = nodes[i]; i++)
    3366         node.removeAttribute('_countedByPrototype');
    3367       return nodes;
    33683909    }
    33693910  });
     
    33733914  return Selector.findChildElements(document, $A(arguments));
    33743915}
     3916
    33753917var Form = {
    33763918  reset: function(form) {
    3377     $(form).reset();
     3919    form = $(form);
     3920    form.reset();
    33783921    return form;
    33793922  },
     
    33873930      if (!element.disabled && element.name) {
    33883931        key = element.name; value = $(element).getValue();
    3389         if (value != null && (element.type != 'submit' || (!submitted &&
     3932        if (value != null && element.type != 'file' && (element.type != 'submit' || (!submitted &&
    33903933            submit !== false && (!submit || key == submit) && (submitted = true)))) {
    33913934          if (key in result) {
    3392             // a key is already present; construct an array of values
    33933935            if (!Object.isArray(result[key])) result[key] = [result[key]];
    33943936            result[key].push(value);
     
    34103952
    34113953  getElements: function(form) {
    3412     return $A($(form).getElementsByTagName('*')).inject([],
    3413       function(elements, child) {
    3414         if (Form.Element.Serializers[child.tagName.toLowerCase()])
    3415           elements.push(Element.extend(child));
    3416         return elements;
    3417       }
    3418     );
     3954    var elements = $(form).getElementsByTagName('*'),
     3955        element,
     3956        arr = [ ],
     3957        serializers = Form.Element.Serializers;
     3958    for (var i = 0; element = elements[i]; i++) {
     3959      arr.push(element);
     3960    }
     3961    return arr.inject([], function(elements, child) {
     3962      if (serializers[child.tagName.toLowerCase()])
     3963        elements.push(Element.extend(child));
     3964      return elements;
     3965    })
    34193966  },
    34203967
     
    34564003
    34574004    return firstByIndex ? firstByIndex : elements.find(function(element) {
    3458       return ['input', 'select', 'textarea'].include(element.tagName.toLowerCase());
     4005      return /^(?:input|select|textarea)$/i.test(element.tagName);
    34594006    });
    34604007  },
     
    34874034/*--------------------------------------------------------------------------*/
    34884035
     4036
    34894037Form.Element = {
    34904038  focus: function(element) {
     
    35004048
    35014049Form.Element.Methods = {
     4050
    35024051  serialize: function(element) {
    35034052    element = $(element);
     
    35404089      element.focus();
    35414090      if (element.select && (element.tagName.toLowerCase() != 'input' ||
    3542           !['button', 'reset', 'submit'].include(element.type)))
     4091          !(/^(?:button|reset|submit)$/i.test(element.type))))
    35434092        element.select();
    35444093    } catch (e) { }
     
    35484097  disable: function(element) {
    35494098    element = $(element);
    3550     element.blur();
    35514099    element.disabled = true;
    35524100    return element;
     
    35634111
    35644112var Field = Form.Element;
     4113
    35654114var $F = Form.Element.Methods.getValue;
    35664115
     
    35884137  },
    35894138
    3590   select: function(element, index) {
    3591     if (Object.isUndefined(index))
     4139  select: function(element, value) {
     4140    if (Object.isUndefined(value))
    35924141      return this[element.type == 'select-one' ?
    35934142        'selectOne' : 'selectMany'](element);
    35944143    else {
    3595       var opt, value, single = !Object.isArray(index);
     4144      var opt, currentValue, single = !Object.isArray(value);
    35964145      for (var i = 0, length = element.length; i < length; i++) {
    35974146        opt = element.options[i];
    3598         value = this.optionValue(opt);
     4147        currentValue = this.optionValue(opt);
    35994148        if (single) {
    3600           if (value == index) {
     4149          if (currentValue == value) {
    36014150            opt.selected = true;
    36024151            return;
    36034152          }
    36044153        }
    3605         else opt.selected = index.include(value);
     4154        else opt.selected = value.include(currentValue);
    36064155      }
    36074156    }
     
    36254174
    36264175  optionValue: function(opt) {
    3627     // extend element because hasAttribute may not be native
    36284176    return Element.extend(opt).hasAttribute('value') ? opt.value : opt.text;
    36294177  }
     
    36314179
    36324180/*--------------------------------------------------------------------------*/
     4181
    36334182
    36344183Abstract.TimedObserver = Class.create(PeriodicalExecuter, {
     
    37134262  }
    37144263});
    3715 if (!window.Event) var Event = { };
    3716 
    3717 Object.extend(Event, {
    3718   KEY_BACKSPACE: 8,
    3719   KEY_TAB:       9,
    3720   KEY_RETURN:   13,
    3721   KEY_ESC:      27,
    3722   KEY_LEFT:     37,
    3723   KEY_UP:       38,
    3724   KEY_RIGHT:    39,
    3725   KEY_DOWN:     40,
    3726   KEY_DELETE:   46,
    3727   KEY_HOME:     36,
    3728   KEY_END:      35,
    3729   KEY_PAGEUP:   33,
    3730   KEY_PAGEDOWN: 34,
    3731   KEY_INSERT:   45,
    3732 
    3733   cache: { },
    3734 
    3735   relatedTarget: function(event) {
    3736     var element;
    3737     switch(event.type) {
    3738       case 'mouseover': element = event.fromElement; break;
    3739       case 'mouseout':  element = event.toElement;   break;
    3740       default: return null;
    3741     }
    3742     return Element.extend(element);
    3743   }
    3744 });
    3745 
    3746 Event.Methods = (function() {
    3747   var isButton;
    3748 
     4264(function() {
     4265
     4266  var Event = {
     4267    KEY_BACKSPACE: 8,
     4268    KEY_TAB:       9,
     4269    KEY_RETURN:   13,
     4270    KEY_ESC:      27,
     4271    KEY_LEFT:     37,
     4272    KEY_UP:       38,
     4273    KEY_RIGHT:    39,
     4274    KEY_DOWN:     40,
     4275    KEY_DELETE:   46,
     4276    KEY_HOME:     36,
     4277    KEY_END:      35,
     4278    KEY_PAGEUP:   33,
     4279    KEY_PAGEDOWN: 34,
     4280    KEY_INSERT:   45,
     4281
     4282    cache: {}
     4283  };
     4284
     4285  var docEl = document.documentElement;
     4286  var MOUSEENTER_MOUSELEAVE_EVENTS_SUPPORTED = 'onmouseenter' in docEl
     4287    && 'onmouseleave' in docEl;
     4288
     4289  var _isButton;
    37494290  if (Prototype.Browser.IE) {
    37504291    var buttonMap = { 0: 1, 1: 4, 2: 2 };
    3751     isButton = function(event, code) {
    3752       return event.button == buttonMap[code];
     4292    _isButton = function(event, code) {
     4293      return event.button === buttonMap[code];
    37534294    };
    3754 
    37554295  } else if (Prototype.Browser.WebKit) {
    3756     isButton = function(event, code) {
     4296    _isButton = function(event, code) {
    37574297      switch (code) {
    37584298        case 0: return event.which == 1 && !event.metaKey;
     
    37614301      }
    37624302    };
    3763 
    37644303  } else {
    3765     isButton = function(event, code) {
     4304    _isButton = function(event, code) {
    37664305      return event.which ? (event.which === code + 1) : (event.button === code);
    37674306    };
    37684307  }
    37694308
    3770   return {
    3771     isLeftClick:   function(event) { return isButton(event, 0) },
    3772     isMiddleClick: function(event) { return isButton(event, 1) },
    3773     isRightClick:  function(event) { return isButton(event, 2) },
    3774 
    3775     element: function(event) {
    3776       var node = Event.extend(event).target;
    3777       return Element.extend(node.nodeType == Node.TEXT_NODE ? node.parentNode : node);
    3778     },
    3779 
    3780     findElement: function(event, expression) {
    3781       var element = Event.element(event);
    3782       if (!expression) return element;
    3783       var elements = [element].concat(element.ancestors());
    3784       return Selector.findElement(elements, expression, 0);
    3785     },
    3786 
    3787     pointer: function(event) {
    3788       return {
    3789         x: event.pageX || (event.clientX +
    3790           (document.documentElement.scrollLeft || document.body.scrollLeft)),
    3791         y: event.pageY || (event.clientY +
    3792           (document.documentElement.scrollTop || document.body.scrollTop))
    3793       };
    3794     },
    3795 
    3796     pointerX: function(event) { return Event.pointer(event).x },
    3797     pointerY: function(event) { return Event.pointer(event).y },
    3798 
    3799     stop: function(event) {
    3800       Event.extend(event);
    3801       event.preventDefault();
    3802       event.stopPropagation();
    3803       event.stopped = true;
    3804     }
     4309  function isLeftClick(event)   { return _isButton(event, 0) }
     4310
     4311  function isMiddleClick(event) { return _isButton(event, 1) }
     4312
     4313  function isRightClick(event)  { return _isButton(event, 2) }
     4314
     4315  function element(event) {
     4316    event = Event.extend(event);
     4317
     4318    var node = event.target, type = event.type,
     4319     currentTarget = event.currentTarget;
     4320
     4321    if (currentTarget && currentTarget.tagName) {
     4322      if (type === 'load' || type === 'error' ||
     4323        (type === 'click' && currentTarget.tagName.toLowerCase() === 'input'
     4324          && currentTarget.type === 'radio'))
     4325            node = currentTarget;
     4326    }
     4327
     4328    if (node.nodeType == Node.TEXT_NODE)
     4329      node = node.parentNode;
     4330
     4331    return Element.extend(node);
     4332  }
     4333
     4334  function findElement(event, expression) {
     4335    var element = Event.element(event);
     4336    if (!expression) return element;
     4337    var elements = [element].concat(element.ancestors());
     4338    return Selector.findElement(elements, expression, 0);
     4339  }
     4340
     4341  function pointer(event) {
     4342    return { x: pointerX(event), y: pointerY(event) };
     4343  }
     4344
     4345  function pointerX(event) {
     4346    var docElement = document.documentElement,
     4347     body = document.body || { scrollLeft: 0 };
     4348
     4349    return event.pageX || (event.clientX +
     4350      (docElement.scrollLeft || body.scrollLeft) -
     4351      (docElement.clientLeft || 0));
     4352  }
     4353
     4354  function pointerY(event) {
     4355    var docElement = document.documentElement,
     4356     body = document.body || { scrollTop: 0 };
     4357
     4358    return  event.pageY || (event.clientY +
     4359       (docElement.scrollTop || body.scrollTop) -
     4360       (docElement.clientTop || 0));
     4361  }
     4362
     4363
     4364  function stop(event) {
     4365    Event.extend(event);
     4366    event.preventDefault();
     4367    event.stopPropagation();
     4368
     4369    event.stopped = true;
     4370  }
     4371
     4372  Event.Methods = {
     4373    isLeftClick: isLeftClick,
     4374    isMiddleClick: isMiddleClick,
     4375    isRightClick: isRightClick,
     4376
     4377    element: element,
     4378    findElement: findElement,
     4379
     4380    pointer: pointer,
     4381    pointerX: pointerX,
     4382    pointerY: pointerY,
     4383
     4384    stop: stop
    38054385  };
    3806 })();
    3807 
    3808 Event.extend = (function() {
     4386
     4387
    38094388  var methods = Object.keys(Event.Methods).inject({ }, function(m, name) {
    38104389    m[name] = Event.Methods[name].methodize();
     
    38134392
    38144393  if (Prototype.Browser.IE) {
     4394    function _relatedTarget(event) {
     4395      var element;
     4396      switch (event.type) {
     4397        case 'mouseover': element = event.fromElement; break;
     4398        case 'mouseout':  element = event.toElement;   break;
     4399        default: return null;
     4400      }
     4401      return Element.extend(element);
     4402    }
     4403
    38154404    Object.extend(methods, {
    38164405      stopPropagation: function() { this.cancelBubble = true },
    38174406      preventDefault:  function() { this.returnValue = false },
    3818       inspect: function() { return "[object Event]" }
     4407      inspect: function() { return '[object Event]' }
    38194408    });
    38204409
    3821     return function(event) {
     4410    Event.extend = function(event, element) {
    38224411      if (!event) return false;
    38234412      if (event._extendedByPrototype) return event;
     
    38254414      event._extendedByPrototype = Prototype.emptyFunction;
    38264415      var pointer = Event.pointer(event);
     4416
    38274417      Object.extend(event, {
    3828         target: event.srcElement,
    3829         relatedTarget: Event.relatedTarget(event),
     4418        target: event.srcElement || element,
     4419        relatedTarget: _relatedTarget(event),
    38304420        pageX:  pointer.x,
    38314421        pageY:  pointer.y
    38324422      });
     4423
    38334424      return Object.extend(event, methods);
    38344425    };
    3835 
    38364426  } else {
    3837     Event.prototype = Event.prototype || document.createEvent("HTMLEvents").__proto__;
     4427    Event.prototype = window.Event.prototype || document.createEvent('HTMLEvents').__proto__;
    38384428    Object.extend(Event.prototype, methods);
    3839     return Prototype.K;
    3840   }
     4429    Event.extend = Prototype.K;
     4430  }
     4431
     4432  function _createResponder(element, eventName, handler) {
     4433    var registry = Element.retrieve(element, 'prototype_event_registry');
     4434
     4435    if (Object.isUndefined(registry)) {
     4436      CACHE.push(element);
     4437      registry = Element.retrieve(element, 'prototype_event_registry', $H());
     4438    }
     4439
     4440    var respondersForEvent = registry.get(eventName);
     4441    if (Object.isUndefined(respondersForEvent)) {
     4442      respondersForEvent = [];
     4443      registry.set(eventName, respondersForEvent);
     4444    }
     4445
     4446    if (respondersForEvent.pluck('handler').include(handler)) return false;
     4447
     4448    var responder;
     4449    if (eventName.include(":")) {
     4450      responder = function(event) {
     4451        if (Object.isUndefined(event.eventName))
     4452          return false;
     4453
     4454        if (event.eventName !== eventName)
     4455          return false;
     4456
     4457        Event.extend(event, element);
     4458        handler.call(element, event);
     4459      };
     4460    } else {
     4461      if (!MOUSEENTER_MOUSELEAVE_EVENTS_SUPPORTED &&
     4462       (eventName === "mouseenter" || eventName === "mouseleave")) {
     4463        if (eventName === "mouseenter" || eventName === "mouseleave") {
     4464          responder = function(event) {
     4465            Event.extend(event, element);
     4466
     4467            var parent = event.relatedTarget;
     4468            while (parent && parent !== element) {
     4469              try { parent = parent.parentNode; }
     4470              catch(e) { parent = element; }
     4471            }
     4472
     4473            if (parent === element) return;
     4474
     4475            handler.call(element, event);
     4476          };
     4477        }
     4478      } else {
     4479        responder = function(event) {
     4480          Event.extend(event, element);
     4481          handler.call(element, event);
     4482        };
     4483      }
     4484    }
     4485
     4486    responder.handler = handler;
     4487    respondersForEvent.push(responder);
     4488    return responder;
     4489  }
     4490
     4491  function _destroyCache() {
     4492    for (var i = 0, length = CACHE.length; i < length; i++) {
     4493      Event.stopObserving(CACHE[i]);
     4494      CACHE[i] = null;
     4495    }
     4496  }
     4497
     4498  var CACHE = [];
     4499
     4500  if (Prototype.Browser.IE)
     4501    window.attachEvent('onunload', _destroyCache);
     4502
     4503  if (Prototype.Browser.WebKit)
     4504    window.addEventListener('unload', Prototype.emptyFunction, false);
     4505
     4506
     4507  var _getDOMEventName = Prototype.K;
     4508
     4509  if (!MOUSEENTER_MOUSELEAVE_EVENTS_SUPPORTED) {
     4510    _getDOMEventName = function(eventName) {
     4511      var translations = { mouseenter: "mouseover", mouseleave: "mouseout" };
     4512      return eventName in translations ? translations[eventName] : eventName;
     4513    };
     4514  }
     4515
     4516  function observe(element, eventName, handler) {
     4517    element = $(element);
     4518
     4519    var responder = _createResponder(element, eventName, handler);
     4520
     4521    if (!responder) return element;
     4522
     4523    if (eventName.include(':')) {
     4524      if (element.addEventListener)
     4525        element.addEventListener("dataavailable", responder, false);
     4526      else {
     4527        element.attachEvent("ondataavailable", responder);
     4528        element.attachEvent("onfilterchange", responder);
     4529      }
     4530    } else {
     4531      var actualEventName = _getDOMEventName(eventName);
     4532
     4533      if (element.addEventListener)
     4534        element.addEventListener(actualEventName, responder, false);
     4535      else
     4536        element.attachEvent("on" + actualEventName, responder);
     4537    }
     4538
     4539    return element;
     4540  }
     4541
     4542  function stopObserving(element, eventName, handler) {
     4543    element = $(element);
     4544
     4545    var registry = Element.retrieve(element, 'prototype_event_registry');
     4546
     4547    if (Object.isUndefined(registry)) return element;
     4548
     4549    if (eventName && !handler) {
     4550      var responders = registry.get(eventName);
     4551
     4552      if (Object.isUndefined(responders)) return element;
     4553
     4554      responders.each( function(r) {
     4555        Element.stopObserving(element, eventName, r.handler);
     4556      });
     4557      return element;
     4558    } else if (!eventName) {
     4559      registry.each( function(pair) {
     4560        var eventName = pair.key, responders = pair.value;
     4561
     4562        responders.each( function(r) {
     4563          Element.stopObserving(element, eventName, r.handler);
     4564        });
     4565      });
     4566      return element;
     4567    }
     4568
     4569    var responders = registry.get(eventName);
     4570
     4571    if (!responders) return;
     4572
     4573    var responder = responders.find( function(r) { return r.handler === handler; });
     4574    if (!responder) return element;
     4575
     4576    var actualEventName = _getDOMEventName(eventName);
     4577
     4578    if (eventName.include(':')) {
     4579      if (element.removeEventListener)
     4580        element.removeEventListener("dataavailable", responder, false);
     4581      else {
     4582        element.detachEvent("ondataavailable", responder);
     4583        element.detachEvent("onfilterchange",  responder);
     4584      }
     4585    } else {
     4586      if (element.removeEventListener)
     4587        element.removeEventListener(actualEventName, responder, false);
     4588      else
     4589        element.detachEvent('on' + actualEventName, responder);
     4590    }
     4591
     4592    registry.set(eventName, responders.without(responder));
     4593
     4594    return element;
     4595  }
     4596
     4597  function fire(element, eventName, memo, bubble) {
     4598    element = $(element);
     4599
     4600    if (Object.isUndefined(bubble))
     4601      bubble = true;
     4602
     4603    if (element == document && document.createEvent && !element.dispatchEvent)
     4604      element = document.documentElement;
     4605
     4606    var event;
     4607    if (document.createEvent) {
     4608      event = document.createEvent('HTMLEvents');
     4609      event.initEvent('dataavailable', true, true);
     4610    } else {
     4611      event = document.createEventObject();
     4612      event.eventType = bubble ? 'ondataavailable' : 'onfilterchange';
     4613    }
     4614
     4615    event.eventName = eventName;
     4616    event.memo = memo || { };
     4617
     4618    if (document.createEvent)
     4619      element.dispatchEvent(event);
     4620    else
     4621      element.fireEvent(event.eventType, event);
     4622
     4623    return Event.extend(event);
     4624  }
     4625
     4626
     4627  Object.extend(Event, Event.Methods);
     4628
     4629  Object.extend(Event, {
     4630    fire:          fire,
     4631    observe:       observe,
     4632    stopObserving: stopObserving
     4633  });
     4634
     4635  Element.addMethods({
     4636    fire:          fire,
     4637
     4638    observe:       observe,
     4639
     4640    stopObserving: stopObserving
     4641  });
     4642
     4643  Object.extend(document, {
     4644    fire:          fire.methodize(),
     4645
     4646    observe:       observe.methodize(),
     4647
     4648    stopObserving: stopObserving.methodize(),
     4649
     4650    loaded:        false
     4651  });
     4652
     4653  if (window.Event) Object.extend(window.Event, Event);
     4654  else window.Event = Event;
    38414655})();
    3842 
    3843 Object.extend(Event, (function() {
    3844   var cache = Event.cache;
    3845 
    3846   function getEventID(element) {
    3847     if (element._prototypeEventID) return element._prototypeEventID[0];
    3848     arguments.callee.id = arguments.callee.id || 1;
    3849     return element._prototypeEventID = [++arguments.callee.id];
    3850   }
    3851 
    3852   function getDOMEventName(eventName) {
    3853     if (eventName && eventName.include(':')) return "dataavailable";
    3854     return eventName;
    3855   }
    3856 
    3857   function getCacheForID(id) {
    3858     return cache[id] = cache[id] || { };
    3859   }
    3860 
    3861   function getWrappersForEventName(id, eventName) {
    3862     var c = getCacheForID(id);
    3863     return c[eventName] = c[eventName] || [];
    3864   }
    3865 
    3866   function createWrapper(element, eventName, handler) {
    3867     var id = getEventID(element);
    3868     var c = getWrappersForEventName(id, eventName);
    3869     if (c.pluck("handler").include(handler)) return false;
    3870 
    3871     var wrapper = function(event) {
    3872       if (!Event || !Event.extend ||
    3873         (event.eventName && event.eventName != eventName))
    3874           return false;
    3875 
    3876       Event.extend(event);
    3877       handler.call(element, event);
    3878     };
    3879 
    3880     wrapper.handler = handler;
    3881     c.push(wrapper);
    3882     return wrapper;
    3883   }
    3884 
    3885   function findWrapper(id, eventName, handler) {
    3886     var c = getWrappersForEventName(id, eventName);
    3887     return c.find(function(wrapper) { return wrapper.handler == handler });
    3888   }
    3889 
    3890   function destroyWrapper(id, eventName, handler) {
    3891     var c = getCacheForID(id);
    3892     if (!c[eventName]) return false;
    3893     c[eventName] = c[eventName].without(findWrapper(id, eventName, handler));
    3894   }
    3895 
    3896   function destroyCache() {
    3897     for (var id in cache)
    3898       for (var eventName in cache[id])
    3899         cache[id][eventName] = null;
    3900   }
    3901 
    3902   if (window.attachEvent) {
    3903     window.attachEvent("onunload", destroyCache);
    3904   }
    3905 
    3906   return {
    3907     observe: function(element, eventName, handler) {
    3908       element = $(element);
    3909       var name = getDOMEventName(eventName);
    3910 
    3911       var wrapper = createWrapper(element, eventName, handler);
    3912       if (!wrapper) return element;
    3913 
    3914       if (element.addEventListener) {
    3915         element.addEventListener(name, wrapper, false);
    3916       } else {
    3917         element.attachEvent("on" + name, wrapper);
    3918       }
    3919 
    3920       return element;
    3921     },
    3922 
    3923     stopObserving: function(element, eventName, handler) {
    3924       element = $(element);
    3925       var id = getEventID(element), name = getDOMEventName(eventName);
    3926 
    3927       if (!handler && eventName) {
    3928         getWrappersForEventName(id, eventName).each(function(wrapper) {
    3929           element.stopObserving(eventName, wrapper.handler);
    3930         });
    3931         return element;
    3932 
    3933       } else if (!eventName) {
    3934         Object.keys(getCacheForID(id)).each(function(eventName) {
    3935           element.stopObserving(eventName);
    3936         });
    3937         return element;
    3938       }
    3939 
    3940       var wrapper = findWrapper(id, eventName, handler);
    3941       if (!wrapper) return element;
    3942 
    3943       if (element.removeEventListener) {
    3944         element.removeEventListener(name, wrapper, false);
    3945       } else {
    3946         element.detachEvent("on" + name, wrapper);
    3947       }
    3948 
    3949       destroyWrapper(id, eventName, handler);
    3950 
    3951       return element;
    3952     },
    3953 
    3954     fire: function(element, eventName, memo) {
    3955       element = $(element);
    3956       if (element == document && document.createEvent && !element.dispatchEvent)
    3957         element = document.documentElement;
    3958 
    3959       var event;
    3960       if (document.createEvent) {
    3961         event = document.createEvent("HTMLEvents");
    3962         event.initEvent("dataavailable", true, true);
    3963       } else {
    3964         event = document.createEventObject();
    3965         event.eventType = "ondataavailable";
    3966       }
    3967 
    3968       event.eventName = eventName;
    3969       event.memo = memo || { };
    3970 
    3971       if (document.createEvent) {
    3972         element.dispatchEvent(event);
    3973       } else {
    3974         element.fireEvent(event.eventType, event);
    3975       }
    3976 
    3977       return Event.extend(event);
    3978     }
    3979   };
    3980 })());
    3981 
    3982 Object.extend(Event, Event.Methods);
    3983 
    3984 Element.addMethods({
    3985   fire:          Event.fire,
    3986   observe:       Event.observe,
    3987   stopObserving: Event.stopObserving
    3988 });
    3989 
    3990 Object.extend(document, {
    3991   fire:          Element.Methods.fire.methodize(),
    3992   observe:       Element.Methods.observe.methodize(),
    3993   stopObserving: Element.Methods.stopObserving.methodize(),
    3994   loaded:        false
    3995 });
    39964656
    39974657(function() {
    39984658  /* Support for the DOMContentLoaded event is based on work by Dan Webb,
    3999      Matthias Miller, Dean Edwards and John Resig. */
     4659     Matthias Miller, Dean Edwards, John Resig, and Diego Perini. */
    40004660
    40014661  var timer;
     
    40034663  function fireContentLoadedEvent() {
    40044664    if (document.loaded) return;
    4005     if (timer) window.clearInterval(timer);
    4006     document.fire("dom:loaded");
     4665    if (timer) window.clearTimeout(timer);
    40074666    document.loaded = true;
     4667    document.fire('dom:loaded');
     4668  }
     4669
     4670  function checkReadyState() {
     4671    if (document.readyState === 'complete') {
     4672      document.stopObserving('readystatechange', checkReadyState);
     4673      fireContentLoadedEvent();
     4674    }
     4675  }
     4676
     4677  function pollDoScroll() {
     4678    try { document.documentElement.doScroll('left'); }
     4679    catch(e) {
     4680      timer = pollDoScroll.defer();
     4681      return;
     4682    }
     4683    fireContentLoadedEvent();
    40084684  }
    40094685
    40104686  if (document.addEventListener) {
    4011     if (Prototype.Browser.WebKit) {
    4012       timer = window.setInterval(function() {
    4013         if (/loaded|complete/.test(document.readyState))
    4014           fireContentLoadedEvent();
    4015       }, 0);
    4016 
    4017       Event.observe(window, "load", fireContentLoadedEvent);
    4018 
    4019     } else {
    4020       document.addEventListener("DOMContentLoaded",
    4021         fireContentLoadedEvent, false);
    4022     }
    4023 
     4687    document.addEventListener('DOMContentLoaded', fireContentLoadedEvent, false);
    40244688  } else {
    4025     document.write("<script id=__onDOMContentLoaded defer src=//:><\/script>");
    4026     $("__onDOMContentLoaded").onreadystatechange = function() {
    4027       if (this.readyState == "complete") {
    4028         this.onreadystatechange = null;
    4029         fireContentLoadedEvent();
    4030       }
    4031     };
    4032   }
     4689    document.observe('readystatechange', checkReadyState);
     4690    if (window == top)
     4691      timer = pollDoScroll.defer();
     4692  }
     4693
     4694  Event.observe(window, 'load', fireContentLoadedEvent);
    40334695})();
     4696
     4697Element.addMethods();
     4698
    40344699/*------------------------------- DEPRECATED -------------------------------*/
    40354700
     
    40604725var $continue = new Error('"throw $continue" is deprecated, use "return" instead');
    40614726
    4062 // This should be moved to script.aculo.us; notice the deprecated methods
    4063 // further below, that map to the newer Element methods.
    40644727var Position = {
    4065   // set to true if needed, warning: firefox performance problems
    4066   // NOT neeeded for page scrolling, only if draggable contained in
    4067   // scrollable elements
    40684728  includeScrollOffsets: false,
    40694729
    4070   // must be called before calling withinIncludingScrolloffset, every time the
    4071   // page is scrolled
    40724730  prepare: function() {
    40734731    this.deltaX =  window.pageXOffset
     
    40814739  },
    40824740
    4083   // caches x/y coordinate pair to use with overlap
    40844741  within: function(element, x, y) {
    40854742    if (this.includeScrollOffsets)
     
    41084765  },
    41094766
    4110   // within must be called directly before
    41114767  overlap: function(mode, element) {
    41124768    if (!mode) return 0;
     
    41194775  },
    41204776
    4121   // Deprecation layer -- use newer Element methods now (1.5.2).
    41224777
    41234778  cumulativeOffset: Element.Methods.cumulativeOffset,
     
    42184873
    42194874/*--------------------------------------------------------------------------*/
    4220 
    4221 Element.addMethods();
Note: See TracChangeset for help on using the changeset viewer.