Show
Ignore:
Timestamp:
06/21/06 11:53:01 (6 years ago)
Author:
john
Message:

updated scriptaculous js files

Location:
trunk/trax/vendor/trax/action_view/helpers
Files:
3 added
5 modified

Legend:

Unmodified
Added
Removed
  • trunk/trax/vendor/trax/action_view/helpers/asset_tag_helper.php

    r207 r226  
    4949            array_key_exists('JAVASCRIPT_DEFAULT_SOURCES',$GLOBALS) 
    5050            ? $GLOBALS['JAVASCRIPT_DEFAULT_SOURCES'] 
    51             : array('prototype', 'effects', 'dragdrop', 'controls');     
     51            : array('prototype', 'effects', 'dragdrop', 'controls', 'slider', 'builder');     
    5252    } 
    5353     
  • trunk/trax/vendor/trax/action_view/helpers/javascripts/controls.js

    r148 r226  
    66//  Rahul Bhargava 
    77//  Rob Wills 
    8 //  
     8//   
    99// See scriptaculous.js for full license. 
    1010 
     
    142142      } 
    143143     else  
    144       if(event.keyCode==Event.KEY_TAB || event.keyCode==Event.KEY_RETURN)  
    145         return; 
     144       if(event.keyCode==Event.KEY_TAB || event.keyCode==Event.KEY_RETURN ||  
     145         (navigator.appVersion.indexOf('AppleWebKit') > 0 && event.keyCode == 0)) return; 
    146146 
    147147    this.changed = true; 
     
    151151      this.observer =  
    152152        setTimeout(this.onObserverEvent.bind(this), this.options.frequency*1000); 
     153  }, 
     154 
     155  activate: function() { 
     156    this.changed = false; 
     157    this.hasFocus = true; 
     158    this.getUpdatedChoices(); 
    153159  }, 
    154160 
     
    311317Object.extend(Object.extend(Ajax.Autocompleter.prototype, Autocompleter.Base.prototype), { 
    312318  initialize: function(element, update, url, options) { 
    313       this.baseInitialize(element, update, options); 
     319    this.baseInitialize(element, update, options); 
    314320    this.options.asynchronous  = true; 
    315321    this.options.onComplete    = this.onComplete.bind(this); 
     
    478484      highlightcolor: Ajax.InPlaceEditor.defaultHighlightColor, 
    479485      highlightendcolor: "#FFFFFF", 
    480       externalControl:  null, 
     486      externalControl: null, 
    481487      submitOnBlur: false, 
    482       ajaxOptions: {} 
     488      ajaxOptions: {}, 
     489      evalScripts: false 
    483490    }, options || {}); 
    484491 
     
    549556      okButton.type = "submit"; 
    550557      okButton.value = this.options.okText; 
     558      okButton.className = 'editor_ok_button'; 
    551559      this.form.appendChild(okButton); 
    552560    } 
     
    557565      cancelLink.appendChild(document.createTextNode(this.options.cancelText)); 
    558566      cancelLink.onclick = this.onclickCancel.bind(this); 
     567      cancelLink.className = 'editor_cancel';       
    559568      this.form.appendChild(cancelLink); 
    560569    } 
     
    585594      textField.value = text; 
    586595      textField.style.backgroundColor = this.options.highlightcolor; 
     596      textField.className = 'editor_field'; 
    587597      var size = this.options.size || this.options.cols || 0; 
    588598      if (size != 0) textField.size = size; 
     
    598608      textArea.rows = this.options.rows; 
    599609      textArea.cols = this.options.cols || 40; 
     610      textArea.className = 'editor_field';       
    600611      if (this.options.submitOnBlur) 
    601612        textArea.onblur = this.onSubmit.bind(this); 
     
    650661    this.onLoading(); 
    651662     
    652     new Ajax.Updater( 
    653       {  
    654         success: this.element, 
    655          // don't update on failure (this could be an option) 
    656         failure: null 
    657       }, 
    658       this.url, 
    659       Object.extend({ 
    660         parameters: this.options.callback(form, value), 
    661         onComplete: this.onComplete.bind(this), 
    662         onFailure: this.onFailure.bind(this) 
    663       }, this.options.ajaxOptions) 
    664     ); 
     663    if (this.options.evalScripts) { 
     664      new Ajax.Request( 
     665        this.url, Object.extend({ 
     666          parameters: this.options.callback(form, value), 
     667          onComplete: this.onComplete.bind(this), 
     668          onFailure: this.onFailure.bind(this), 
     669          asynchronous:true,  
     670          evalScripts:true 
     671        }, this.options.ajaxOptions)); 
     672    } else  { 
     673      new Ajax.Updater( 
     674        { success: this.element, 
     675          // don't update on failure (this could be an option) 
     676          failure: null },  
     677        this.url, Object.extend({ 
     678          parameters: this.options.callback(form, value), 
     679          onComplete: this.onComplete.bind(this), 
     680          onFailure: this.onFailure.bind(this) 
     681        }, this.options.ajaxOptions)); 
     682    } 
    665683    // stop the event to avoid a page refresh in Safari 
    666684    if (arguments.length > 1) { 
     
    743761  } 
    744762}; 
     763 
     764Ajax.InPlaceCollectionEditor = Class.create(); 
     765Object.extend(Ajax.InPlaceCollectionEditor.prototype, Ajax.InPlaceEditor.prototype); 
     766Object.extend(Ajax.InPlaceCollectionEditor.prototype, { 
     767  createEditField: function() { 
     768    if (!this.cached_selectTag) { 
     769      var selectTag = document.createElement("select"); 
     770      var collection = this.options.collection || []; 
     771      var optionTag; 
     772      collection.each(function(e,i) { 
     773        optionTag = document.createElement("option"); 
     774        optionTag.value = (e instanceof Array) ? e[0] : e; 
     775        if(this.options.value==optionTag.value) optionTag.selected = true; 
     776        optionTag.appendChild(document.createTextNode((e instanceof Array) ? e[1] : e)); 
     777        selectTag.appendChild(optionTag); 
     778      }.bind(this)); 
     779      this.cached_selectTag = selectTag; 
     780    } 
     781 
     782    this.editField = this.cached_selectTag; 
     783    if(this.options.loadTextURL) this.loadExternalText(); 
     784    this.form.appendChild(this.editField); 
     785    this.options.callback = function(form, value) { 
     786      return "value=" + encodeURIComponent(value); 
     787    } 
     788  } 
     789}); 
    745790 
    746791// Delayed observer, like Form.Element.Observer,  
  • trunk/trax/vendor/trax/action_view/helpers/javascripts/dragdrop.js

    r148 r226  
    11// Copyright (c) 2005 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us) 
    2 //  
     2//           (c) 2005 Sammi Williams (http://www.oriontransfer.co.nz, sammi@oriontransfer.co.nz) 
     3//   
    34// See scriptaculous.js for full license. 
    45 
     
    1617    var options = Object.extend({ 
    1718      greedy:     true, 
    18       hoverclass: null   
     19      hoverclass: null, 
     20      tree:       false 
    1921    }, arguments[1] || {}); 
    2022 
     
    3840    this.drops.push(options); 
    3941  }, 
     42   
     43  findDeepestChild: function(drops) { 
     44    deepest = drops[0]; 
     45       
     46    for (i = 1; i < drops.length; ++i) 
     47      if (Element.isParent(drops[i].element, deepest.element)) 
     48        deepest = drops[i]; 
     49     
     50    return deepest; 
     51  }, 
    4052 
    4153  isContained: function(element, drop) { 
    42     var parentNode = element.parentNode; 
    43     return drop._containers.detect(function(c) { return parentNode == c }); 
    44   }, 
    45  
     54    var containmentNode; 
     55    if(drop.tree) { 
     56      containmentNode = element.treeNode;  
     57    } else { 
     58      containmentNode = element.parentNode; 
     59    } 
     60    return drop._containers.detect(function(c) { return containmentNode == c }); 
     61  }, 
     62   
    4663  isAffected: function(point, element, drop) { 
    4764    return ( 
     
    6986  show: function(point, element) { 
    7087    if(!this.drops.length) return; 
     88    var affected = []; 
    7189     
    7290    if(this.last_active) this.deactivate(this.last_active); 
    7391    this.drops.each( function(drop) { 
    74       if(Droppables.isAffected(point, element, drop)) { 
    75         if(drop.onHover) 
    76            drop.onHover(element, drop.element, Position.overlap(drop.overlap, drop.element)); 
    77         if(drop.greedy) {  
    78           Droppables.activate(drop); 
    79           throw $break; 
    80         } 
    81       } 
     92      if(Droppables.isAffected(point, element, drop)) 
     93        affected.push(drop); 
    8294    }); 
     95         
     96    if(affected.length>0) { 
     97      drop = Droppables.findDeepestChild(affected); 
     98      Position.within(drop.element, point[0], point[1]); 
     99      if(drop.onHover) 
     100        drop.onHover(element, drop.element, Position.overlap(drop.overlap, drop.element)); 
     101       
     102      Droppables.activate(drop); 
     103    } 
    83104  }, 
    84105 
     
    129150  }, 
    130151   
    131   deactivate: function(draggbale) { 
     152  deactivate: function() { 
    132153    this.activeDraggable = null; 
    133154  }, 
     
    188209    var options = Object.extend({ 
    189210      handle: false, 
    190       starteffect: function(element) {  
    191         new Effect.Opacity(element, {duration:0.2, from:1.0, to:0.7});  
     211      starteffect: function(element) { 
     212        element._opacity = Element.getOpacity(element);  
     213        new Effect.Opacity(element, {duration:0.2, from:element._opacity, to:0.7});  
    192214      }, 
    193215      reverteffect: function(element, top_offset, left_offset) { 
     
    195217        element._revert = new Effect.Move(element, { x: -left_offset, y: -top_offset, duration: dur}); 
    196218      }, 
    197       endeffect: function(element) {  
    198         new Effect.Opacity(element, {duration:0.2, from:0.7, to:1.0});  
     219      endeffect: function(element) { 
     220        var toOpacity = typeof element._opacity == 'number' ? element._opacity : 1.0 
     221        new Effect.Opacity(element, {duration:0.2, from:0.7, to:toOpacity});  
    199222      }, 
    200223      zindex: 1000, 
    201224      revert: false, 
     225      scroll: false, 
     226      scrollSensitivity: 20, 
     227      scrollSpeed: 15, 
    202228      snap: false   // false, or xy or [x,y] or function(x,y){ return [x,y] } 
    203229    }, arguments[1] || {}); 
     
    205231    this.element = $(element); 
    206232     
    207     if(options.handle && (typeof options.handle == 'string')) 
    208       this.handle = Element.childrenWithClassName(this.element, options.handle)[0];   
     233    if(options.handle && (typeof options.handle == 'string')) { 
     234      var h = Element.childrenWithClassName(this.element, options.handle, true); 
     235      if(h.length>0) this.handle = h[0]; 
     236    } 
    209237    if(!this.handle) this.handle = $(options.handle); 
    210238    if(!this.handle) this.handle = this.element; 
     239     
     240    if(options.scroll && !options.scroll.scrollTo && !options.scroll.outerHTML) 
     241      options.scroll = $(options.scroll); 
    211242 
    212243    Element.makePositioned(this.element); // fix IE     
     
    240271        src.tagName=='INPUT' || 
    241272        src.tagName=='SELECT' || 
     273        src.tagName=='OPTION' || 
    242274        src.tagName=='BUTTON' || 
    243275        src.tagName=='TEXTAREA')) return; 
     
    269301      Position.absolutize(this.element); 
    270302      this.element.parentNode.insertBefore(this._clone, this.element); 
     303    } 
     304     
     305    if(this.options.scroll) { 
     306      if (this.options.scroll == window) { 
     307        var where = this._getWindowScroll(this.options.scroll); 
     308        this.originalScrollLeft = where.left; 
     309        this.originalScrollTop = where.top; 
     310      } else { 
     311        this.originalScrollLeft = this.options.scroll.scrollLeft; 
     312        this.originalScrollTop = this.options.scroll.scrollTop; 
     313      } 
    271314    } 
    272315     
     
    283326    if(this.options.change) this.options.change(this); 
    284327     
     328    if(this.options.scroll) { 
     329      this.stopScrolling(); 
     330       
     331      var p; 
     332      if (this.options.scroll == window) { 
     333        with(this._getWindowScroll(this.options.scroll)) { p = [ left, top, left+width, top+height ]; } 
     334      } else { 
     335        p = Position.page(this.options.scroll); 
     336        p[0] += this.options.scroll.scrollLeft; 
     337        p[1] += this.options.scroll.scrollTop; 
     338        p.push(p[0]+this.options.scroll.offsetWidth); 
     339        p.push(p[1]+this.options.scroll.offsetHeight); 
     340      } 
     341      var speed = [0,0]; 
     342      if(pointer[0] < (p[0]+this.options.scrollSensitivity)) speed[0] = pointer[0]-(p[0]+this.options.scrollSensitivity); 
     343      if(pointer[1] < (p[1]+this.options.scrollSensitivity)) speed[1] = pointer[1]-(p[1]+this.options.scrollSensitivity); 
     344      if(pointer[0] > (p[2]-this.options.scrollSensitivity)) speed[0] = pointer[0]-(p[2]-this.options.scrollSensitivity); 
     345      if(pointer[1] > (p[3]-this.options.scrollSensitivity)) speed[1] = pointer[1]-(p[3]-this.options.scrollSensitivity); 
     346      this.startScrolling(speed); 
     347    } 
     348     
    285349    // fix AppleWebKit rendering 
    286350    if(navigator.appVersion.indexOf('AppleWebKit')>0) window.scrollBy(0,0); 
     351     
    287352    Event.stop(event); 
    288353  }, 
     
    322387   
    323388  keyPress: function(event) { 
    324     if(!event.keyCode==Event.KEY_ESC) return; 
     389    if(event.keyCode!=Event.KEY_ESC) return; 
    325390    this.finishDrag(event, false); 
    326391    Event.stop(event); 
     
    329394  endDrag: function(event) { 
    330395    if(!this.dragging) return; 
     396    this.stopScrolling(); 
    331397    this.finishDrag(event, true); 
    332398    Event.stop(event); 
     
    338404    pos[0] -= d[0]; pos[1] -= d[1]; 
    339405     
    340     var p = [0,1].map(function(i){ return (point[i]-pos[i]-this.offset[i]) }.bind(this)); 
     406    if(this.options.scroll && (this.options.scroll != window)) { 
     407      pos[0] -= this.options.scroll.scrollLeft-this.originalScrollLeft; 
     408      pos[1] -= this.options.scroll.scrollTop-this.originalScrollTop; 
     409    } 
     410     
     411    var p = [0,1].map(function(i){  
     412      return (point[i]-pos[i]-this.offset[i])  
     413    }.bind(this)); 
    341414     
    342415    if(this.options.snap) { 
    343416      if(typeof this.options.snap == 'function') { 
    344         p = this.options.snap(p[0],p[1]); 
     417        p = this.options.snap(p[0],p[1],this); 
    345418      } else { 
    346419      if(this.options.snap instanceof Array) { 
     
    359432      style.top  = p[1] + "px"; 
    360433    if(style.visibility=="hidden") style.visibility = ""; // fix gecko rendering 
     434  }, 
     435   
     436  stopScrolling: function() { 
     437    if(this.scrollInterval) { 
     438      clearInterval(this.scrollInterval); 
     439      this.scrollInterval = null; 
     440      Draggables._lastScrollPointer = null; 
     441    } 
     442  }, 
     443   
     444  startScrolling: function(speed) { 
     445    this.scrollSpeed = [speed[0]*this.options.scrollSpeed,speed[1]*this.options.scrollSpeed]; 
     446    this.lastScrolled = new Date(); 
     447    this.scrollInterval = setInterval(this.scroll.bind(this), 10); 
     448  }, 
     449   
     450  scroll: function() { 
     451    var current = new Date(); 
     452    var delta = current - this.lastScrolled; 
     453    this.lastScrolled = current; 
     454    if(this.options.scroll == window) { 
     455      with (this._getWindowScroll(this.options.scroll)) { 
     456        if (this.scrollSpeed[0] || this.scrollSpeed[1]) { 
     457          var d = delta / 1000; 
     458          this.options.scroll.scrollTo( left + d*this.scrollSpeed[0], top + d*this.scrollSpeed[1] ); 
     459        } 
     460      } 
     461    } else { 
     462      this.options.scroll.scrollLeft += this.scrollSpeed[0] * delta / 1000; 
     463      this.options.scroll.scrollTop  += this.scrollSpeed[1] * delta / 1000; 
     464    } 
     465     
     466    Position.prepare(); 
     467    Droppables.show(Draggables._lastPointer, this.element); 
     468    Draggables.notify('onDrag', this); 
     469    Draggables._lastScrollPointer = Draggables._lastScrollPointer || $A(Draggables._lastPointer); 
     470    Draggables._lastScrollPointer[0] += this.scrollSpeed[0] * delta / 1000; 
     471    Draggables._lastScrollPointer[1] += this.scrollSpeed[1] * delta / 1000; 
     472    if (Draggables._lastScrollPointer[0] < 0) 
     473      Draggables._lastScrollPointer[0] = 0; 
     474    if (Draggables._lastScrollPointer[1] < 0) 
     475      Draggables._lastScrollPointer[1] = 0; 
     476    this.draw(Draggables._lastScrollPointer); 
     477     
     478    if(this.options.change) this.options.change(this); 
     479  }, 
     480   
     481  _getWindowScroll: function(w) { 
     482    var T, L, W, H; 
     483    with (w.document) { 
     484      if (w.document.documentElement && documentElement.scrollTop) { 
     485        T = documentElement.scrollTop; 
     486        L = documentElement.scrollLeft; 
     487      } else if (w.document.body) { 
     488        T = body.scrollTop; 
     489        L = body.scrollLeft; 
     490      } 
     491      if (w.innerWidth) { 
     492        W = w.innerWidth; 
     493        H = w.innerHeight; 
     494      } else if (w.document.documentElement && documentElement.clientWidth) { 
     495        W = documentElement.clientWidth; 
     496        H = documentElement.clientHeight; 
     497      } else { 
     498        W = body.offsetWidth; 
     499        H = body.offsetHeight 
     500      } 
     501    } 
     502    return { top: T, left: L, width: W, height: H }; 
    361503  } 
    362504} 
     
    384526 
    385527var Sortable = { 
    386   sortables: new Array(), 
    387    
    388   options: function(element){ 
    389     element = $(element); 
    390     return this.sortables.detect(function(s) { return s.element == element }); 
     528  sortables: {}, 
     529   
     530  _findRootElement: function(element) { 
     531    while (element.tagName != "BODY") {   
     532      if(element.id && Sortable.sortables[element.id]) return element; 
     533      element = element.parentNode; 
     534    } 
     535  }, 
     536 
     537  options: function(element) { 
     538    element = Sortable._findRootElement($(element)); 
     539    if(!element) return; 
     540    return Sortable.sortables[element.id]; 
    391541  }, 
    392542   
    393543  destroy: function(element){ 
    394     element = $(element); 
    395     this.sortables.findAll(function(s) { return s.element == element }).each(function(s){ 
     544    var s = Sortable.options(element); 
     545     
     546    if(s) { 
    396547      Draggables.removeObserver(s.element); 
    397548      s.droppables.each(function(d){ Droppables.remove(d) }); 
    398549      s.draggables.invoke('destroy'); 
    399     }); 
    400     this.sortables = this.sortables.reject(function(s) { return s.element == element }); 
    401   }, 
    402    
     550       
     551      delete Sortable.sortables[s.element.id]; 
     552    } 
     553  }, 
     554 
    403555  create: function(element) { 
    404556    element = $(element); 
     
    407559      tag:         'li',       // assumes li children, override with tag: 'tagname' 
    408560      dropOnEmpty: false, 
    409       tree:        false,      // fixme: unimplemented 
     561      tree:        false, 
     562      treeTag:     'ul', 
    410563      overlap:     'vertical', // one of 'vertical', 'horizontal' 
    411564      constraint:  'vertical', // one of 'vertical', 'horizontal', false 
     
    415568      hoverclass:  null, 
    416569      ghosting:    false, 
    417       format:      null, 
     570      scroll:      false, 
     571      scrollSensitivity: 20, 
     572      scrollSpeed: 15, 
     573      format:      /^[^_]*_(.*)$/, 
    418574      onChange:    Prototype.emptyFunction, 
    419575      onUpdate:    Prototype.emptyFunction 
     
    426582    var options_for_draggable = { 
    427583      revert:      true, 
     584      scroll:      options.scroll, 
     585      scrollSpeed: options.scrollSpeed, 
     586      scrollSensitivity: options.scrollSensitivity, 
    428587      ghosting:    options.ghosting, 
    429588      constraint:  options.constraint, 
     
    451610      overlap:     options.overlap, 
    452611      containment: options.containment, 
     612      tree:        options.tree, 
    453613      hoverclass:  options.hoverclass, 
    454       onHover:     Sortable.onHover, 
    455       greedy:      !options.dropOnEmpty 
     614      onHover:     Sortable.onHover 
     615      //greedy:      !options.dropOnEmpty 
     616    } 
     617     
     618    var options_for_tree = { 
     619      onHover:      Sortable.onEmptyHover, 
     620      overlap:      options.overlap, 
     621      containment:  options.containment, 
     622      hoverclass:   options.hoverclass 
    456623    } 
    457624 
     
    462629    options.droppables = []; 
    463630 
    464     // make it so 
    465  
    466631    // drop on empty handling 
    467     if(options.dropOnEmpty) { 
    468       Droppables.add(element, 
    469         {containment: options.containment, onHover: Sortable.onEmptyHover, greedy: false}); 
     632    if(options.dropOnEmpty || options.tree) { 
     633      Droppables.add(element, options_for_tree); 
    470634      options.droppables.push(element); 
    471635    } 
     
    478642        new Draggable(e, Object.extend(options_for_draggable, { handle: handle }))); 
    479643      Droppables.add(e, options_for_droppable); 
     644      if(options.tree) e.treeNode = element; 
    480645      options.droppables.push(e);       
    481646    }); 
     647     
     648    if(options.tree) { 
     649      (Sortable.findTreeElements(element, options) || []).each( function(e) { 
     650        Droppables.add(e, options_for_tree); 
     651        e.treeNode = element; 
     652        options.droppables.push(e); 
     653      }); 
     654    } 
    482655 
    483656    // keep reference 
    484     this.sortables.push(options); 
     657    this.sortables[element.id] = options; 
    485658 
    486659    // for onupdate 
     
    491664  // return all suitable-for-sortable elements in a guaranteed order 
    492665  findElements: function(element, options) { 
    493     if(!element.hasChildNodes()) return null; 
    494     var elements = []; 
    495     $A(element.childNodes).each( function(e) { 
    496       if(e.tagName && e.tagName.toUpperCase()==options.tag.toUpperCase() && 
    497         (!options.only || (Element.hasClassName(e, options.only)))) 
    498           elements.push(e); 
    499       if(options.tree) { 
    500         var grandchildren = this.findElements(e, options); 
    501         if(grandchildren) elements.push(grandchildren); 
    502       } 
    503     }); 
    504  
    505     return (elements.length>0 ? elements.flatten() : null); 
     666    return Element.findChildren( 
     667      element, options.only, options.tree ? true : false, options.tag); 
     668  }, 
     669   
     670  findTreeElements: function(element, options) { 
     671    return Element.findChildren( 
     672      element, options.only, options.tree ? true : false, options.treeTag); 
    506673  }, 
    507674 
    508675  onHover: function(element, dropon, overlap) { 
    509     if(overlap>0.5) { 
     676    if(Element.isParent(dropon, element)) return; 
     677 
     678    if(overlap > .33 && overlap < .66 && Sortable.options(dropon).tree) { 
     679      return; 
     680    } else if(overlap>0.5) { 
    510681      Sortable.mark(dropon, 'before'); 
    511682      if(dropon.previousSibling != element) { 
     
    530701    } 
    531702  }, 
    532  
    533   onEmptyHover: function(element, dropon) { 
    534     if(element.parentNode!=dropon) { 
    535       var oldParentNode = element.parentNode; 
    536       dropon.appendChild(element); 
     703   
     704  onEmptyHover: function(element, dropon, overlap) { 
     705    var oldParentNode = element.parentNode; 
     706    var droponOptions = Sortable.options(dropon); 
     707         
     708    if(!Element.isParent(dropon, element)) { 
     709      var index; 
     710       
     711      var children = Sortable.findElements(dropon, {tag: droponOptions.tag}); 
     712      var child = null; 
     713             
     714      if(children) { 
     715        var offset = Element.offsetSize(dropon, droponOptions.overlap) * (1.0 - overlap); 
     716         
     717        for (index = 0; index < children.length; index += 1) { 
     718          if (offset - Element.offsetSize (children[index], droponOptions.overlap) >= 0) { 
     719            offset -= Element.offsetSize (children[index], droponOptions.overlap); 
     720          } else if (offset - (Element.offsetSize (children[index], droponOptions.overlap) / 2) >= 0) { 
     721            child = index + 1 < children.length ? children[index + 1] : null; 
     722            break; 
     723          } else { 
     724            child = children[index]; 
     725            break; 
     726          } 
     727        } 
     728      } 
     729       
     730      dropon.insertBefore(element, child); 
     731       
    537732      Sortable.options(oldParentNode).onChange(element); 
    538       Sortable.options(dropon).onChange(element); 
     733      droponOptions.onChange(element); 
    539734    } 
    540735  }, 
     
    568763    Element.show(Sortable._marker); 
    569764  }, 
    570  
    571   serialize: function(element) { 
     765   
     766  _tree: function(element, options, parent) { 
     767    var children = Sortable.findElements(element, options) || []; 
     768   
     769    for (var i = 0; i < children.length; ++i) { 
     770      var match = children[i].id.match(options.format); 
     771 
     772      if (!match) continue; 
     773       
     774      var child = { 
     775        id: encodeURIComponent(match ? match[1] : null), 
     776        element: element, 
     777        parent: parent, 
     778        children: new Array, 
     779        position: parent.children.length, 
     780        container: Sortable._findChildrenElement(children[i], options.treeTag.toUpperCase()) 
     781      } 
     782       
     783      /* Get the element containing the children and recurse over it */ 
     784      if (child.container) 
     785        this._tree(child.container, options, child) 
     786       
     787      parent.children.push (child); 
     788    } 
     789 
     790    return parent;  
     791  }, 
     792 
     793  /* Finds the first element of the given tag type within a parent element. 
     794    Used for finding the first LI[ST] within a L[IST]I[TEM].*/ 
     795  _findChildrenElement: function (element, containerTag) { 
     796    if (element && element.hasChildNodes) 
     797      for (var i = 0; i < element.childNodes.length; ++i) 
     798        if (element.childNodes[i].tagName == containerTag) 
     799          return element.childNodes[i]; 
     800   
     801    return null; 
     802  }, 
     803 
     804  tree: function(element) { 
    572805    element = $(element); 
    573806    var sortableOptions = this.options(element); 
    574807    var options = Object.extend({ 
    575       tag:  sortableOptions.tag, 
     808      tag: sortableOptions.tag, 
     809      treeTag: sortableOptions.treeTag, 
    576810      only: sortableOptions.only, 
    577811      name: element.id, 
    578       format: sortableOptions.format || /^[^_]*_(.*)$/ 
     812      format: sortableOptions.format 
    579813    }, arguments[1] || {}); 
     814     
     815    var root = { 
     816      id: null, 
     817      parent: null, 
     818      children: new Array, 
     819      container: element, 
     820      position: 0 
     821    } 
     822     
     823    return Sortable._tree (element, options, root); 
     824  }, 
     825 
     826  /* Construct a [i] index for a particular node */ 
     827  _constructIndex: function(node) { 
     828    var index = ''; 
     829    do { 
     830      if (node.id) index = '[' + node.position + ']' + index; 
     831    } while ((node = node.parent) != null); 
     832    return index; 
     833  }, 
     834 
     835  sequence: function(element) { 
     836    element = $(element); 
     837    var options = Object.extend(this.options(element), arguments[1] || {}); 
     838     
    580839    return $(this.findElements(element, options) || []).map( function(item) { 
    581       return (encodeURIComponent(options.name) + "[]=" +  
    582               encodeURIComponent(item.id.match(options.format) ? item.id.match(options.format)[1] : '')); 
    583     }).join("&"); 
     840      return item.id.match(options.format) ? item.id.match(options.format)[1] : ''; 
     841    }); 
     842  }, 
     843 
     844  setSequence: function(element, new_sequence) { 
     845    element = $(element); 
     846    var options = Object.extend(this.options(element), arguments[2] || {}); 
     847     
     848    var nodeMap = {}; 
     849    this.findElements(element, options).each( function(n) { 
     850        if (n.id.match(options.format)) 
     851            nodeMap[n.id.match(options.format)[1]] = [n, n.parentNode]; 
     852        n.parentNode.removeChild(n); 
     853    }); 
     854    
     855    new_sequence.each(function(ident) { 
     856      var n = nodeMap[ident]; 
     857      if (n) { 
     858        n[1].appendChild(n[0]); 
     859        delete nodeMap[ident]; 
     860      } 
     861    }); 
     862  }, 
     863   
     864  serialize: function(element) { 
     865    element = $(element); 
     866    var options = Object.extend(Sortable.options(element), arguments[1] || {}); 
     867    var name = encodeURIComponent( 
     868      (arguments[1] && arguments[1].name) ? arguments[1].name : element.id); 
     869     
     870    if (options.tree) { 
     871      return Sortable.tree(element, arguments[1]).children.map( function (item) { 
     872        return [name + Sortable._constructIndex(item) + "=" +  
     873                encodeURIComponent(item.id)].concat(item.children.map(arguments.callee)); 
     874      }).flatten().join('&'); 
     875    } else { 
     876      return Sortable.sequence(element, arguments[1]).map( function(item) { 
     877        return name + "[]=" + encodeURIComponent(item); 
     878      }).join('&'); 
     879    } 
    584880  } 
    585881} 
     882 
     883/* Returns true if child is contained within element */ 
     884Element.isParent = function(child, element) { 
     885  if (!child.parentNode || child == element) return false; 
     886 
     887  if (child.parentNode == element) return true; 
     888 
     889  return Element.isParent(child.parentNode, element); 
     890} 
     891 
     892Element.findChildren = function(element, only, recursive, tagName) {     
     893  if(!element.hasChildNodes()) return null; 
     894  tagName = tagName.toUpperCase(); 
     895  if(only) only = [only].flatten(); 
     896  var elements = []; 
     897  $A(element.childNodes).each( function(e) { 
     898    if(e.tagName && e.tagName.toUpperCase()==tagName && 
     899      (!only || (Element.classNames(e).detect(function(v) { return only.include(v) })))) 
     900        elements.push(e); 
     901    if(recursive) { 
     902      var grandchildren = Element.findChildren(e, only, recursive, tagName); 
     903      if(grandchildren) elements.push(grandchildren); 
     904    } 
     905  }); 
     906 
     907  return (elements.length>0 ? elements.flatten() : []); 
     908} 
     909 
     910Element.offsetSize = function (element, type) { 
     911  if (type == 'vertical' || type == 'height') 
     912    return element.offsetHeight; 
     913  else 
     914    return element.offsetWidth; 
     915} 
  • trunk/trax/vendor/trax/action_view/helpers/javascripts/effects.js

    r148 r226  
    44//  Mark Pilgrim (http://diveintomark.org/) 
    55//  Martin Bialasinki 
    6 //  
     6//   
    77// See scriptaculous.js for full license.   
    88 
    9 /* ------------- element ext -------------- */   
    10   
    119// converts rgb() and #xxx to #xxxxxx format,   
    1210// returns self (or first argument) if not convertable   
     
    2523} 
    2624 
     25/*--------------------------------------------------------------------------*/ 
     26 
    2727Element.collectTextNodes = function(element) {   
    2828  return $A($(element).childNodes).collect( function(node) { 
     
    3636    return (node.nodeType==3 ? node.nodeValue :  
    3737      ((node.hasChildNodes() && !Element.hasClassName(node,className)) ?  
    38         Element.collectTextNodes(node) : '')); 
     38        Element.collectTextNodesIgnoreClass(node, className) : '')); 
    3939  }).flatten().join(''); 
    4040} 
    4141 
    42 Element.setStyle = function(element, style) { 
    43   element = $(element); 
    44   for(k in style) element.style[k.camelize()] = style[k]; 
    45 } 
    46  
    47 Element.setContentZoom = function(element, percent) {   
     42Element.setContentZoom = function(element, percent) { 
     43  element = $(element);   
    4844  Element.setStyle(element, {fontSize: (percent/100) + 'em'});    
    49   if(navigator.appVersion.indexOf('AppleWebKit')>0) window.scrollBy(0,0);   
     45  if(navigator.appVersion.indexOf('AppleWebKit')>0) window.scrollBy(0,0); 
    5046} 
    5147 
     
    7470       { filter: Element.getStyle(element,'filter').replace(/alpha\([^\)]*\)/gi,'') + 
    7571                 'alpha(opacity='+value*100+')' });   
    76   }    
     72  } 
    7773 
    7874  
     
    8177 
    8278 
    83 Element.childrenWithClassName = function(element, className) {   
    84   return $A($(element).getElementsByTagName('*')).select( 
    85     function(c) { return Element.hasClassName(c, className) }); 
    86 } 
     79Element.childrenWithClassName = function(element, className, findFirst) { 
     80  var classNameRegExp = new RegExp("(^|\\s)" + className + "(\\s|$)"); 
     81  var results = $A($(element).getElementsByTagName('*'))[findFirst ? 'detect' : 'select']( function(c) {  
     82    return (c.className && c.className.match(classNameRegExp)); 
     83  }); 
     84  if(!results) results = []; 
     85  return results; 
     86} 
     87 
     88Element.forceRerendering = function(element) { 
     89  try { 
     90    element = $(element); 
     91    var n = document.createTextNode(' '); 
     92    element.appendChild(n); 
     93    element.removeChild(n); 
     94  } catch(e) { } 
     95}; 
     96 
     97/*--------------------------------------------------------------------------*/ 
    8798 
    8899Array.prototype.call = function() { 
     
    138149    effect = (effect || 'appear').toLowerCase(); 
    139150    var options = Object.extend({ 
    140       queue: { position:'end', scope:(element.id || 'global') } 
     151      queue: { position:'end', scope:(element.id || 'global'), limit: 1 } 
    141152    }, arguments[2] || {}); 
    142     Effect[Element.visible(element) ?  
     153    Effect[element.visible() ?  
    143154      Effect.PAIRS[effect][1] : Effect.PAIRS[effect][0]](element, options); 
    144155  } 
     
    210221    effect.startOn  += timestamp; 
    211222    effect.finishOn += timestamp; 
    212     this.effects.push(effect); 
     223 
     224    if(!effect.options.queue.limit || (this.effects.length < effect.options.queue.limit)) 
     225      this.effects.push(effect); 
     226     
    213227    if(!this.interval)  
    214228      this.interval = setInterval(this.loop.bind(this), 40); 
     
    341355    // make this work on IE on elements without 'layout' 
    342356    if(/MSIE/.test(navigator.userAgent) && (!this.element.hasLayout)) 
    343       Element.setStyle(this.element, {zoom: 1}); 
     357      this.element.setStyle({zoom: 1}); 
    344358    var options = Object.extend({ 
    345       from: Element.getOpacity(this.element) || 0.0, 
     359      from: this.element.getOpacity() || 0.0, 
    346360      to:   1.0 
    347361    }, arguments[1] || {}); 
     
    349363  }, 
    350364  update: function(position) { 
    351     Element.setOpacity(this.element, position); 
     365    this.element.setOpacity(position); 
    352366  } 
    353367}); 
     
    369383    // ==> Always set top and left for position relative elements in your stylesheets  
    370384    // (to 0 if you do not need them)  
    371     Element.makePositioned(this.element); 
    372     this.originalLeft = parseFloat(Element.getStyle(this.element,'left') || '0'); 
    373     this.originalTop  = parseFloat(Element.getStyle(this.element,'top')  || '0'); 
     385    this.element.makePositioned(); 
     386    this.originalLeft = parseFloat(this.element.getStyle('left') || '0'); 
     387    this.originalTop  = parseFloat(this.element.getStyle('top')  || '0'); 
    374388    if(this.options.mode == 'absolute') { 
    375389      // absolute movement, so we need to calc deltaX and deltaY 
     
    379393  }, 
    380394  update: function(position) { 
    381     Element.setStyle(this.element, { 
     395    this.element.setStyle({ 
    382396      left: this.options.x  * position + this.originalLeft + 'px', 
    383397      top:  this.options.y  * position + this.originalTop  + 'px' 
     
    409423  setup: function() { 
    410424    this.restoreAfterFinish = this.options.restoreAfterFinish || false; 
    411     this.elementPositioning = Element.getStyle(this.element,'position'); 
     425    this.elementPositioning = this.element.getStyle('position'); 
    412426     
    413427    this.originalStyle = {}; 
     
    419433    this.originalLeft = this.element.offsetLeft; 
    420434     
    421     var fontSize = Element.getStyle(this.element,'font-size') || '100%'; 
     435    var fontSize = this.element.getStyle('font-size') || '100%'; 
    422436    ['em','px','%'].each( function(fontSizeType) { 
    423437      if(fontSize.indexOf(fontSizeType)>0) { 
     
    441455    var currentScale = (this.options.scaleFrom/100.0) + (this.factor * position); 
    442456    if(this.options.scaleContent && this.fontSize) 
    443       Element.setStyle(this.element, {fontSize: this.fontSize * currentScale + this.fontSizeType }); 
     457      this.element.setStyle({fontSize: this.fontSize * currentScale + this.fontSizeType }); 
    444458    this.setDimensions(this.dims[0] * currentScale, this.dims[1] * currentScale); 
    445459  }, 
    446460  finish: function(position) { 
    447     if (this.restoreAfterFinish) Element.setStyle(this.element, this.originalStyle); 
     461    if (this.restoreAfterFinish) this.element.setStyle(this.originalStyle); 
    448462  }, 
    449463  setDimensions: function(height, width) { 
     
    462476      } 
    463477    } 
    464     Element.setStyle(this.element, d); 
     478    this.element.setStyle(d); 
    465479  } 
    466480}); 
     
    475489  setup: function() { 
    476490    // Prevent executing on elements not in the layout flow 
    477     if(Element.getStyle(this.element, 'display')=='none') { this.cancel(); return; } 
     491    if(this.element.getStyle('display')=='none') { this.cancel(); return; } 
    478492    // Disable background image during the effect 
    479493    this.oldStyle = { 
    480       backgroundImage: Element.getStyle(this.element, 'background-image') }; 
    481     Element.setStyle(this.element, {backgroundImage: 'none'}); 
     494      backgroundImage: this.element.getStyle('background-image') }; 
     495    this.element.setStyle({backgroundImage: 'none'}); 
    482496    if(!this.options.endcolor) 
    483       this.options.endcolor = Element.getStyle(this.element, 'background-color').parseColor('#ffffff'); 
     497      this.options.endcolor = this.element.getStyle('background-color').parseColor('#ffffff'); 
    484498    if(!this.options.restorecolor) 
    485       this.options.restorecolor = Element.getStyle(this.element, 'background-color'); 
     499      this.options.restorecolor = this.element.getStyle('background-color'); 
    486500    // init color calculations 
    487501    this._base  = $R(0,2).map(function(i){ return parseInt(this.options.startcolor.slice(i*2+1,i*2+3),16) }.bind(this)); 
     
    489503  }, 
    490504  update: function(position) { 
    491     Element.setStyle(this.element,{backgroundColor: $R(0,2).inject('#',function(m,v,i){ 
     505    this.element.setStyle({backgroundColor: $R(0,2).inject('#',function(m,v,i){ 
    492506      return m+(Math.round(this._base[i]+(this._delta[i]*position)).toColorPart()); }.bind(this)) }); 
    493507  }, 
    494508  finish: function() { 
    495     Element.setStyle(this.element, Object.extend(this.oldStyle, { 
     509    this.element.setStyle(Object.extend(this.oldStyle, { 
    496510      backgroundColor: this.options.restorecolor 
    497511    })); 
     
    527541 
    528542Effect.Fade = function(element) { 
    529   var oldOpacity = Element.getInlineOpacity(element); 
     543  element = $(element); 
     544  var oldOpacity = element.getInlineOpacity(); 
    530545  var options = Object.extend({ 
    531   from: Element.getOpacity(element) || 1.0, 
     546  from: element.getOpacity() || 1.0, 
    532547  to:   0.0, 
    533   afterFinishInternal: function(effect) { with(Element) {  
     548  afterFinishInternal: function(effect) {  
    534549    if(effect.options.to!=0) return; 
    535     hide(effect.element); 
    536     setStyle(effect.element, {opacity: oldOpacity}); }} 
    537   }, arguments[1] || {}); 
     550    effect.element.hide(); 
     551    effect.element.setStyle({opacity: oldOpacity});  
     552  }}, arguments[1] || {}); 
    538553  return new Effect.Opacity(element,options); 
    539554} 
    540555 
    541556Effect.Appear = function(element) { 
     557  element = $(element); 
    542558  var options = Object.extend({ 
    543   from: (Element.getStyle(element, 'display') == 'none' ? 0.0 : Element.getOpacity(element) || 0.0), 
     559  from: (element.getStyle('display') == 'none' ? 0.0 : element.getOpacity() || 0.0), 
    544560  to:   1.0, 
    545   beforeSetup: function(effect) { with(Element) { 
    546     setOpacity(effect.element, effect.options.from); 
    547     show(effect.element); }} 
    548   }, arguments[1] || {}); 
     561  // force Safari to render floated elements properly 
     562  afterFinishInternal: function(effect) { 
     563    effect.element.forceRerendering(); 
     564  }, 
     565  beforeSetup: function(effect) { 
     566    effect.element.setOpacity(effect.options.from); 
     567    effect.element.show();  
     568  }}, arguments[1] || {}); 
    549569  return new Effect.Opacity(element,options); 
    550570} 
     
    552572Effect.Puff = function(element) { 
    553573  element = $(element); 
    554   var oldStyle = { opacity: Element.getInlineOpacity(element), position: Element.getStyle(element, 'position') }; 
     574  var oldStyle = { opacity: element.getInlineOpacity(), position: element.getStyle('position') }; 
    555575  return new Effect.Parallel( 
    556576   [ new Effect.Scale(element, 200,  
     
    558578     new Effect.Opacity(element, { sync: true, to: 0.0 } ) ],  
    559579     Object.extend({ duration: 1.0,  
    560       beforeSetupInternal: function(effect) { with(Element) { 
    561         setStyle(effect.effects[0].element, {position: 'absolute'}); }}, 
    562       afterFinishInternal: function(effect) { with(Element) { 
    563          hide(effect.effects[0].element); 
    564          setStyle(effect.effects[0].element, oldStyle); }} 
     580      beforeSetupInternal: function(effect) { 
     581        effect.effects[0].element.setStyle({position: 'absolute'}); }, 
     582      afterFinishInternal: function(effect) { 
     583         effect.effects[0].element.hide(); 
     584         effect.effects[0].element.setStyle(oldStyle); } 
    565585     }, arguments[1] || {}) 
    566586   ); 
     
    569589Effect.BlindUp = function(element) { 
    570590  element = $(element); 
    571   Element.makeClipping(element); 
     591  element.makeClipping(); 
    572592  return new Effect.Scale(element, 0,  
    573593    Object.extend({ scaleContent: false,  
    574594      scaleX: false,  
    575595      restoreAfterFinish: true, 
    576       afterFinishInternal: function(effect) { with(Element) { 
    577         [hide, undoClipping].call(effect.element); }}  
     596      afterFinishInternal: function(effect) { 
     597        effect.element.hide(); 
     598        effect.element.undoClipping(); 
     599      }  
    578600    }, arguments[1] || {}) 
    579601  ); 
     
    582604Effect.BlindDown = function(element) { 
    583605  element = $(element); 
    584   var oldHeight = Element.getStyle(element, 'height'); 
    585   var elementDimensions = Element.getDimensions(element); 
     606  var elementDimensions = element.getDimensions(); 
    586607  return new Effect.Scale(element, 100,  
    587608    Object.extend({ scaleContent: false,  
     
    590611      scaleMode: {originalHeight: elementDimensions.height, originalWidth: elementDimensions.width}, 
    591612      restoreAfterFinish: true, 
    592       afterSetup: function(effect) { with(Element) { 
    593         makeClipping(effect.element); 
    594         setStyle(effect.element, {height: '0px'}); 
    595         show(effect.element);  
    596       }},   
    597       afterFinishInternal: function(effect) { with(Element) { 
    598         undoClipping(effect.element); 
    599         setStyle(effect.element, {height: oldHeight}); 
    600       }} 
     613      afterSetup: function(effect) { 
     614        effect.element.makeClipping(); 
     615        effect.element.setStyle({height: '0px'}); 
     616        effect.element.show();  
     617      },   
     618      afterFinishInternal: function(effect) { 
     619        effect.element.undoClipping(); 
     620      } 
    601621    }, arguments[1] || {}) 
    602622  ); 
     
    605625Effect.SwitchOff = function(element) { 
    606626  element = $(element); 
    607   var oldOpacity = Element.getInlineOpacity(element); 
     627  var oldOpacity = element.getInlineOpacity(); 
    608628  return new Effect.Appear(element, {  
    609629    duration: 0.4, 
     
    614634        duration: 0.3, scaleFromCenter: true, 
    615635        scaleX: false, scaleContent: false, restoreAfterFinish: true, 
    616         beforeSetup: function(effect) { with(Element) { 
    617           [makePositioned,makeClipping].call(effect.element); 
    618         }}, 
    619         afterFinishInternal: function(effect) { with(Element) { 
    620           [hide,undoClipping,undoPositioned].call(effect.element); 
    621           setStyle(effect.element, {opacity: oldOpacity}); 
    622         }} 
     636        beforeSetup: function(effect) {  
     637          effect.element.makePositioned(); 
     638          effect.element.makeClipping(); 
     639        }, 
     640        afterFinishInternal: function(effect) { 
     641          effect.element.hide(); 
     642          effect.element.undoClipping(); 
     643          effect.element.undoPositioned(); 
     644          effect.element.setStyle({opacity: oldOpacity}); 
     645        } 
    623646      }) 
    624647    } 
     
    629652  element = $(element); 
    630653  var oldStyle = { 
    631     top: Element.getStyle(element, 'top'), 
    632     left: Element.getStyle(element, 'left'), 
    633     opacity: Element.getInlineOpacity(element) }; 
     654    top: element.getStyle('top'), 
     655    left: element.getStyle('left'), 
     656    opacity: element.getInlineOpacity() }; 
    634657  return new Effect.Parallel( 
    635658    [ new Effect.Move(element, {x: 0, y: 100, sync: true }),  
     
    637660    Object.extend( 
    638661      { duration: 0.5, 
    639         beforeSetup: function(effect) { with(Element) { 
    640           makePositioned(effect.effects[0].element); }}, 
    641         afterFinishInternal: function(effect) { with(Element) { 
    642           [hide, undoPositioned].call(effect.effects[0].element); 
    643           setStyle(effect.effects[0].element, oldStyle); }}  
     662        beforeSetup: function(effect) { 
     663          effect.effects[0].element.makePositioned();  
     664        }, 
     665        afterFinishInternal: function(effect) { 
     666          effect.effects[0].element.hide(); 
     667          effect.effects[0].element.undoPositioned(); 
     668          effect.effects[0].element.setStyle(oldStyle); 
     669        }  
    644670      }, arguments[1] || {})); 
    645671} 
     
    648674  element = $(element); 
    649675  var oldStyle = { 
    650     top: Element.getStyle(element, 'top'), 
    651     left: Element.getStyle(element, 'left') }; 
    652       return new Effect.Move(element,  
    653         { x:  20, y: 0, duration: 0.05, afterFinishInternal: function(effect) { 
    654       new Effect.Move(effect.element, 
    655         { x: -40, y: 0, duration: 0.1,  afterFinishInternal: function(effect) { 
    656       new Effect.Move(effect.element, 
    657         { x:  40, y: 0, duration: 0.1,  afterFinishInternal: function(effect) { 
    658       new Effect.Move(effect.element, 
    659         { x: -40, y: 0, duration: 0.1,  afterFinishInternal: function(effect) { 
    660       new Effect.Move(effect.element, 
    661         { x:  40, y: 0, duration: 0.1,  afterFinishInternal: function(effect) { 
    662       new Effect.Move(effect.element, 
    663         { x: -20, y: 0, duration: 0.05, afterFinishInternal: function(effect) { with(Element) { 
    664         undoPositioned(effect.element); 
    665         setStyle(effect.element, oldStyle); 
    666   }}}) }}) }}) }}) }}) }}); 
     676    top: element.getStyle('top'), 
     677    left: element.getStyle('left') }; 
     678    return new Effect.Move(element,  
     679      { x:  20, y: 0, duration: 0.05, afterFinishInternal: function(effect) { 
     680    new Effect.Move(effect.element, 
     681      { x: -40, y: 0, duration: 0.1,  afterFinishInternal: function(effect) { 
     682    new Effect.Move(effect.element, 
     683      { x:  40, y: 0, duration: 0.1,  afterFinishInternal: function(effect) { 
     684    new Effect.Move(effect.element, 
     685      { x: -40, y: 0, duration: 0.1,  afterFinishInternal: function(effect) { 
     686    new Effect.Move(effect.element, 
     687      { x:  40, y: 0, duration: 0.1,  afterFinishInternal: function(effect) { 
     688    new Effect.Move(effect.element, 
     689      { x: -20, y: 0, duration: 0.05, afterFinishInternal: function(effect) { 
     690        effect.element.undoPositioned(); 
     691        effect.element.setStyle(oldStyle); 
     692  }}) }}) }}) }}) }}) }}); 
    667693} 
    668694 
    669695Effect.SlideDown = function(element) { 
    670696  element = $(element); 
    671   Element.cleanWhitespace(element); 
     697  element.cleanWhitespace(); 
    672698  // SlideDown need to have the content of the element wrapped in a container element with fixed height! 
    673   var oldInnerBottom = Element.getStyle(element.firstChild, 'bottom'); 
    674   var elementDimensions = Element.getDimensions(element); 
     699  var oldInnerBottom = $(element.firstChild).getStyle('bottom'); 
     700  var elementDimensions = element.getDimensions(); 
    675701  return new Effect.Scale(element, 100, Object.extend({  
    676702    scaleContent: false,  
    677703    scaleX: false,  
    678     scaleFrom: 0, 
     704    scaleFrom: window.opera ? 0 : 1, 
    679705    scaleMode: {originalHeight: elementDimensions.height, originalWidth: elementDimensions.width}, 
    680706    restoreAfterFinish: true, 
    681     afterSetup: function(effect) { with(Element) { 
    682       makePositioned(effect.element); 
    683       makePositioned(effect.element.firstChild); 
    684       if(window.opera) setStyle(effect.element, {top: ''}); 
    685       makeClipping(effect.element); 
    686       setStyle(effect.element, {height: '0px'}); 
    687       show(element); }}, 
    688     afterUpdateInternal: function(effect) { with(Element) { 
    689       setStyle(effect.element.firstChild, {bottom: 
    690         (effect.dims[0] - effect.element.clientHeight) + 'px' }); }}, 
    691     afterFinishInternal: function(effect) { with(Element) { 
    692       undoClipping(effect.element);  
    693       undoPositioned(effect.element.firstChild); 
    694       undoPositioned(effect.element); 
    695       setStyle(effect.element.firstChild, {bottom: oldInnerBottom}); }} 
     707    afterSetup: function(effect) { 
     708      effect.element.makePositioned(); 
     709      effect.element.firstChild.makePositioned(); 
     710      if(window.opera) effect.element.setStyle({top: ''}); 
     711      effect.element.makeClipping(); 
     712      effect.element.setStyle({height: '0px'}); 
     713      effect.element.show(); }, 
     714    afterUpdateInternal: function(effect) { 
     715      effect.element.firstChild.setStyle({bottom: 
     716        (effect.dims[0] - effect.element.clientHeight) + 'px' });  
     717    }, 
     718    afterFinishInternal: function(effect) { 
     719      effect.element.undoClipping();  
     720      // IE will crash if child is undoPositioned first 
     721      if(/MSIE/.test(navigator.userAgent)){ 
     722        effect.element.undoPositioned(); 
     723        effect.element.firstChild.undoPositioned(); 
     724      }else{ 
     725        effect.element.firstChild.undoPositioned(); 
     726        effect.element.undoPositioned(); 
     727      } 
     728      effect.element.firstChild.setStyle({bottom: oldInnerBottom}); } 
    696729    }, arguments[1] || {}) 
    697730  ); 
     
    700733Effect.SlideUp = function(element) { 
    701734  element = $(element); 
    702   Element.cleanWhitespace(element); 
    703   var oldInnerBottom = Element.getStyle(element.firstChild, 'bottom'); 
    704   return new Effect.Scale(element, 0,  
     735  element.cleanWhitespace(); 
     736  var oldInnerBottom = $(element.firstChild).getStyle('bottom'); 
     737  return new Effect.Scale(element, window.opera ? 0 : 1, 
    705738   Object.extend({ scaleContent: false,  
    706739    scaleX: false,  
     
    708741    scaleFrom: 100, 
    709742    restoreAfterFinish: true, 
    710     beforeStartInternal: function(effect) { with(Element) { 
    711       makePositioned(effect.element); 
    712       makePositioned(effect.element.firstChild); 
    713       if(window.opera) setStyle(effect.element, {top: ''}); 
    714       makeClipping(effect.element); 
    715       show(element); }},   
    716     afterUpdateInternal: function(effect) { with(Element) { 
    717       setStyle(effect.element.firstChild, {bottom: 
    718         (effect.dims[0] - effect.element.clientHeight) + 'px' }); }}, 
    719     afterFinishInternal: function(effect) { with(Element) { 
    720         [hide, undoClipping].call(effect.element);  
    721         undoPositioned(effect.element.firstChild); 
    722         undoPositioned(effect.element); 
    723         setStyle(effect.element.firstChild, {bottom: oldInnerBottom}); }} 
     743    beforeStartInternal: function(effect) { 
     744      effect.element.makePositioned(); 
     745      effect.element.firstChild.makePositioned(); 
     746      if(window.opera) effect.element.setStyle({top: ''}); 
     747      effect.element.makeClipping(); 
     748      effect.element.show(); },   
     749    afterUpdateInternal: function(effect) { 
     750      effect.element.firstChild.setStyle({bottom: 
     751        (effect.dims[0] - effect.element.clientHeight) + 'px' }); }, 
     752    afterFinishInternal: function(effect) { 
     753      effect.element.hide(); 
     754      effect.element.undoClipping(); 
     755      effect.element.firstChild.undoPositioned(); 
     756      effect.element.undoPositioned(); 
     757      effect.element.setStyle({bottom: oldInnerBottom}); } 
    724758   }, arguments[1] || {}) 
    725759  ); 
     
    730764  return new Effect.Scale(element, window.opera ? 1 : 0,  
    731765    { restoreAfterFinish: true, 
    732       beforeSetup: function(effect) { with(Element) { 
    733         makeClipping(effect.element); }},   
    734       afterFinishInternal: function(effect) { with(Element) { 
    735         hide(effect.element);  
    736         undoClipping(effect.element); }} 
     766      beforeSetup: function(effect) { 
     767        effect.element.makeClipping(effect.element); },   
     768      afterFinishInternal: function(effect) { 
     769        effect.element.hide(effect.element);  
     770        effect.element.undoClipping(effect.element); } 
    737771  }); 
    738772} 
     
    742776  var options = Object.extend({ 
    743777    direction: 'center', 
    744     moveTransistion: Effect.Transitions.sinoidal, 
     778    moveTransition: Effect.Transitions.sinoidal, 
    745779    scaleTransition: Effect.Transitions.sinoidal, 
    746780    opacityTransition: Effect.Transitions.full 
     
    751785    height: element.style.height, 
    752786    width: element.style.width, 
    753     opacity: Element.getInlineOpacity(element) }; 
    754  
    755   var dims = Element.getDimensions(element);     
     787    opacity: element.getInlineOpacity() }; 
     788 
     789  var dims = element.getDimensions();     
    756790  var initialMoveX, initialMoveY; 
    757791  var moveX, moveY; 
     
    789823    y: initialMoveY, 
    790824    duration: 0.01,  
    791     beforeSetup: function(effect) { with(Element) { 
    792       hide(effect.element); 
    793       makeClipping(effect.element); 
    794       makePositioned(effect.element); 
    795     }}, 
     825    beforeSetup: function(effect) { 
     826      effect.element.hide(); 
     827      effect.element.makeClipping(); 
     828      effect.element.makePositioned(); 
     829    }, 
    796830    afterFinishInternal: function(effect) { 
    797831      new Effect.Parallel( 
     
    802836            sync: true, scaleFrom: window.opera ? 1 : 0, transition: options.scaleTransition, restoreAfterFinish: true}) 
    803837        ], Object.extend({ 
    804              beforeSetup: function(effect) { with(Element) { 
    805                setStyle(effect.effects[0].element, {height: '0px'}); 
    806                show(effect.effects[0].element); }}, 
    807              afterFinishInternal: function(effect) { with(Element) { 
    808                [undoClipping, undoPositioned].call(effect.effects[0].element);  
    809                setStyle(effect.effects[0].element, oldStyle); }} 
     838             beforeSetup: function(effect) { 
     839               effect.effects[0].element.setStyle({height: '0px'}); 
     840               effect.effects[0].element.show();  
     841             }, 
     842             afterFinishInternal: function(effect) { 
     843               effect.effects[0].element.undoClipping(); 
     844               effect.effects[0].element.undoPositioned(); 
     845               effect.effects[0].element.setStyle(oldStyle);  
     846             } 
    810847           }, options) 
    811848      ) 
     
    818855  var options = Object.extend({ 
    819856    direction: 'center', 
    820     moveTransistion: Effect.Transitions.sinoidal, 
     857    moveTransition: Effect.Transitions.sinoidal, 
    821858    scaleTransition: Effect.Transitions.sinoidal, 
    822859    opacityTransition: Effect.Transitions.none 
     
    827864    height: element.style.height, 
    828865    width: element.style.width, 
    829     opacity: Element.getInlineOpacity(element) }; 
    830  
    831   var dims = Element.getDimensions(element); 
     866    opacity: element.getInlineOpacity() }; 
     867 
     868  var dims = element.getDimensions(); 
    832869  var moveX, moveY; 
    833870   
     
    859896      new Effect.Move(element, { x: moveX, y: moveY, sync: true, transition: options.moveTransition }) 
    860897    ], Object.extend({             
    861          beforeStartInternal: function(effect) { with(Element) { 
    862            [makePositioned, makeClipping].call(effect.effects[0].element) }}, 
    863          afterFinishInternal: function(effect) { with(Element) { 
    864            [hide, undoClipping, undoPositioned].call(effect.effects[0].element); 
    865            setStyle(effect.effects[0].element, oldStyle); }} 
     898         beforeStartInternal: function(effect) { 
     899           effect.effects[0].element.makePositioned(); 
     900           effect.effects[0].element.makeClipping(); }, 
     901         afterFinishInternal: function(effect) { 
     902           effect.effects[0].element.hide(); 
     903           effect.effects[0].element.undoClipping(); 
     904           effect.effects[0].element.undoPositioned(); 
     905           effect.effects[0].element.setStyle(oldStyle); } 
    866906       }, options) 
    867907  ); 
     
    871911  element = $(element); 
    872912  var options    = arguments[1] || {}; 
    873   var oldOpacity = Element.getInlineOpacity(element); 
     913  var oldOpacity = element.getInlineOpacity(); 
    874914  var transition = options.transition || Effect.Transitions.sinoidal; 
    875915  var reverser   = function(pos){ return transition(1-Effect.Transitions.pulse(pos)) }; 
     
    877917  return new Effect.Opacity(element,  
    878918    Object.extend(Object.extend({  duration: 3.0, from: 0, 
    879       afterFinishInternal: function(effect) { Element.setStyle(effect.element, {opacity: oldOpacity}); } 
     919      afterFinishInternal: function(effect) { effect.element.setStyle({opacity: oldOpacity}); } 
    880920    }, options), {transition: reverser})); 
    881921} 
     
    896936      scaleContent: false,  
    897937      scaleY: false, 
    898       afterFinishInternal: function(effect) { with(Element) { 
    899         [hide, undoClipping].call(effect.element);  
    900         setStyle(effect.element, oldStyle); 
    901       }} }); 
     938      afterFinishInternal: function(effect) { 
     939        effect.element.hide(); 
     940        effect.element.undoClipping();  
     941        effect.element.setStyle(oldStyle); 
     942      } }); 
    902943  }}, arguments[1] || {})); 
    903 } 
     944}; 
     945 
     946['setOpacity','getOpacity','getInlineOpacity','forceRerendering','setContentZoom', 
     947 'collectTextNodes','collectTextNodesIgnoreClass','childrenWithClassName'].each(  
     948  function(f) { Element.Methods[f] = Element[f]; } 
     949); 
     950 
     951Element.Methods.visualEffect = function(element, effect, options) { 
     952  s = effect.gsub(/_/, '-').camelize(); 
     953  effect_class = s.charAt(0).toUpperCase() + s.substring(1); 
     954  new Effect[effect_class](element, options); 
     955  return $(element); 
     956}; 
     957 
     958Element.addMethods(); 
  • trunk/trax/vendor/trax/action_view/helpers/javascripts/prototype.js

    r148 r226  
    1 /*  Prototype JavaScript framework, version 1.4.0 
     1/*  Prototype JavaScript framework, version 1.5.0_rc0 
    22 *  (c) 2005 Sam Stephenson <sam@conio.net> 
    33 * 
    4  *  THIS FILE IS AUTOMATICALLY GENERATED. When sending patches, please diff 
    5  *  against the source tree, available from the Prototype darcs repository. 
    6  * 
    74 *  Prototype is freely distributable under the terms of an MIT-style license. 
    8  * 
    95 *  For details, see the Prototype web site: http://prototype.conio.net/ 
    106 * 
     
    128 
    139var Prototype = { 
    14   Version: '1.4.0', 
     10  Version: '1.5.0_rc0', 
    1511  ScriptFragment: '(?:<script.*?>)((\n|\r|.)*?)(?:<\/script>)', 
    1612 
     
    3026 
    3127Object.extend = function(destination, source) { 
    32   for (property in source) { 
     28  for (var property in source) { 
    3329    destination[property] = source[property]; 
    3430  } 
     
    121117  } 
    122118} 
    123  
    124 /*--------------------------------------------------------------------------*/ 
    125  
    126 function $() { 
    127   var elements = new Array(); 
    128  
    129   for (var i = 0; i < arguments.length; i++) { 
    130     var element = arguments[i]; 
    131     if (typeof element == 'string') 
    132       element = document.getElementById(element); 
    133  
    134     if (arguments.length == 1) 
    135       return element; 
    136  
    137     elements.push(element); 
    138   } 
    139  
    140   return elements; 
    141 } 
    142119Object.extend(String.prototype, { 
     120  gsub: function(pattern, replacement) { 
     121    var result = '', source = this, match; 
     122    replacement = arguments.callee.prepareReplacement(replacement); 
     123 
     124    while (source.length > 0) { 
     125      if (match = source.match(pattern)) { 
     126        result += source.slice(0, match.index); 
     127        result += (replacement(match) || '').toString(); 
     128        source  = source.slice(match.index + match[0].length); 
     129      } else { 
     130        result += source, source = ''; 
     131      } 
     132    } 
     133    return result; 
     134  }, 
     135 
     136  sub: function(pattern, replacement, count) { 
     137    replacement = this.gsub.prepareReplacement(replacement); 
     138    count = count === undefined ? 1 : count; 
     139 
     140    return this.gsub(pattern, function(match) { 
     141      if (--count < 0) return match[0]; 
     142      return replacement(match); 
     143    }); 
     144  }, 
     145 
     146  scan: function(pattern, iterator) { 
     147    this.gsub(pattern, iterator); 
     148    return this; 
     149  }, 
     150 
     151  truncate: function(length, truncation) { 
     152    length = length || 30; 
     153    truncation = truncation === undefined ? '...' : truncation; 
     154    return this.length > length ? 
     155      this.slice(0, length - truncation.length) + truncation : this; 
     156  }, 
     157 
     158  strip: function() { 
     159    return this.replace(/^\s+/, '').replace(/\s+$/, ''); 
     160  }, 
     161 
    143162  stripTags: function() { 
    144163    return this.replace(/<\/?[^>]+>/gi, ''); 
     
    158177 
    159178  evalScripts: function() { 
    160     return this.extractScripts().map(eval); 
     179    return this.extractScripts().map(function(script) { return eval(script) }); 
    161180  }, 
    162181 
     
    204223 
    205224  inspect: function() { 
    206     return "'" + this.replace('\\', '\\\\').replace("'", '\\\'') + "'"; 
     225    return "'" + this.replace(/\\/g, '\\\\').replace(/'/g, '\\\'') + "'"; 
    207226  } 
    208227}); 
    209228 
     229String.prototype.gsub.prepareReplacement = function(replacement) { 
     230  if (typeof replacement == 'function') return replacement; 
     231  var template = new Template(replacement); 
     232  return function(match) { return template.evaluate(match) }; 
     233} 
     234 
    210235String.prototype.parseQuery = String.prototype.toQueryParams; 
     236 
     237var Template = Class.create(); 
     238Template.Pattern = /(^|.|\r|\n)(#\{(.*?)\})/; 
     239Template.prototype = { 
     240  initialize: function(template, pattern) { 
     241    this.template = template.toString(); 
     242    this.pattern  = pattern || Template.Pattern; 
     243  }, 
     244 
     245  evaluate: function(object) { 
     246    return this.template.gsub(this.pattern, function(match) { 
     247      var before = match[1]; 
     248      if (before == '\\') return match[2]; 
     249      return before + (object[match[3]] || '').toString(); 
     250    }); 
     251  } 
     252} 
    211253 
    212254var $break    = new Object(); 
     
    314356    this.each(function(value, index) { 
    315357      value = (iterator || Prototype.K)(value, index); 
    316       if (value >= (result || value)) 
     358      if (result == undefined || value >= result) 
    317359        result = value; 
    318360    }); 
     
    324366    this.each(function(value, index) { 
    325367      value = (iterator || Prototype.K)(value, index); 
    326       if (value <= (result || value)) 
     368      if (result == undefined || value < result) 
    327369        result = value; 
    328370    }); 
     
    376418    var collections = [this].concat(args).map($A); 
    377419    return this.map(function(value, index) { 
    378       iterator(value = collections.pluck(index)); 
    379       return value; 
     420      return iterator(collections.pluck(index)); 
    380421    }); 
    381422  }, 
     
    407448Object.extend(Array.prototype, Enumerable); 
    408449 
    409 Array.prototype._reverse = Array.prototype.reverse; 
     450if (!Array.prototype._reverse) 
     451  Array.prototype._reverse = Array.prototype.reverse; 
    410452 
    411453Object.extend(Array.prototype, { 
     
    436478  flatten: function() { 
    437479    return this.inject([], function(array, value) { 
    438       return array.concat(value.constructor == Array ? 
     480      return array.concat(value && value.constructor == Array ? 
    439481        value.flatten() : [value]); 
    440482    }); 
     
    458500  }, 
    459501 
    460   shift: function() { 
    461     var result = this[0]; 
    462     for (var i = 0; i < this.length - 1; i++) 
    463       this[i] = this[i + 1]; 
    464     this.length--; 
    465     return result; 
    466   }, 
    467  
    468502  inspect: function() { 
    469503    return '[' + this.map(Object.inspect).join(', ') + ']'; 
     
    472506var Hash = { 
    473507  _each: function(iterator) { 
    474     for (key in this) { 
     508    for (var key in this) { 
    475509      var value = this[key]; 
    476510      if (typeof value == 'function') continue; 
     
    550584  getTransport: function() { 
    551585    return Try.these( 
     586      function() {return new XMLHttpRequest()}, 
    552587      function() {return new ActiveXObject('Msxml2.XMLHTTP')}, 
    553       function() {return new ActiveXObject('Microsoft.XMLHTTP')}, 
    554       function() {return new XMLHttpRequest()} 
     588      function() {return new ActiveXObject('Microsoft.XMLHTTP')} 
    555589    ) || false; 
    556590  }, 
     
    604638      method:       'post', 
    605639      asynchronous: true, 
     640      contentType:  'application/x-www-form-urlencoded', 
    606641      parameters:   '' 
    607642    } 
     
    663698    var requestHeaders = 
    664699      ['X-Requested-With', 'XMLHttpRequest', 
    665        'X-Prototype-Version', Prototype.Version]; 
     700       'X-Prototype-Version', Prototype.Version, 
     701       'Accept', 'text/javascript, text/html, application/xml, text/xml, */*']; 
    666702 
    667703    if (this.options.method == 'post') { 
    668       requestHeaders.push('Content-type', 
    669         'application/x-www-form-urlencoded'); 
     704      requestHeaders.push('Content-type', this.options.contentType); 
    670705 
    671706      /* Force "Connection: close" for Mozilla browsers to work around 
     
    698733  evalJSON: function() { 
    699734    try { 
    700       return eval(this.header('X-JSON')); 
     735      return eval('(' + this.header('X-JSON') + ')'); 
    701736    } catch (e) {} 
    702737  }, 
     
    832867  } 
    833868}); 
     869function $() { 
     870  var results = [], element; 
     871  for (var i = 0; i < arguments.length; i++) { 
     872    element = arguments[i]; 
     873    if (typeof element == 'string') 
     874      element = document.getElementById(element); 
     875    results.push(Element.extend(element)); 
     876  } 
     877  return results.length < 2 ? results[0] : results; 
     878} 
     879 
    834880document.getElementsByClassName = function(className, parentElement) { 
    835881  var children = ($(parentElement) || document.body).getElementsByTagName('*'); 
    836882  return $A(children).inject([], function(elements, child) { 
    837883    if (child.className.match(new RegExp("(^|\\s)" + className + "(\\s|$)"))) 
    838       elements.push(child); 
     884      elements.push(Element.extend(child)); 
    839885    return elements; 
    840886  }); 
     
    843889/*--------------------------------------------------------------------------*/ 
    844890 
    845 if (!window.Element) { 
     891if (!window.Element) 
    846892  var Element = new Object(); 
    847 } 
    848  
    849 Object.extend(Element, { 
     893 
     894Element.extend = function(element) { 
     895  if (!element) return; 
     896  if (_nativeExtensions) return element; 
     897 
     898  if (!element._extended && element.tagName && element != window) { 
     899    var methods = Element.Methods, cache = Element.extend.cache; 
     900    for (property in methods) { 
     901      var value = methods[property]; 
     902      if (typeof value == 'function') 
     903        element[property] = cache.findOrStore(value); 
     904    } 
     905  } 
     906 
     907  element._extended = true; 
     908  return element; 
     909} 
     910 
     911Element.extend.cache = { 
     912  findOrStore: function(value) { 
     913    return this[value] = this[value] || function() { 
     914      return value.apply(null, [this].concat($A(arguments))); 
     915    } 
     916  } 
     917} 
     918 
     919Element.Methods = { 
    850920  visible: function(element) { 
    851921    return $(element).style.display != 'none'; 
     
    880950  update: function(element, html) { 
    881951    $(element).innerHTML = html.stripScripts(); 
     952    setTimeout(function() {html.evalScripts()}, 10); 
     953  }, 
     954 
     955  replace: function(element, html) { 
     956    element = $(element); 
     957    if (element.outerHTML) { 
     958      element.outerHTML = html.stripScripts(); 
     959    } else { 
     960      var range = element.ownerDocument.createRange(); 
     961      range.selectNodeContents(element); 
     962      element.parentNode.replaceChild( 
     963        range.createContextualFragment(html.stripScripts()), element); 
     964    } 
    882965    setTimeout(function() {html.evalScripts()}, 10); 
    883966  }, 
     
    9191002  empty: function(element) { 
    9201003    return $(element).innerHTML.match(/^\s*$/); 
     1004  }, 
     1005 
     1006  childOf: function(element, ancestor) { 
     1007    element = $(element), ancestor = $(ancestor); 
     1008    while (element = element.parentNode) 
     1009      if (element == ancestor) return true; 
     1010    return false; 
    9211011  }, 
    9221012 
     
    9481038  setStyle: function(element, style) { 
    9491039    element = $(element); 
    950     for (name in style) 
     1040    for (var name in style) 
    9511041      element.style[name.camelize()] = style[name]; 
    9521042  }, 
     
    10141104    element._overflow = undefined; 
    10151105  } 
    1016 }); 
     1106} 
     1107 
     1108Object.extend(Element, Element.Methods); 
     1109 
     1110var _nativeExtensions = false; 
     1111 
     1112if(!HTMLElement && /Konqueror|Safari|KHTML/.test(navigator.userAgent)) { 
     1113  var HTMLElement = {} 
     1114  HTMLElement.prototype = document.createElement('div').__proto__; 
     1115} 
     1116 
     1117Element.addMethods = function(methods) { 
     1118  Object.extend(Element.Methods, methods || {}); 
     1119 
     1120  if(typeof HTMLElement != 'undefined') { 
     1121    var methods = Element.Methods, cache = Element.extend.cache; 
     1122    for (property in methods) { 
     1123      var value = methods[property]; 
     1124      if (typeof value == 'function') 
     1125        HTMLElement.prototype[property] = cache.findOrStore(value); 
     1126    } 
     1127    _nativeExtensions = true; 
     1128  } 
     1129} 
     1130 
     1131Element.addMethods(); 
    10171132 
    10181133var Toggle = new Object(); 
     
    10341149        this.element.insertAdjacentHTML(this.adjacency, this.content); 
    10351150      } catch (e) { 
    1036         if (this.element.tagName.toLowerCase() == 'tbody') { 
     1151        var tagName = this.element.tagName.toLowerCase(); 
     1152        if (tagName == 'tbody' || tagName == 'tr') { 
    10371153          this.insertContent(this.contentFromAnonymousTable()); 
    10381154        } else { 
     
    11491265 
    11501266Object.extend(Element.ClassNames.prototype, Enumerable); 
     1267var Selector = Class.create(); 
     1268Selector.prototype = { 
     1269  initialize: function(expression) { 
     1270    this.params = {classNames: []}; 
     1271    this.expression = expression.toString().strip(); 
     1272    this.parseExpression(); 
     1273    this.compileMatcher(); 
     1274  }, 
     1275 
     1276  parseExpression: function() { 
     1277    function abort(message) { throw 'Parse error in selector: ' + message; } 
     1278 
     1279    if (this.expression == '')  abort('empty expression'); 
     1280 
     1281    var params = this.params, expr = this.expression, match, modifier, clause, rest; 
     1282    while (match = expr.match(/^(.*)\[([a-z0-9_:-]+?)(?:([~\|!]?=)(?:"([^"]*)"|([^\]\s]*)))?\]$/i)) { 
     1283      params.attributes = params.attributes || []; 
     1284      params.attributes.push({name: match[2], operator: match[3], value: match[4] || match[5] || ''}); 
     1285      expr = match[1]; 
     1286    } 
     1287 
     1288    if (expr == '*') return this.params.wildcard = true; 
     1289 
     1290    while (match = expr.match(/^([^a-z0-9_-])?([a-z0-9_-]+)(.*)/i)) { 
     1291      modifier = match[1], clause = match[2], rest = match[3]; 
     1292      switch (modifier) { 
     1293        case '#':       params.id = clause; break; 
     1294        case '.':       params.classNames.push(clause); break; 
     1295        case '': 
     1296        case undefined: params.tagName = clause.toUpperCase(); break; 
     1297        default:        abort(expr.inspect()); 
     1298      } 
     1299      expr = rest; 
     1300    } 
     1301 
     1302    if (expr.length > 0) abort(expr.inspect()); 
     1303  }, 
     1304 
     1305  buildMatchExpression: function() { 
     1306    var params = this.params, conditions = [], clause; 
     1307 
     1308    if (params.wildcard) 
     1309      conditions.push('true'); 
     1310    if (clause = params.id) 
     1311      conditions.push('element.id == ' + clause.inspect()); 
     1312    if (clause = params.tagName) 
     1313      conditions.push('element.tagName.toUpperCase() == ' + clause.inspect()); 
     1314    if ((clause = params.classNames).length > 0) 
     1315      for (var i = 0; i < clause.length; i++) 
     1316        conditions.push('Element.hasClassName(element, ' + clause[i].inspect() + ')'); 
     1317    if (clause = params.attributes) { 
     1318      clause.each(function(attribute) { 
     1319        var value = 'element.getAttribute(' + attribute.name.inspect() + ')'; 
     1320        var splitValueBy = function(delimiter) { 
     1321          return value + ' && ' + value + '.split(' + delimiter.inspect() + ')'; 
     1322        } 
     1323 
     1324        switch (attribute.operator) { 
     1325          case '=':       conditions.push(value + ' == ' + attribute.value.inspect()); break; 
     1326          case '~=':      conditions.push(splitValueBy(' ') + '.include(' + attribute.value.inspect() + ')'); break; 
     1327          case '|=':      conditions.push( 
     1328                            splitValueBy('-') + '.first().toUpperCase() == ' + attribute.value.toUpperCase().inspect() 
     1329                          ); break; 
     1330          case '!=':      conditions.push(value + ' != ' + attribute.value.inspect()); break; 
     1331          case '': 
     1332          case undefined: conditions.push(value + ' != null'); break; 
     1333          default:        throw 'Unknown operator ' + attribute.operator + ' in selector'; 
     1334        } 
     1335      }); 
     1336    } 
     1337 
     1338    return conditions.join(' && '); 
     1339  }, 
     1340 
     1341  compileMatcher: function() { 
     1342    this.match = new Function('element', 'if (!element.tagName) return false; \ 
     1343      return ' + this.buildMatchExpression()); 
     1344  }, 
     1345 
     1346  findElements: function(scope) { 
     1347    var element; 
     1348 
     1349    if (element = $(this.params.id)) 
     1350      if (this.match(element)) 
     1351        if (!scope || Element.childOf(element, scope)) 
     1352          return [element]; 
     1353 
     1354    scope = (scope || document).getElementsByTagName(this.params.tagName || '*'); 
     1355 
     1356    var results = []; 
     1357    for (var i = 0; i < scope.length; i++) 
     1358      if (this.match(element = scope[i])) 
     1359        results.push(Element.extend(element)); 
     1360 
     1361    return results; 
     1362  }, 
     1363 
     1364  toString: function() { 
     1365    return this.expression; 
     1366  } 
     1367} 
     1368 
     1369function $$() { 
     1370  return $A(arguments).map(function(expression) { 
     1371    return expression.strip().split(/\s+/).inject([null], function(results, expr) { 
     1372      var selector = new Selector(expr); 
     1373      return results.map(selector.findElements.bind(selector)).flatten(); 
     1374    }); 
     1375  }).flatten(); 
     1376} 
    11511377var Field = { 
    11521378  clear: function() { 
     
    11801406 
    11811407var Form = { 
    1182   serialize: function(form) {  
     1408  serialize: function(form) { 
    11831409    var elements = Form.getElements($(form)); 
    11841410    var queryComponents = new Array(); 
     
    11971423    var elements = new Array(); 
    11981424 
    1199     for (tagName in Form.Element.Serializers) { 
     1425    for (var tagName in Form.Element.Serializers) { 
    12001426      var tagElements = form.getElementsByTagName(tagName); 
    12011427      for (var j = 0; j < tagElements.length; j++) 
     
    13191545    if (index >= 0) { 
    13201546      opt = element.options[index]; 
    1321       value = opt.value; 
    1322       if (!value && !('value' in opt)) 
    1323         value = opt.text; 
     1547      value = opt.value || opt.text; 
    13241548    } 
    13251549    return [element.name, value]; 
     
    13271551 
    13281552  selectMany: function(element) { 
    1329     var value = new Array(); 
     1553    var value = []; 
    13301554    for (var i = 0; i < element.length; i++) { 
    13311555      var opt = element.options[i]; 
    1332       if (opt.selected) { 
    1333         var optValue = opt.value; 
    1334         if (!optValue && !('value' in opt)) 
    1335           optValue = opt.text; 
    1336         value.push(optValue); 
    1337       } 
     1556      if (opt.selected) 
     1557        value.push(opt.value || opt.text); 
    13381558    } 
    13391559    return [element.name, value]; 
     
    15521772 
    15531773/* prevent memory leaks in IE */ 
    1554 Event.observe(window, 'unload', Event.unloadCache, false); 
     1774if (navigator.appVersion.match(/\bMSIE\b/)) 
     1775  Event.observe(window, 'unload', Event.unloadCache, false); 
    15551776var Position = { 
    15561777  // set to true if needed, warning: firefox performance problems