To edit pages or tickets please login with username/password: aaf/aaf

Changeset 28

Show
Ignore:
Timestamp:
04/17/06 10:29:54 (2 years ago)
Author:
jk
Message:

rails 1.1.1

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • trunk/demo/config/boot.rb

    r5 r28  
    33unless defined?(RAILS_ROOT) 
    44  root_path = File.join(File.dirname(__FILE__), '..') 
     5 
    56  unless RUBY_PLATFORM =~ /mswin32/ 
    67    require 'pathname' 
    78    root_path = Pathname.new(root_path).cleanpath(true).to_s 
    89  end 
     10 
    911  RAILS_ROOT = root_path 
    1012end 
    1113 
    12 if File.directory?("#{RAILS_ROOT}/vendor/rails") 
    13   require "#{RAILS_ROOT}/vendor/rails/railties/lib/initializer" 
    14 else 
    15   require 'rubygems' 
    16   require 'initializer' 
     14unless defined?(Rails::Initializer) 
     15  if File.directory?("#{RAILS_ROOT}/vendor/rails") 
     16    require "#{RAILS_ROOT}/vendor/rails/railties/lib/initializer" 
     17  else 
     18    require 'rubygems' 
     19 
     20    environment_without_comments = IO.readlines(File.dirname(__FILE__) + '/environment.rb').reject { |l| l =~ /^#/ }.join 
     21    environment_without_comments =~ /[^#]RAILS_GEM_VERSION = '([\d.]+)'/ 
     22    rails_gem_version = $1 
     23 
     24    if version = defined?(RAILS_GEM_VERSION) ? RAILS_GEM_VERSION : rails_gem_version 
     25      rails_gem = Gem.cache.search('rails', "=#{version}").first 
     26 
     27      if rails_gem 
     28        require_gem "rails", "=#{version}" 
     29        require rails_gem.full_gem_path + '/lib/initializer' 
     30      else 
     31        STDERR.puts %(Cannot find gem for Rails =#{version}: 
     32    Install the missing gem with 'gem install -v=#{version} rails', or 
     33    change environment.rb to define RAILS_GEM_VERSION with your desired version. 
     34  ) 
     35        exit 1 
     36      end 
     37    else 
     38      require_gem "rails" 
     39      require 'initializer' 
     40    end 
     41  end 
     42 
     43  Rails::Initializer.run(:set_load_path) 
    1744end 
    18  
    19 Rails::Initializer.run(:set_load_path) 
  • trunk/demo/public/javascripts/controls.js

    r5 r28  
    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 
     
    222228      return; 
    223229    } 
    224  
    225     var value = Element.collectTextNodesIgnoreClass(selectedElement, 'informal'); 
     230    var value = ''; 
     231    if (this.options.select) { 
     232      var nodes = document.getElementsByClassName(this.options.select, selectedElement) || []; 
     233      if(nodes.length>0) value = Element.collectTextNodes(nodes[0], this.options.select); 
     234    } else 
     235      value = Element.collectTextNodesIgnoreClass(selectedElement, 'informal'); 
     236     
    226237    var lastTokenPos = this.findLastToken(); 
    227238    if (lastTokenPos != -1) { 
     
    306317Object.extend(Object.extend(Ajax.Autocompleter.prototype, Autocompleter.Base.prototype), { 
    307318  initialize: function(element, update, url, options) { 
    308          this.baseInitialize(element, update, options); 
     319    this.baseInitialize(element, update, options); 
    309320    this.options.asynchronous  = true; 
    310321    this.options.onComplete    = this.onComplete.bind(this); 
     
    449460 
    450461    this.options = Object.extend({ 
     462      okButton: true, 
    451463      okText: "ok", 
     464      cancelLink: true, 
    452465      cancelText: "cancel", 
    453466      savingText: "Saving...", 
     
    471484      highlightcolor: Ajax.InPlaceEditor.defaultHighlightColor, 
    472485      highlightendcolor: "#FFFFFF", 
    473       externalControl:  null, 
    474       ajaxOptions: {} 
     486      externalControl: null, 
     487      submitOnBlur: false, 
     488      ajaxOptions: {}, 
     489      evalScripts: false 
    475490    }, options || {}); 
    476491 
     
    537552    } 
    538553 
    539     okButton = document.createElement("input"); 
    540     okButton.type = "submit"; 
    541     okButton.value = this.options.okText; 
    542     this.form.appendChild(okButton); 
    543  
    544     cancelLink = document.createElement("a"); 
    545     cancelLink.href = "#"; 
    546     cancelLink.appendChild(document.createTextNode(this.options.cancelText)); 
    547     cancelLink.onclick = this.onclickCancel.bind(this); 
    548     this.form.appendChild(cancelLink); 
     554    if (this.options.okButton) { 
     555      okButton = document.createElement("input"); 
     556      okButton.type = "submit"; 
     557      okButton.value = this.options.okText; 
     558      okButton.className = 'editor_ok_button'; 
     559      this.form.appendChild(okButton); 
     560    } 
     561 
     562    if (this.options.cancelLink) { 
     563      cancelLink = document.createElement("a"); 
     564      cancelLink.href = "#"; 
     565      cancelLink.appendChild(document.createTextNode(this.options.cancelText)); 
     566      cancelLink.onclick = this.onclickCancel.bind(this); 
     567      cancelLink.className = 'editor_cancel';       
     568      this.form.appendChild(cancelLink); 
     569    } 
    549570  }, 
    550571  hasHTMLLineBreaks: function(string) { 
     
    562583      text = this.getText(); 
    563584    } 
     585 
     586    var obj = this; 
    564587     
    565588    if (this.options.rows == 1 && !this.hasHTMLLineBreaks(text)) { 
    566589      this.options.textarea = false; 
    567590      var textField = document.createElement("input"); 
     591      textField.obj = this; 
    568592      textField.type = "text"; 
    569593      textField.name = "value"; 
    570594      textField.value = text; 
    571595      textField.style.backgroundColor = this.options.highlightcolor; 
     596      textField.className = 'editor_field'; 
    572597      var size = this.options.size || this.options.cols || 0; 
    573598      if (size != 0) textField.size = size; 
     599      if (this.options.submitOnBlur) 
     600        textField.onblur = this.onSubmit.bind(this); 
    574601      this.editField = textField; 
    575602    } else { 
    576603      this.options.textarea = true; 
    577604      var textArea = document.createElement("textarea"); 
     605      textArea.obj = this; 
    578606      textArea.name = "value"; 
    579607      textArea.value = this.convertHTMLLineBreaks(text); 
    580608      textArea.rows = this.options.rows; 
    581609      textArea.cols = this.options.cols || 40; 
     610      textArea.className = 'editor_field';       
     611      if (this.options.submitOnBlur) 
     612        textArea.onblur = this.onSubmit.bind(this); 
    582613      this.editField = textArea; 
    583614    } 
     
    630661    this.onLoading(); 
    631662     
    632     new Ajax.Updater( 
    633       {  
    634         success: this.element, 
    635          // don't update on failure (this could be an option) 
    636         failure: null 
    637       }, 
    638       this.url, 
    639       Object.extend({ 
    640         parameters: this.options.callback(form, value), 
    641         onComplete: this.onComplete.bind(this), 
    642         onFailure: this.onFailure.bind(this) 
    643       }, this.options.ajaxOptions) 
    644     ); 
     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    } 
    645683    // stop the event to avoid a page refresh in Safari 
    646684    if (arguments.length > 1) { 
     
    723761  } 
    724762}; 
     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}); 
    725790 
    726791// Delayed observer, like Form.Element.Observer,  
  • trunk/demo/public/javascripts/dragdrop.js

    r5 r28  
    11// Copyright (c) 2005 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us) 
     2//           (c) 2005 Sammi Williams (http://www.oriontransfer.co.nz, sammi@oriontransfer.co.nz) 
    23//  
    34// See scriptaculous.js for full license. 
     
    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  }, 
     
    147168    this._lastPointer = null; 
    148169    this.activeDraggable.endDrag(event); 
     170    this.activeDraggable = null; 
    149171  }, 
    150172   
     
    192214      reverteffect: function(element, top_offset, left_offset) { 
    193215        var dur = Math.sqrt(Math.abs(top_offset^2)+Math.abs(left_offset^2))*0.02; 
    194         element._revert = new Effect.MoveBy(element, -top_offset, -left_offset, {duration:dur}); 
     216        element._revert = new Effect.Move(element, { x: -left_offset, y: -top_offset, duration: dur}); 
    195217      }, 
    196218      endeffect: function(element) {  
     
    199221      zindex: 1000, 
    200222      revert: false, 
     223      scroll: false, 
     224      scrollSensitivity: 20, 
     225      scrollSpeed: 15, 
    201226      snap: false   // false, or xy or [x,y] or function(x,y){ return [x,y] } 
    202227    }, arguments[1] || {}); 
     
    204229    this.element = $(element); 
    205230     
    206     if(options.handle && (typeof options.handle == 'string')) 
    207       this.handle = Element.childrenWithClassName(this.element, options.handle)[0];   
     231    if(options.handle && (typeof options.handle == 'string')) { 
     232      var h = Element.childrenWithClassName(this.element, options.handle, true); 
     233      if(h.length>0) this.handle = h[0]; 
     234    } 
    208235    if(!this.handle) this.handle = $(options.handle); 
    209236    if(!this.handle) this.handle = this.element; 
     237     
     238    if(options.scroll && !options.scroll.scrollTo && !options.scroll.outerHTML) 
     239      options.scroll = $(options.scroll); 
    210240 
    211241    Element.makePositioned(this.element); // fix IE     
     
    228258  currentDelta: function() { 
    229259    return([ 
    230       parseInt(this.element.style.left || '0'), 
    231       parseInt(this.element.style.top || '0')]); 
     260      parseInt(Element.getStyle(this.element,'left') || '0'), 
     261      parseInt(Element.getStyle(this.element,'top') || '0')]); 
    232262  }, 
    233263   
     
    239269        src.tagName=='INPUT' || 
    240270        src.tagName=='SELECT' || 
     271        src.tagName=='OPTION' || 
    241272        src.tagName=='BUTTON' || 
    242273        src.tagName=='TEXTAREA')) return; 
     
    268299      Position.absolutize(this.element); 
    269300      this.element.parentNode.insertBefore(this._clone, this.element); 
     301    } 
     302     
     303    if(this.options.scroll) { 
     304      if (this.options.scroll == window) { 
     305        var where = this._getWindowScroll(this.options.scroll); 
     306        this.originalScrollLeft = where.left; 
     307        this.originalScrollTop = where.top; 
     308      } else { 
     309        this.originalScrollLeft = this.options.scroll.scrollLeft; 
     310        this.originalScrollTop = this.options.scroll.scrollTop; 
     311      } 
    270312    } 
    271313     
     
    282324    if(this.options.change) this.options.change(this); 
    283325     
     326    if(this.options.scroll) { 
     327      this.stopScrolling(); 
     328       
     329      var p; 
     330      if (this.options.scroll == window) { 
     331        with(this._getWindowScroll(this.options.scroll)) { p = [ left, top, left+width, top+height ]; } 
     332      } else { 
     333        p = Position.page(this.options.scroll); 
     334        p[0] += this.options.scroll.scrollLeft; 
     335        p[1] += this.options.scroll.scrollTop; 
     336        p.push(p[0]+this.options.scroll.offsetWidth); 
     337        p.push(p[1]+this.options.scroll.offsetHeight); 
     338      } 
     339      var speed = [0,0]; 
     340      if(pointer[0] < (p[0]+this.options.scrollSensitivity)) speed[0] = pointer[0]-(p[0]+this.options.scrollSensitivity); 
     341      if(pointer[1] < (p[1]+this.options.scrollSensitivity)) speed[1] = pointer[1]-(p[1]+this.options.scrollSensitivity); 
     342      if(pointer[0] > (p[2]-this.options.scrollSensitivity)) speed[0] = pointer[0]-(p[2]-this.options.scrollSensitivity); 
     343      if(pointer[1] > (p[3]-this.options.scrollSensitivity)) speed[1] = pointer[1]-(p[3]-this.options.scrollSensitivity); 
     344      this.startScrolling(speed); 
     345    } 
     346     
    284347    // fix AppleWebKit rendering 
    285348    if(navigator.appVersion.indexOf('AppleWebKit')>0) window.scrollBy(0,0); 
     349     
    286350    Event.stop(event); 
    287351  }, 
     
    321385   
    322386  keyPress: function(event) { 
    323     if(!event.keyCode==Event.KEY_ESC) return; 
     387    if(event.keyCode!=Event.KEY_ESC) return; 
    324388    this.finishDrag(event, false); 
    325389    Event.stop(event); 
     
    328392  endDrag: function(event) { 
    329393    if(!this.dragging) return; 
     394    this.stopScrolling(); 
    330395    this.finishDrag(event, true); 
    331396    Event.stop(event); 
     
    337402    pos[0] -= d[0]; pos[1] -= d[1]; 
    338403     
    339     var p = [0,1].map(function(i){ return (point[i]-pos[i]-this.offset[i]) }.bind(this)); 
     404    if(this.options.scroll && (this.options.scroll != window)) { 
     405      pos[0] -= this.options.scroll.scrollLeft-this.originalScrollLeft; 
     406      pos[1] -= this.options.scroll.scrollTop-this.originalScrollTop; 
     407    } 
     408     
     409    var p = [0,1].map(function(i){  
     410      return (point[i]-pos[i]-this.offset[i])  
     411    }.bind(this)); 
    340412     
    341413    if(this.options.snap) { 
     
    358430      style.top  = p[1] + "px"; 
    359431    if(style.visibility=="hidden") style.visibility = ""; // fix gecko rendering 
     432  }, 
     433   
     434  stopScrolling: function() { 
     435    if(this.scrollInterval) { 
     436      clearInterval(this.scrollInterval); 
     437      this.scrollInterval = null; 
     438      Draggables._lastScrollPointer = null; 
     439    } 
     440  }, 
     441   
     442  startScrolling: function(speed) { 
     443    this.scrollSpeed = [speed[0]*this.options.scrollSpeed,speed[1]*this.options.scrollSpeed]; 
     444    this.lastScrolled = new Date(); 
     445    this.scrollInterval = setInterval(this.scroll.bind(this), 10); 
     446  }, 
     447   
     448  scroll: function() { 
     449    var current = new Date(); 
     450    var delta = current - this.lastScrolled; 
     451    this.lastScrolled = current; 
     452    if(this.options.scroll == window) { 
     453      with (this._getWindowScroll(this.options.scroll)) { 
     454        if (this.scrollSpeed[0] || this.scrollSpeed[1]) { 
     455          var d = delta / 1000; 
     456          this.options.scroll.scrollTo( left + d*this.scrollSpeed[0], top + d*this.scrollSpeed[1] ); 
     457        } 
     458      } 
     459    } else { 
     460      this.options.scroll.scrollLeft += this.scrollSpeed[0] * delta / 1000; 
     461      this.options.scroll.scrollTop  += this.scrollSpeed[1] * delta / 1000; 
     462    } 
     463     
     464    Position.prepare(); 
     465    Droppables.show(Draggables._lastPointer, this.element); 
     466    Draggables.notify('onDrag', this); 
     467    Draggables._lastScrollPointer = Draggables._lastScrollPointer || $A(Draggables._lastPointer); 
     468    Draggables._lastScrollPointer[0] += this.scrollSpeed[0] * delta / 1000; 
     469    Draggables._lastScrollPointer[1] += this.scrollSpeed[1] * delta / 1000; 
     470    if (Draggables._lastScrollPointer[0] < 0) 
     471      Draggables._lastScrollPointer[0] = 0; 
     472    if (Draggables._lastScrollPointer[1] < 0) 
     473      Draggables._lastScrollPointer[1] = 0; 
     474    this.draw(Draggables._lastScrollPointer); 
     475     
     476    if(this.options.change) this.options.change(this); 
     477  }, 
     478   
     479  _getWindowScroll: function(w) { 
     480    var T, L, W, H; 
     481    with (w.document) { 
     482      if (w.document.documentElement && documentElement.scrollTop) { 
     483        T = documentElement.scrollTop; 
     484        L = documentElement.scrollLeft; 
     485      } else if (w.document.body) { 
     486        T = body.scrollTop; 
     487        L = body.scrollLeft; 
     488      } 
     489      if (w.innerWidth) { 
     490        W = w.innerWidth; 
     491        H = w.innerHeight; 
     492      } else if (w.document.documentElement && documentElement.clientWidth) { 
     493        W = documentElement.clientWidth; 
     494        H = documentElement.clientHeight; 
     495      } else { 
     496        W = body.offsetWidth; 
     497        H = body.offsetHeight 
     498      } 
     499    } 
     500    return { top: T, left: L, width: W, height: H }; 
    360501  } 
    361502} 
     
    383524 
    384525var Sortable = { 
    385   sortables: new Array(), 
    386    
    387   options: function(element){ 
    388     element = $(element); 
    389     return this.sortables.detect(function(s) { return s.element == element }); 
     526  sortables: {}, 
     527   
     528  _findRootElement: function(element) { 
     529    while (element.tagName != "BODY") {   
     530      if(element.id && Sortable.sortables[element.id]) return element; 
     531      element = element.parentNode; 
     532    } 
     533  }, 
     534 
     535  options: function(element) { 
     536    element = Sortable._findRootElement($(element)); 
     537    if(!element) return; 
     538    return Sortable.sortables[element.id]; 
    390539  }, 
    391540   
    392541  destroy: function(element){ 
    393     element = $(element); 
    394     this.sortables.findAll(function(s) { return s.element == element }).each(function(s){ 
     542    var s = Sortable.options(element); 
     543     
     544    if(s) { 
    395545      Draggables.removeObserver(s.element); 
    396546      s.droppables.each(function(d){ Droppables.remove(d) }); 
    397547      s.draggables.invoke('destroy'); 
    398     }); 
    399     this.sortables = this.sortables.reject(function(s) { return s.element == element }); 
    400   }, 
    401    
     548       
     549      delete Sortable.sortables[s.element.id]; 
     550    } 
     551  }, 
     552 
    402553  create: function(element) { 
    403554    element = $(element); 
     
    406557      tag:         'li',       // assumes li children, override with tag: 'tagname' 
    407558      dropOnEmpty: false, 
    408       tree:        false,      // fixme: unimplemented 
     559      tree:        false, 
     560      treeTag:     'ul', 
    409561      overlap:     'vertical', // one of 'vertical', 'horizontal' 
    410562      constraint:  'vertical', // one of 'vertical', 'horizontal', false 
     
    414566      hoverclass:  null, 
    415567      ghosting:    false, 
    416       format:      null, 
     568      scroll:      false, 
     569      scrollSensitivity: 20, 
     570      scrollSpeed: 15, 
     571      format:      /^[^_]*_(.*)$/, 
    417572      onChange:    Prototype.emptyFunction, 
    418573      onUpdate:    Prototype.emptyFunction 
     
    425580    var options_for_draggable = { 
    426581      revert:      true, 
     582      scroll:      options.scroll, 
     583      scrollSpeed: options.scrollSpeed, 
     584      scrollSensitivity: options.scrollSensitivity, 
    427585      ghosting:    options.ghosting, 
    428586      constraint:  options.constraint, 
     
    450608      overlap:     options.overlap, 
    451609      containment: options.containment, 
     610      tree:        options.tree, 
    452611      hoverclass:  options.hoverclass, 
    453       onHover:     Sortable.onHover, 
    454       greedy:      !options.dropOnEmpty 
     612      onHover:     Sortable.onHover 
     613      //greedy:      !options.dropOnEmpty 
     614    } 
     615     
     616    var options_for_tree = { 
     617      onHover:      Sortable.onEmptyHover, 
     618      overlap:      options.overlap, 
     619      containment:  options.containment, 
     620      hoverclass:   options.hoverclass 
    455621    } 
    456622 
     
    461627    options.droppables = []; 
    462628 
    463     // make it so 
    464  
    465629    // drop on empty handling 
    466     if(options.dropOnEmpty) { 
    467       Droppables.add(element, 
    468         {containment: options.containment, onHover: Sortable.onEmptyHover, greedy: false}); 
     630    if(options.dropOnEmpty || options.tree) { 
     631      Droppables.add(element, options_for_tree); 
    469632      options.droppables.push(element); 
    470633    } 
     
    477640        new Draggable(e, Object.extend(options_for_draggable, { handle: handle }))); 
    478641      Droppables.add(e, options_for_droppable); 
     642      if(options.tree) e.treeNode = element; 
    479643      options.droppables.push(e);       
    480644    }); 
     645     
     646    if(options.tree) { 
     647      (Sortable.findTreeElements(element, options) || []).each( function(e) { 
     648        Droppables.add(e, options_for_tree); 
     649        e.treeNode = element; 
     650        options.droppables.push(e); 
     651      }); 
     652    } 
    481653 
    482654    // keep reference 
    483     this.sortables.push(options)
     655    this.sortables[element.id] = options
    484656 
    485657    // for onupdate 
     
    490662  // return all suitable-for-sortable elements in a guaranteed order 
    491663  findElements: function(element, options) { 
    492     if(!element.hasChildNodes()) return null; 
    493     var elements = []; 
    494     $A(element.childNodes).each( function(e) { 
    495       if(e.tagName && e.tagName.toUpperCase()==options.tag.toUpperCase() && 
    496         (!options.only || (Element.hasClassName(e, options.only)))) 
    497           elements.push(e); 
    498       if(options.tree) { 
    499         var grandchildren = this.findElements(e, options); 
    500         if(grandchildren) elements.push(grandchildren); 
    501       } 
    502     }); 
    503  
    504     return (elements.length>0 ? elements.flatten() : null); 
     664    return Element.findChildren( 
     665      element, options.only, options.tree ? true : false, options.tag); 
     666  }, 
     667   
     668  findTreeElements: function(element, options) { 
     669    return Element.findChildren( 
     670      element, options.only, options.tree ? true : false, options.treeTag); 
    505671  }, 
    506672 
    507673  onHover: function(element, dropon, overlap) { 
    508     if(overlap>0.5) { 
     674    if(Element.isParent(dropon, element)) return; 
     675 
     676    if(overlap > .33 && overlap < .66 && Sortable.options(dropon).tree) { 
     677      return; 
     678    } else if(overlap>0.5) { 
    509679      Sortable.mark(dropon, 'before'); 
    510680      if(dropon.previousSibling != element) { 
     
    529699    } 
    530700  }, 
    531  
    532   onEmptyHover: function(element, dropon) { 
    533     if(element.parentNode!=dropon) { 
    534       var oldParentNode = element.parentNode; 
    535       dropon.appendChild(element); 
     701   
     702  onEmptyHover: function(element, dropon, overlap) { 
     703    var oldParentNode = element.parentNode; 
     704    var droponOptions = Sortable.options(dropon); 
     705         
     706    if(!Element.isParent(dropon, element)) { 
     707      var index; 
     708       
     709      var children = Sortable.findElements(dropon, {tag: droponOptions.tag}); 
     710      var child = null; 
     711             
     712      if(children) { 
     713        var offset = Element.offsetSize(dropon, droponOptions.overlap) * (1.0 - overlap); 
     714         
     715        for (index = 0; index < children.length; index += 1) { 
     716          if (offset - Element.offsetSize (children[index], droponOptions.overlap) >= 0) { 
     717            offset -= Element.offsetSize (children[index], droponOptions.overlap); 
     718          } else if (offset - (Element.offsetSize (children[index], droponOptions.overlap) / 2) >= 0) { 
     719            child = index + 1 < children.length ? children[index + 1] : null; 
     720            break; 
     721          } else { 
     722            child = children[index]; 
     723            break; 
     724          } 
     725        } 
     726      } 
     727       
     728      dropon.insertBefore(element, child); 
     729       
    536730      Sortable.options(oldParentNode).onChange(element); 
    537       Sortable.options(dropon).onChange(element); 
     731      droponOptions.onChange(element); 
    538732    } 
    539733  }, 
     
    567761    Element.show(Sortable._marker); 
    568762  }, 
    569  
    570   serialize: function(element) { 
     763   
     764  _tree: function(element, options, parent) { 
     765    var children = Sortable.findElements(element, options) || []; 
     766   
     767    for (var i = 0; i < children.length; ++i) { 
     768      var match = children[i].id.match(options.format); 
     769 
     770      if (!match) continue; 
     771       
     772      var child = { 
     773        id: encodeURIComponent(match ? match[1] : null), 
     774        element: element, 
     775        parent: parent, 
     776        children: new Array, 
     777        position: parent.children.length, 
     778        container: Sortable._findChildrenElement(children[i], options.treeTag.toUpperCase()) 
     779      } 
     780       
     781      /* Get the element containing the children and recurse over it */ 
     782      if (child.container) 
     783        this._tree(child.container, options, child) 
     784       
     785      parent.children.push (child); 
     786    } 
     787 
     788    return parent;  
     789  }, 
     790 
     791  /* Finds the first element of the given tag type within a parent element. 
     792    Used for finding the first LI[ST] within a L[IST]I[TEM].*/ 
     793  _findChildrenElement: function (element, containerTag) { 
     794    if (element && element.hasChildNodes) 
     795      for (var i = 0; i < element.childNodes.length; ++i) 
     796        if (element.childNodes[i].tagName == containerTag) 
     797          return element.childNodes[i]; 
     798   
     799    return null; 
     800  }, 
     801 
     802  tree: function(element) { 
    571803    element = $(element); 
    572804    var sortableOptions = this.options(element); 
    573805    var options = Object.extend({ 
    574       tag:  sortableOptions.tag, 
     806      tag: sortableOptions.tag, 
     807      treeTag: sortableOptions.treeTag, 
    575808      only: sortableOptions.only, 
    576809      name: element.id, 
    577       format: sortableOptions.format || /^[^_]*_(.*)$/ 
     810      format: sortableOptions.format 
    578811    }, arguments[1] || {}); 
     812     
     813    var root = { 
     814      id: null, 
     815      parent: null, 
     816      children: new Array, 
     817      container: element, 
     818      position: 0 
     819    } 
     820     
     821    return Sortable._tree (element, options, root); 
     822  }, 
     823 
     824  /* Construct a [i] index for a particular node */ 
     825  _constructIndex: function(node) { 
     826    var index = ''; 
     827    do { 
     828      if (node.id) index = '[' + node.position + ']' + index; 
     829    } while ((node = node.parent) != null); 
     830    return index; 
     831  }, 
     832 
     833  sequence: function(element) { 
     834    element = $(element); 
     835    var options = Object.extend(this.options(element), arguments[1] || {}); 
     836     
    579837    return $(this.findElements(element, options) || []).map( function(item) { 
    580       return (encodeURIComponent(options.name) + "[]=" +  
    581               encodeURIComponent(item.id.match(options.format) ? item.id.match(options.format)[1] : '')); 
    582     }).join("&"); 
     838      return item.id.match(options.format) ? item.id.match(options.format)[1] : ''; 
     839    }); 
     840  }, 
     841 
     842  setSequence: function(element, new_sequence) { 
     843    element = $(element); 
     844    var options = Object.extend(this.options(element), arguments[2] || {}); 
     845     
     846    var nodeMap = {}; 
     847    this.findElements(element, options).each( function(n) { 
     848        if (n.id.match(options.format)) 
     849            nodeMap[n.id.match(options.format)[1]] = [n, n.parentNode]; 
     850        n.parentNode.removeChild(n); 
     851    }); 
     852    
     853    new_sequence.each(function(ident) { 
     854      var n = nodeMap[ident]; 
     855      if (n) { 
     856        n[1].appendChild(n[0]); 
     857        delete nodeMap[ident]; 
     858      } 
     859    }); 
     860  }, 
     861   
     862  serialize: function(element) { 
     863    element = $(element); 
     864    var options = Object.extend(Sortable.options(element), arguments[1] || {}); 
     865    var name = encodeURIComponent( 
     866      (arguments[1] && arguments[1].name) ? arguments[1].name : element.id); 
     867     
     868    if (options.tree) { 
     869      return Sortable.tree(element, arguments[1]).children.map( function (item) { 
     870        return [name + Sortable._constructIndex(item) + "=" +  
     871                encodeURIComponent(item.id)].concat(item.children.map(arguments.callee)); 
     872      }).flatten().join('&'); 
     873    } else { 
     874      return Sortable.sequence(element, arguments[1]).map( function(item) { 
     875        return name + "[]=" + encodeURIComponent(item); 
     876      }).join('&'); 
     877    } 
    583878  } 
    584879} 
     880 
     881/* Returns true if child is contained within element */ 
     882Element.isParent = function(child, element) { 
     883  if (!child.parentNode || child == element) return false; 
     884 
     885  if (child.parentNode == element) return true; 
     886 
     887  return Element.isParent(child.parentNode, element); 
     888} 
     889 
     890Element.findChildren = function(element, only, recursive, tagName) {     
     891  if(!element.hasChildNodes()) return null; 
     892  tagName = tagName.toUpperCase(); 
     893  if(only) only = [only].flatten(); 
     894  var elements = []; 
     895  $A(element.childNodes).each( function(e) { 
     896    if(e.tagName && e.tagName.toUpperCase()==tagName && 
     897      (!only || (Element.classNames(e).detect(function(v) { return only.include(v) })))) 
     898        elements.push(e); 
     899    if(recursive) { 
     900      var grandchildren = Element.findChildren(e, only, recursive, tagName); 
     901      if(grandchildren) elements.push(grandchildren); 
     902    } 
     903  }); 
     904 
     905  return (elements.length>0 ? elements.flatten() : []); 
     906} 
     907 
     908Element.offsetSize = function (element, type) { 
     909  if (type == 'vertical' || type == 'height') 
     910    return element.offsetHeight; 
     911  else 
     912    return element.offsetWidth; 
     913} 
  • trunk/demo/public/javascripts/effects.js

    r5 r28  
    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   
     
    2321  }   
    2422  return(color.length==7 ? color : (arguments[0] || this));   
    25 }   
    26  
    27 Element.collectTextNodesIgnoreClass = function(element, ignoreclass) {   
    28   var children = $(element).childNodes;   
    29   var text     = '';   
    30   var classtest = new RegExp('^([^ ]+ )*' + ignoreclass+ '( [^ ]+)*$','i');   
    31   
    32   for (var i = 0; i < children.length; i++) {   
    33     if(children[i].nodeType==3) {   
    34       text+=children[i].nodeValue;   
    35     } else {   
    36       if((!children[i].className.match(classtest)) && children[i].hasChildNodes())   
    37         text += Element.collectTextNodesIgnoreClass(children[i], ignoreclass);   
    38     }   
    39   }   
    40   
    41   return text; 
    42 
    43  
    44 Element.setStyle = function(element, style) { 
    45   element = $(element); 
    46   for(k in style) element.style[k.camelize()] = style[k]; 
    47 
    48  
    49 Element.setContentZoom = function(element, percent) {   
     23
     24 
     25/*--------------------------------------------------------------------------*/ 
     26 
     27Element.collectTextNodes = function(element) {   
     28  return $A($(element).childNodes).collect( function(node) { 
     29    return (node.nodeType==3 ? node.nodeValue :  
     30      (node.hasChildNodes() ? Element.collectTextNodes(node) : '')); 
     31  }).flatten().join(''); 
     32
     33 
     34Element.collectTextNodesIgnoreClass = function(element, className) {   
     35  return $A($(element).childNodes).collect( function(node) { 
     36    return (node.nodeType==3 ? node.nodeValue :  
     37      ((node.hasChildNodes() && !Element.hasClassName(node,className)) ?  
     38        Element.collectTextNodesIgnoreClass(node, className) : '')); 
     39  }).flatten().join(''); 
     40
     41 
     42Element.setContentZoom = function(element, percent) { 
     43  element = $(element);   
    5044  Element.setStyle(element, {fontSize: (percent/100) + 'em'});    
    51   if(navigator.appVersion.indexOf('AppleWebKit')>0) window.scrollBy(0,0);   
     45  if(navigator.appVersion.indexOf('AppleWebKit')>0) window.scrollBy(0,0); 
    5246} 
    5347 
     
    7670       { filter: Element.getStyle(element,'filter').replace(/alpha\([^\)]*\)/gi,'') + 
    7771                 'alpha(opacity='+value*100+')' });   
    78   }    
     72  } 
    7973 
    8074  
     
    8377 
    8478 
    85 Element.childrenWithClassName = function(element, className) {   
    86   return $A($(element).getElementsByTagName('*')).select( 
    87     function(c) { return Element.hasClassName(c, className) }); 
    88 
     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/*--------------------------------------------------------------------------*/ 
    8998 
    9099Array.prototype.call = function() { 
     
    130139      new effect(element, Object.extend(options, { delay: index * options.speed + masterDelay })); 
    131140    }); 
     141  }, 
     142  PAIRS: { 
     143    'slide':  ['SlideDown','SlideUp'], 
     144    'blind':  ['BlindDown','BlindUp'], 
     145    'appear': ['Appear','Fade'] 
     146  }, 
     147  toggle: function(element, effect) { 
     148    element = $(element); 
     149    effect = (effect || 'appear').toLowerCase(); 
     150    var options = Object.extend({ 
     151      queue: { position:'end', scope:(element.id || 'global'), limit: 1 } 
     152    }, arguments[2] || {}); 
     153    Effect[element.visible() ?  
     154      Effect.PAIRS[effect][1] : Effect.PAIRS[effect][0]](element, options); 
    132155  } 
    133156}; 
     
    167190/* ------------- core effects ------------- */ 
    168191 
    169 Effect.Queue = { 
    170   effects:  [], 
     192Effect.ScopedQueue = Class.create(); 
     193Object.extend(Object.extend(Effect.ScopedQueue.prototype, Enumerable), { 
     194  initialize: function() { 
     195    this.effects  = []; 
     196    this.interval = null; 
     197  }, 
    171198  _each: function(iterator) { 
    172199    this.effects._each(iterator); 
    173200  }, 
    174   interval: null, 
    175201  add: function(effect) { 
    176202    var timestamp = new Date().getTime(); 
    177203     
    178     switch(effect.options.queue) { 
     204    var position = (typeof effect.options.queue == 'string') ?  
     205      effect.options.queue : effect.options.queue.position; 
     206     
     207    switch(position) { 
    179208      case 'front': 
    180209        // move unstarted effects after this effect   
     
    192221    effect.startOn  += timestamp; 
    193222    effect.finishOn += timestamp; 
    194     this.effects.push(effect); 
     223 
     224    if(!effect.options.queue.limit || (this.effects.length < effect.options.queue.limit)) 
     225      this.effects.push(effect); 
     226     
    195227    if(!this.interval)  
    196228      this.interval = setInterval(this.loop.bind(this), 40); 
     
    207239    this.effects.invoke('loop', timePos); 
    208240  } 
    209 
    210 Object.extend(Effect.Queue, Enumerable); 
     241}); 
     242 
     243Effect.Queues = { 
     244  instances: $H(), 
     245  get: function(queueName) { 
     246    if(typeof queueName != 'string') return queueName; 
     247     
     248    if(!this.instances[queueName]) 
     <