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

Changeset 223

Show
Ignore:
Timestamp:
08/26/07 19:29:18 (1 year ago)
Author:
jk
Message:

major overhaul of demo project: moved to edge rails, restful controllers, will_paginate for pagination of both content list and search results

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • trunk/demo/app/controllers/content_controller.rb

    r5 r223  
    11class ContentController < ApplicationController 
    2   def index 
    3     list 
    4     render :action => 'list' 
    5   end 
     2  before_filter :find_content, :only => [ :show, :edit, :update, :destroy ] 
    63 
    7   def list 
    8     @content_pages, @contents = paginate :contents, :per_page => 10 
     4  def index  
     5    @contents = Content.paginate :page => params[:page] 
    96  end 
    107 
    118  def show 
    12     @content = Content.find(params[:id]) 
    139  end 
    1410 
     
    2824 
    2925  def edit 
    30     @content = Content.find(params[:id]) 
    3126  end 
    3227 
    3328  def update 
    34     @content = Content.find(params[:id]) 
    3529    if @content.update_attributes(params[:content]) 
    3630      flash[:notice] = 'Content was successfully updated.' 
     
    4236 
    4337  def destroy 
    44     Content.find(params[:id]).destroy 
     38    @content.destroy 
    4539    redirect_to :action => 'list' 
    4640  end 
    4741 
    48   def search 
    49     @query = params[:query] || '' 
    50     unless @query.blank? 
    51       @results = Content.find_by_contents @query 
     42  protected 
     43 
     44    def find_content 
     45      @content = Content.find params[:id] 
    5246    end 
    53   end 
     47 
    5448end 
  • trunk/demo/app/models/content.rb

    r142 r223  
    11class Content < ContentBase #ActiveRecord::Base 
     2 
     3  def self.per_page; 10; end 
    24 
    35  has_many :comments 
  • trunk/demo/app/views/content/index.rhtml

    r5 r223  
    11<h1>Listing contents</h1> 
    22 
     3<p><%= will_paginate @contents %></p> 
    34<table> 
    45  <tr> 
     
    2021</table> 
    2122 
    22 <%= link_to 'Previous page', { :page => @content_pages.current.previous } if @content_pages.current.previous %> 
    23 <%= link_to 'Next page', { :page => @content_pages.current.next } if @content_pages.current.next %>  
    24  
    25 <br /> 
    26  
    27 <%= link_to 'New content', :action => 'new' %> 
     23<p><%= will_paginate @contents %></p> 
     24<p><%= link_to 'New content', :action => 'new' %></p> 
  • trunk/demo/app/views/search/show.html.erb

    r135 r223  
    1 <h1>Search Content</h1> 
    2 <% form_tag :action => 'search' do %> 
     1<h1>Search</h1> 
     2<% form_for :search, @search, search_path, :method => :get do |f| %> 
    33  <fieldset> 
    44    <legend>Search</legend> 
    5     <input type="text" name="query" value="<%= h @query %>" /
     5    <%= f.text_field 'query' %
    66  </fieldset> 
    77  <%= submit_tag 'search' %> 
     
    99 
    1010<% if @results -%> 
    11 <p>Your search for <%= h @query %> returned <%= @results.size %> Results:</p> 
    12 <ul> 
    13   <% @results.each { |result| -%> 
    14   <li><%= link_to result.title, :action => 'show', :id => result %></li> 
    15   <% } -%> 
    16 </ul> 
     11 
     12  <p>Your search for <%= h @search.query %> returned <%= @results.total_hits %> Results:</p> 
     13 
     14  <p><%= will_paginate @results %></p> 
     15  <ul> 
     16    <% @results.each { |result| -%> 
     17      <li><%= link_to result.title, :action => 'show', :id => result %></li> 
     18    <% } -%> 
     19  </ul> 
     20  <p><%= will_paginate @results %></p> 
     21 
    1722<% end -%> 
  • trunk/demo/config/boot.rb

    r169 r223  
    11# Don't change this file. Configuration is done in config/environment.rb and config/environments/*.rb 
    22 
    3 unless defined?(RAILS_ROOT) 
    4   root_path = File.join(File.dirname(__FILE__), '..') 
    5  
    6   unless RUBY_PLATFORM =~ /(:?mswin|mingw)/ 
    7     require 'pathname' 
    8     root_path = Pathname.new(root_path).cleanpath(true).to_s 
    9   end 
    10  
    11   RAILS_ROOT = root_path 
    12 end 
     3RAILS_ROOT = "#{File.dirname(__FILE__)}/.." unless defined?(RAILS_ROOT) 
    134 
    145unless defined?(Rails::Initializer) 
  • trunk/demo/config/environments/development.rb

    r5 r223  
    99config.whiny_nils        = true 
    1010 
    11 # Enable the breakpoint server that script/breakpointer connects to 
    12 config.breakpoint_server = true 
    13  
    1411# Show full error reports and disable caching 
    1512config.action_controller.consider_all_requests_local = true 
  • trunk/demo/config/routes.rb

    r5 r223  
    11ActionController::Routing::Routes.draw do |map| 
    2   # Add your own custom routes here. 
    3   # The priority is based upon order of creation: first created -> highest priority. 
    4    
    5   # Here's a sample route: 
    6   # map.connect 'products/:id', :controller => 'catalog', :action => 'view' 
    7   # Keep in mind you can assign values other than :controller and :action 
    82 
    9   # You can have the root of your site routed by hooking up ''  
    10   # -- just remember to delete public/index.html. 
    11   # map.connect '', :controller => "welcome" 
     3  map.resources :content 
     4  map.resource :search 
    125 
    13   # Allow downloading Web Service WSDL as a file with an extension 
    14   # instead of a file named 'wsdl' 
    15   map.connect ':controller/service.wsdl', :action => 'wsdl' 
    166 
    177  # Install the default route as the lowest priority. 
  • trunk/demo/public/javascripts/controls.js

    r169 r223  
    1 // Copyright (c) 2005, 2006 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us) 
    2 //           (c) 2005, 2006 Ivan Krstic (http://blogs.law.harvard.edu/ivan) 
    3 //           (c) 2005, 2006 Jon Tirsen (http://www.tirsen.com) 
     1// Copyright (c) 2005-2007 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us) 
     2//           (c) 2005-2007 Ivan Krstic (http://blogs.law.harvard.edu/ivan) 
     3//           (c) 2005-2007 Jon Tirsen (http://www.tirsen.com) 
    44// Contributors: 
    55//  Richard Livsey 
     
    4242Autocompleter.Base.prototype = { 
    4343  baseInitialize: function(element, update, options) { 
    44     this.element     = $(element);  
     44    element          = $(element) 
     45    this.element     = element;  
    4546    this.update      = $(update);   
    4647    this.hasFocus    = false;  
     
    8283    Element.hide(this.update); 
    8384 
    84     Event.observe(this.element, "blur", this.onBlur.bindAsEventListener(this)); 
    85     Event.observe(this.element, "keypress", this.onKeyPress.bindAsEventListener(this)); 
     85    Event.observe(this.element, 'blur', this.onBlur.bindAsEventListener(this)); 
     86    Event.observe(this.element, 'keypress', this.onKeyPress.bindAsEventListener(this)); 
     87 
     88    // Turn autocomplete back on when the user leaves the page, so that the 
     89    // field's value will be remembered on Mozilla-based browsers. 
     90    Event.observe(window, 'beforeunload', function(){  
     91      element.setAttribute('autocomplete', 'on');  
     92    }); 
    8693  }, 
    8794 
     
    8996    if(Element.getStyle(this.update, 'display')=='none') this.options.onShow(this.element, this.update); 
    9097    if(!this.iefix &&  
    91       (navigator.appVersion.indexOf('MSIE')>0) && 
    92       (navigator.userAgent.indexOf('Opera')<0) && 
     98      (Prototype.Browser.IE) && 
    9399      (Element.getStyle(this.update, 'position')=='absolute')) { 
    94100      new Insertion.After(this.update,  
     
    140146         this.markPrevious(); 
    141147         this.render(); 
    142          if(navigator.appVersion.indexOf('AppleWebKit')>0) Event.stop(event); 
     148         if(Prototype.Browser.WebKit) Event.stop(event); 
    143149         return; 
    144150       case Event.KEY_DOWN: 
    145151         this.markNext(); 
    146152         this.render(); 
    147          if(navigator.appVersion.indexOf('AppleWebKit')>0) Event.stop(event); 
     153         if(Prototype.Browser.WebKit) Event.stop(event); 
    148154         return; 
    149155      } 
    150156     else  
    151157       if(event.keyCode==Event.KEY_TAB || event.keyCode==Event.KEY_RETURN ||  
    152          (navigator.appVersion.indexOf('AppleWebKit') > 0 && event.keyCode == 0)) return; 
     158         (Prototype.Browser.WebKit > 0 && event.keyCode == 0)) return; 
    153159 
    154160    this.changed = true; 
     
    196202          Element.addClassName(this.getEntry(i),"selected") :  
    197203          Element.removeClassName(this.getEntry(i),"selected"); 
    198          
    199204      if(this.hasFocus) {  
    200205        this.show(); 
     
    298303    this.changed = false;    
    299304    if(this.getToken().length>=this.options.minChars) { 
    300       this.startIndicator(); 
    301305      this.getUpdatedChoices(); 
    302306    } else { 
     
    339343 
    340344  getUpdatedChoices: function() { 
    341     entry = encodeURIComponent(this.options.paramName) + '=' +  
     345    this.startIndicator(); 
     346     
     347    var entry = encodeURIComponent(this.options.paramName) + '=' +  
    342348      encodeURIComponent(this.getToken()); 
    343349 
     
    347353    if(this.options.defaultParams)  
    348354      this.options.parameters += '&' + this.options.defaultParams; 
    349  
     355     
    350356    new Ajax.Request(this.url, this.options); 
    351357  }, 
     
    476482      paramName: "value", 
    477483      okButton: true, 
     484      okLink: false, 
    478485      okText: "ok", 
     486      cancelButton: false, 
    479487      cancelLink: true, 
    480488      cancelText: "cancel", 
     489      textBeforeControls: '', 
     490      textBetweenControls: '', 
     491      textAfterControls: '', 
    481492      savingText: "Saving...", 
    482493      clickToEditText: "Click to edit", 
     
    566577      this.form.appendChild(br); 
    567578    } 
     579     
     580    if (this.options.textBeforeControls) 
     581      this.form.appendChild(document.createTextNode(this.options.textBeforeControls)); 
    568582 
    569583    if (this.options.okButton) { 
    570       okButton = document.createElement("input"); 
     584      var okButton = document.createElement("input"); 
    571585      okButton.type = "submit"; 
    572586      okButton.value = this.options.okText; 
     
    574588      this.form.appendChild(okButton); 
    575589    } 
     590     
     591    if (this.options.okLink) { 
     592      var okLink = document.createElement("a"); 
     593      okLink.href = "#"; 
     594      okLink.appendChild(document.createTextNode(this.options.okText)); 
     595      okLink.onclick = this.onSubmit.bind(this); 
     596      okLink.className = 'editor_ok_link'; 
     597      this.form.appendChild(okLink); 
     598    } 
     599     
     600    if (this.options.textBetweenControls &&  
     601      (this.options.okLink || this.options.okButton) &&  
     602      (this.options.cancelLink || this.options.cancelButton)) 
     603      this.form.appendChild(document.createTextNode(this.options.textBetweenControls)); 
     604       
     605    if (this.options.cancelButton) { 
     606      var cancelButton = document.createElement("input"); 
     607      cancelButton.type = "submit"; 
     608      cancelButton.value = this.options.cancelText; 
     609      cancelButton.onclick = this.onclickCancel.bind(this); 
     610      cancelButton.className = 'editor_cancel_button'; 
     611      this.form.appendChild(cancelButton); 
     612    } 
    576613 
    577614    if (this.options.cancelLink) { 
    578       cancelLink = document.createElement("a"); 
     615      var cancelLink = document.createElement("a"); 
    579616      cancelLink.href = "#"; 
    580617      cancelLink.appendChild(document.createTextNode(this.options.cancelText)); 
    581618      cancelLink.onclick = this.onclickCancel.bind(this); 
    582       cancelLink.className = 'editor_cancel';       
     619      cancelLink.className = 'editor_cancel editor_cancel_link';       
    583620      this.form.appendChild(cancelLink); 
    584621    } 
     622     
     623    if (this.options.textAfterControls) 
     624      this.form.appendChild(document.createTextNode(this.options.textAfterControls)); 
    585625  }, 
    586626  hasHTMLLineBreaks: function(string) { 
  • trunk/demo/public/javascripts/dragdrop.js

    r169 r223  
    1 // Copyright (c) 2005, 2006 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us) 
    2 //           (c) 2005, 2006 Sammi Williams (http://www.oriontransfer.co.nz, sammi@oriontransfer.co.nz) 
     1// Copyright (c) 2005-2007 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us) 
     2//           (c) 2005-2007 Sammi Williams (http://www.oriontransfer.co.nz, sammi@oriontransfer.co.nz) 
    33//  
    44// script.aculo.us is freely distributable under the terms of an MIT-style license. 
     
    111111 
    112112    if (this.isAffected([Event.pointerX(event), Event.pointerY(event)], element, this.last_active)) 
    113       if (this.last_active.onDrop)  
    114         this.last_active.onDrop(element, this.last_active.element, event); 
     113      if (this.last_active.onDrop) { 
     114        this.last_active.onDrop(element, this.last_active.element, event);  
     115        return true;  
     116      } 
    115117  }, 
    116118 
     
    244246      zindex: 1000, 
    245247      revert: false, 
     248      quiet: false, 
    246249      scroll: false, 
    247250      scrollSensitivity: 20, 
     
    304307      // abort on form elements, fixes a Firefox issue 
    305308      var src = Event.element(event); 
    306       if(src.tagName && ( 
    307         src.tagName=='INPUT' || 
    308         src.tagName=='SELECT' || 
    309         src.tagName=='OPTION' || 
    310         src.tagName=='BUTTON' || 
    311         src.tagName=='TEXTAREA')) return; 
     309      if((tag_name = src.tagName.toUpperCase()) && ( 
     310        tag_name=='INPUT' || 
     311        tag_name=='SELECT' || 
     312        tag_name=='OPTION' || 
     313        tag_name=='BUTTON' || 
     314        tag_name=='TEXTAREA')) return; 
    312315         
    313316      var pointer = [Event.pointerX(event), Event.pointerY(event)]; 
     
    352355  updateDrag: function(event, pointer) { 
    353356    if(!this.dragging) this.startDrag(event); 
    354     Position.prepare(); 
    355     Droppables.show(pointer, this.element); 
     357     
     358    if(!this.options.quiet){ 
     359      Position.prepare(); 
     360      Droppables.show(pointer, this.element); 
     361    } 
     362     
    356363    Draggables.notify('onDrag', this, event); 
    357364     
     
    381388     
    382389    // fix AppleWebKit rendering 
    383     if(navigator.appVersion.indexOf('AppleWebKit')>0) window.scrollBy(0,0); 
     390    if(Prototype.Browser.WebKit) window.scrollBy(0,0); 
    384391     
    385392    Event.stop(event); 
     
    388395  finishDrag: function(event, success) { 
    389396    this.dragging = false; 
     397     
     398    if(this.options.quiet){ 
     399      Position.prepare(); 
     400      var pointer = [Event.pointerX(event), Event.pointerY(event)]; 
     401      Droppables.show(pointer, this.element); 
     402    } 
    390403 
    391404    if(this.options.ghosting) { 
     
    395408    } 
    396409 
    397     if(success) Droppables.fire(event, this.element); 
     410    var dropped = false;  
     411    if(success) {  
     412      dropped = Droppables.fire(event, this.element);  
     413      if (!dropped) dropped = false;  
     414    } 
     415    if(dropped && this.options.onDropped) this.options.onDropped(this.element); 
    398416    Draggables.notify('onEnd', this, event); 
    399417 
     
    403421    var d = this.currentDelta(); 
    404422    if(revert && this.options.reverteffect) { 
    405       this.options.reverteffect(this.element,  
    406         d[1]-this.delta[1], d[0]-this.delta[0]); 
     423      if (dropped == 0 || revert != 'failure') 
     424        this.options.reverteffect(this.element, 
     425          d[1]-this.delta[1], d[0]-this.delta[0]); 
    407426    } else { 
    408427      this.delta = d; 
     
    573592   
    574593  _findRootElement: function(element) { 
    575     while (element.tagName != "BODY") {   
     594    while (element.tagName.toUpperCase() != "BODY") {   
    576595      if(element.id && Sortable.sortables[element.id]) return element; 
    577596      element = element.parentNode; 
     
    613632      hoverclass:  null, 
    614633      ghosting:    false, 
     634      quiet:       false,  
    615635      scroll:      false, 
    616636      scrollSensitivity: 20, 
    617637      scrollSpeed: 15, 
    618638      format:      this.SERIALIZE_RULE, 
     639       
     640      // these take arrays of elements or ids and can be  
     641      // used for better initialization performance 
     642      elements:    false, 
     643      handles:     false, 
     644       
    619645      onChange:    Prototype.emptyFunction, 
    620646      onUpdate:    Prototype.emptyFunction 
     
    627653    var options_for_draggable = { 
    628654      revert:      true, 
     655      quiet:       options.quiet, 
    629656      scroll:      options.scroll, 
    630657      scrollSpeed: options.scrollSpeed, 
     
    680707    } 
    681708 
    682     (this.findElements(element, options) || []).each( function(e) { 
    683       // handles are per-draggable 
    684       var handle = options.handle ?  
    685         $(e).down('.'+options.handle,0) : e;     
     709    (options.elements || this.findElements(element, options) || []).each( function(e,i) { 
     710      var handle = options.handles ? $(options.handles[i]) : 
     711        (options.handle ? $(e).getElementsByClassName(options.handle)[0] : e);  
    686712      options.draggables.push( 
    687713        new Draggable(e, Object.extend(options_for_draggable, { handle: handle }))); 
     
    920946} 
    921947 
    922 Element.findChildren = function(element, only, recursive, tagName) {     
     948Element.findChildren = function(element, only, recursive, tagName) {    
    923949  if(!element.hasChildNodes()) return null; 
    924950  tagName = tagName.toUpperCase(); 
  • trunk/demo/public/javascripts/effects.js

    r169 r223  
    1 // Copyright (c) 2005, 2006 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us) 
     1// Copyright (c) 2005-2007 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us) 
    22// Contributors: 
    33//  Justin Palmer (http://encytemedia.com/) 
     
    4444  element = $(element);   
    4545  element.setStyle({fontSize: (percent/100) + 'em'});    
    46   if(navigator.appVersion.indexOf('AppleWebKit')>0) window.scrollBy(0,0); 
     46  if(Prototype.Browser.WebKit) window.scrollBy(0,0); 
    4747  return element; 
    4848} 
    4949 
    50 Element.getOpacity = function(element){ 
    51   element = $(element); 
    52   var opacity; 
    53   if (opacity = element.getStyle('opacity'))   
    54     return parseFloat(opacity);   
    55   if (opacity = (element.getStyle('filter') || '').match(/alpha\(opacity=(.*)\)/))   
    56     if(opacity[1]) return parseFloat(opacity[1]) / 100;   
    57   return 1.0;   
    58 
    59  
    60 Element.setOpacity = function(element, value){   
    61   element= $(element);   
    62   if (value == 1){ 
    63     element.setStyle({ opacity:  
    64       (/Gecko/.test(navigator.userAgent) && !/Konqueror|Safari|KHTML/.test(navigator.userAgent)) ?  
    65       0.999999 : 1.0 }); 
    66     if(/MSIE/.test(navigator.userAgent) && !window.opera)   
    67       element.setStyle({filter: Element.getStyle(element,'filter').replace(/alpha\([^\)]*\)/gi,'')});   
    68   } else {   
    69     if(value < 0.00001) value = 0;   
    70     element.setStyle({opacity: value}); 
    71     if(/MSIE/.test(navigator.userAgent) && !window.opera)   
    72       element.setStyle( 
    73         { filter: element.getStyle('filter').replace(/alpha\([^\)]*\)/gi,'') + 
    74             'alpha(opacity='+value*100+')' });   
    75   } 
    76   return element; 
    77 }   
    78   
    79 Element.getInlineOpacity = function(element){   
     50Element.getInlineOpacity = function(element){ 
    8051  return $(element).style.opacity || ''; 
    81 }   
     52} 
    8253 
    8354Element.forceRerendering = function(element) { 
     
    10980       
    11081    var tagifyStyle = 'position:relative'; 
    111     if(/MSIE/.test(navigator.userAgent) && !window.opera) tagifyStyle += ';zoom:1'; 
     82    if(Prototype.Browser.IE) tagifyStyle += ';zoom:1'; 
    11283     
    11384    element = $(element); 
     
    172143  }, 
    173144  flicker: function(pos) { 
    174     return ((-Math.cos(pos*Math.PI)/4) + 0.75) + Math.random()/4; 
     145    var pos = ((-Math.cos(pos*Math.PI)/4) + 0.75) + Math.random()/4; 
     146    return (pos > 1 ? 1 : pos); 
    175147  }, 
    176148  wobble: function(pos) { 
     
    199171  initialize: function() { 
    200172    this.effects  = []; 
    201     this.interval = null; 
     173    this.interval = null;     
    202174  }, 
    203175  _each: function(iterator) { 
     
    233205      this.effects.push(effect); 
    234206     
    235     if(!this.interval)  
    236       this.interval = setInterval(this.loop.bind(this), 40); 
     207    if(!this.interval) 
     208      this.interval = setInterval(this.loop.bind(this), 15); 
    237209  }, 
    238210  remove: function(effect) { 
     
    245217  loop: function() { 
    246218    var timePos = new Date().getTime(); 
    247     this.effects.invoke('loop', timePos); 
     219    for(var i=0, len=this.effects.length;i<len;i++)  
     220      this.effects[i] && this.effects[i].loop(timePos); 
    248221  } 
    249222}); 
     
    265238  transition: Effect.Transitions.sinoidal, 
    266239  duration:   1.0,   // seconds 
    267   fps:        25.0,  // max. 25fps due to Effect.Queue implementation 
     240  fps:        100,   // 100= assume 66fps max. 
    268241  sync:       false, // true for combining 
    269242  from:       0.0, 
     
    277250  position: null, 
    278251  start: function(options) { 
     252    function codeForEvent(options,eventName){ 
     253      return ( 
     254        (options[eventName+'Internal'] ? 'this.options.'+eventName+'Internal(this);' : '') + 
     255        (options[eventName] ? 'this.options.'+eventName+'(this);' : '') 
     256      ); 
     257    } 
     258    if(options.transition === false) options.transition = Effect.Transitions.linear; 
    279259    this.options      = Object.extend(Object.extend({},Effect.DefaultOptions), options || {}); 
    280260    this.currentFrame = 0; 
    281261    this.state        = 'idle'; 
    282262    this.startOn      = this.options.delay*1000; 
    283     this.finishOn     = this.startOn + (this.options.duration*1000); 
     263    this.finishOn     = this.startOn+(this.options.duration*1000); 
     264    this.fromToDelta  = this.options.to-this.options.from; 
     265    this.totalTime    = this.finishOn-this.startOn; 
     266    this.totalFrames  = this.options.fps*this.options.duration; 
     267     
     268    eval('this.render = function(pos){ '+ 
     269      'if(this.state=="idle"){this.state="running";'+ 
     270      codeForEvent(options,'beforeSetup')+ 
     271      (this.setup ? 'this.setup();':'')+  
     272      codeForEvent(options,'afterSetup')+ 
     273      '};if(this.state=="running"){'+ 
     274      'pos=this.options.transition(pos)*'+this.fromToDelta+'+'+this.options.from+';'+ 
     275      'this.position=pos;'+ 
     276      codeForEvent(options,'beforeUpdate')+ 
     277      (this.update ? 'this.update(pos);':'')+ 
     278      codeForEvent(options,'afterUpdate')+ 
     279      '}}'); 
     280     
    284281    this.event('beforeStart'); 
    285282    if(!this.options.sync) 
     
    297294        return;   
    298295      } 
    299       var pos   = (timePos - this.startOn) / (this.finishOn - this.startOn); 
    300       var frame = Math.round(pos * this.options.fps * this.options.duration); 
     296      var pos   = (timePos - this.startOn) / this.totalTime, 
     297          frame = Math.round(pos * this.totalFrames); 
    301298      if(frame > this.currentFrame) { 
    302299        this.render(pos); 
    303300        this.currentFrame = frame; 
    304301      } 
    305     } 
    306   }, 
    307   render: function(pos) { 
    308     if(this.state == 'idle') { 
    309       this.state = 'running'; 
    310       this.event('beforeSetup'); 
    311       if(this.setup) this.setup(); 
    312       this.event('afterSetup'); 
    313     } 
    314     if(this.state == 'running') { 
    315       if(this.options.transition) pos = this.options.transition(pos); 
    316       pos *= (this.options.to-this.options.from); 
    317       pos += this.options.from; 
    318       this.position = pos; 
    319       this.event('beforeUpdate'); 
    320       if(this.update) this.update(pos); 
    321       this.event('afterUpdate'); 
    322302    } 
    323303  }, 
     
    333313  }, 
    334314  inspect: function() { 
    335     return '#<Effect:' + $H(this).inspect() + ',options:' + $H(this.options).inspect() + '>'; 
     315    var data = $H(); 
     316    for(property in this) 
     317      if(typeof this[property] != 'function') data[property] = this[property]; 
     318    return '#<Effect:' + data.inspect() + ',options:' + $H(this.options).inspect() + '>'; 
    336319  } 
    337320} 
     
    374357    if(!this.element) throw(Effect._elementDoesNotExistError); 
    375358    // make this work on IE on elements without 'layout' 
    376     if(/MSIE/.test(navigator.userAgent) && !window.opera && (!this.element.currentStyle.hasLayout)) 
     359    if(Prototype.Browser.IE && (!this.element.currentStyle.hasLayout)) 
    377360      this.element.setStyle({zoom: 1}); 
    378361    var options = Object.extend({ 
     
    514497    if(this.element.getStyle('display')=='none') { this.cancel(); return; } 
    515498    // Disable background image during the effect 
    516     this.oldStyle = { 
    517       backgroundImage: this.element.getStyle('background-image') }; 
    518     this.element.setStyle({backgroundImage: 'none'}); 
     499    this.oldStyle = {}; 
     500    if (!this.options.keepBackgroundImage) { 
     501      this.oldStyle.backgroundImage = this.element.getStyle('background-image'); 
     502      this.element.setStyle({backgroundImage: 'none'}); 
     503    } 
    519504    if(!this.options.endcolor) 
    520505      this.options.endcolor = this.element.getStyle('background-color').parseColor('#ffffff'); 
     
    946931    if(!this.element) throw(Effect._elementDoesNotExistError); 
    947932    var options = Object.extend({ 
    948       style: '' 
     933      style: {} 
    949934    }, arguments[1] || {}); 
     935    if (typeof options.style == 'string') { 
     936      if(options.style.indexOf(':') == -1) { 
     937        var cssText = '', selector = '.' + options.style; 
     938        $A(document.styleSheets).reverse().each(function(styleSheet) { 
     939          if (styleSheet.cssRules) cssRules = styleSheet.cssRules; 
     940          else if (styleSheet.rules) cssRules = styleSheet.rules; 
     941          $A(cssRules).reverse().each(function(rule) { 
     942            if (selector == rule.selectorText) { 
     943              cssText = rule.style.cssText; 
     944              throw $break; 
     945            } 
     946          }); 
     947          if (cssText) throw $break; 
     948        }); 
     949        this.style = cssText.parseStyle(); 
     950        options.afterFinishInternal = function(effect){ 
     951          effect.element.addClassName(effect.options.style); 
     952          effect.transforms.each(function(transform) { 
     953            if(transform.style != 'opacity') 
     954              effect.element.style[transform.style] = ''; 
     955          }); 
     956        } 
     957      } else this.style = options.style.parseStyle(); 
     958    } else this.style = $H(options.style) 
    950959    this.start(options); 
    951960  }, 
     
    958967      }); 
    959968    } 
    960     this.transforms = this.options.style.parseStyle().map(function(property){ 
    961       var originalValue = this.element.getStyle(property[0]); 
    962       return $H({  
    963         style: property[0],  
    964         originalValue: property[1].unit=='color' ?  
    965           parseColor(originalValue) : parseFloat(originalValue || 0),  
    966         targetValue: property[1].unit=='color' ?  
    967           parseColor(property[1].value) : property[1].value, 
    968         unit: property[1].unit 
    969       }); 
     969    this.transforms = this.style.map(function(pair){ 
     970      var property = pair[0], value = pair[1], unit = null; 
     971 
     972      if(value.parseColor('#zzzzzz') != '#zzzzzz') { 
     973        value = value.parseColor(); 
     974        unit  = 'color'; 
     975      } else if(property == 'opacity') { 
     976        value = parseFloat(value); 
     977        if(Prototype.Browser.IE && (!this.element.currentStyle.hasLayout)) 
     978          this.element.setStyle({zoom: 1}); 
     979      } else if(Element.CSS_LENGTH.test(value)) { 
     980          var components = value.match(/^([\+\-]?[0-9\.]+)(.*)$/); 
     981          value = parseFloat(components[1]); 
     982          unit = (components.length == 3) ? components[2] : null; 
     983      } 
     984 
     985      var originalValue = this.element.getStyle(property); 
     986      return {  
     987        style: property.camelize(),  
     988        originalValue: unit=='color' ? parseColor(originalValue) : parseFloat(originalValue || 0),  
     989        targetValue: unit=='color' ? parseColor(value) : value, 
     990        unit: unit 
     991      }; 
    970992    }.bind(this)).reject(function(transform){ 
    971993      return ( 
     
    9791001  }, 
    9801002  update: function(position) { 
    981     var style = $H(), value = null; 
    982     this.transforms.each(function(transform){ 
    983       value = transform.unit=='color' ? 
    984         $R(0,2).inject('#',function(m,v,i){ 
    985           return m+(Math.round(transform.originalValue[i]+ 
    986             (transform.targetValue[i] - transform.originalValue[i])*position)).toColorPart() }) :  
     1003    var style = {}, transform, i = this.transforms.length; 
     1004    while(i--) 
     1005      style[(transform = this.transforms[i]).style] =  
     1006        transform.unit=='color' ? '#'+ 
     1007          (Math.round(transform.originalValue[0]+ 
     1008            (transform.targetValue[0]-transform.originalValue[0])*position)).toColorPart() + 
     1009          (Math.round(transform.originalValue[1]+ 
     1010            (transform.targetValue[1]-transform.originalValue[1])*position)).toColorPart() + 
     1011          (Math.round(transform.originalValue[2]+ 
     1012            (transform.targetValue[2]-transform.originalValue[2])*position)).toColorPart() : 
    9871013        transform.originalValue + Math.round( 
    9881014          ((transform.targetValue - transform.originalValue) * position) * 1000)/1000 + transform.unit; 
    989       style[transform.style] = value; 
    990     }); 
    991     this.element.setStyle(style); 
     1015    this.element.setStyle(style, true); 
    9921016  } 
    9931017}); 
     
    10221046}); 
    10231047 
    1024 Element.CSS_PROPERTIES = ['azimuth', 'backgroundAttachment', 'backgroundColor', 'backgroundImage',  
    1025   'backgroundPosition', 'backgroundRepeat', 'borderBottomColor', 'borderBottomStyle',  
    1026   'borderBottomWidth', 'borderCollapse', 'borderLeftColor', 'borderLeftStyle', 'borderLeftWidth', 
    1027   'borderRightColor', 'borderRightStyle', 'borderRightWidth', 'borderSpacing', 'borderTopColor', 
    1028   'borderTopStyle', 'borderTopWidth', 'bottom', 'captionSide', 'clear', 'clip', 'color', 'content', 
    1029   'counterIncrement', 'counterReset', 'cssFloat', 'cueAfter', 'cueBefore', 'cursor', 'direction', 
    1030   'display', 'elevation', 'emptyCells', 'fontFamily', 'fontSize', 'fontSizeAdjust', 'fontStretch', 
    1031   'fontStyle', 'fontVariant', 'fontWeight', 'height', 'left', 'letterSpacing', 'lineHeight', 
    1032   'listStyleImage', 'listStylePosition', 'listStyleType', 'marginBottom', 'marginLeft', 'marginRight', 
    1033   'marginTop', 'markerOffset', 'marks', 'maxHeight', 'maxWidth', 'minHeight', 'minWidth', 'opacity', 
    1034   'orphans', 'outlineColor', 'outlineOffset', 'outlineStyle', 'outlineWidth', 'overflowX', 'overflowY', 
    1035   'paddingBottom', 'paddingLeft', 'paddingRight', 'paddingTop', 'page', 'pageBreakAfter', 'pageBreakBefore', 
    1036   'pageBreakInside', 'pauseAfter', 'pauseBefore', 'pitch', 'pitchRange', 'position', 'quotes', 
    1037   'richness', 'right', 'size', 'speakHeader', 'speakNumeral', 'speakPunctuation', 'speechRate', 'stress', 
    1038   'tableLayout', 'textAlign', 'textDecoration', 'textIndent', 'textShadow', 'textTransform', 'top', 
    1039   'unicodeBidi', 'verticalAlign', 'visibility', 'voiceFamily', 'volume', 'whiteSpace', 'widows', 
    1040   'width', 'wordSpacing', 'zIndex']; 
     1048Element.CSS_PROPERTIES = $w( 
     1049  'backgroundColor backgroundPosition borderBottomColor borderBottomStyle ' +  
     1050  'borderBottomWidth borderLeftColor borderLeftStyle borderLeftWidth ' + 
     1051  'borderRightColor borderRightStyle borderRightWidth borderSpacing ' + 
     1052  'borderTopColor borderTopStyle borderTopWidth bottom clip color ' + 
     1053  'fontSize fontWeight height left letterSpacing lineHeight ' + 
     1054  'marginBottom marginLeft marginRight marginTop markerOffset maxHeight '+ 
     1055  'maxWidth minHeight minWidth opacity outlineColor outlineOffset ' + 
     1056  'outlineWidth paddingBottom paddingLeft paddingRight paddingTop ' + 
     1057  'right textIndent top width wordSpacing zIndex'); 
    10411058   
    10421059Element.CSS_LENGTH = /^(([\+\-]?[0-9\.]+)(em|ex|px|in|cm|mm|pt|pc|\%))|0$/; 
    10431060 
    10441061String.prototype.parseStyle = function(){ 
    1045   var element = Element.extend(document.createElement('div')); 
     1062  var element = document.createElement('div'); 
    10461063  element.innerHTML = '<div style="' + this + '"></div>'; 
    1047   var style = element.down().style, styleRules = $H(); 
     1064  var style = element.childNodes[0].style, styleRules = $H(); 
    10481065   
    10491066  Element.CSS_PROPERTIES.each(function(property){ 
    1050    if(style[property]) styleRules[property] = style[property];  
     1067    if(style[property]) styleRules[property] = style[property];  
    10511068  }); 
    1052    
    1053   var result = $H(); 
    1054    
    1055   styleRules.each(function(pair){ 
    1056     var property = pair[0], value = pair[1], unit = null; 
    1057      
    1058     if(value.parseColor('#zzzzzz') != '#zzzzzz') { 
    1059       value = value.parseColor(); 
    1060       unit  = 'color'; 
    1061     } else if(Element.CSS_LENGTH.test(value))  
    1062       var components = value.match(/^([\+\-]?[0-9\.]+)(.*)$/), 
    1063           value = parseFloat(components[1]), unit = (components.length == 3) ? components[2] : null; 
    1064      
    1065     result[property.underscore().dasherize()] = $H({ value:value, unit:unit }); 
    1066   }.bind(this)); 
    1067    
    1068   return result; 
     1069  if(Prototype.Browser.IE && this.indexOf('opacity') > -1) { 
     1070    styleRules.opacity = this.match(/opacity:\s*((?:0|1)?(?:\.\d*)?)/)[1]; 
     1071  } 
     1072  return styleRules; 
    10691073}; 
    10701074 
     
    10741078}; 
    10751079 
    1076 ['setOpacity','getOpacity','getInlineOpacity','forceRerendering','setContentZoom', 
     1080['getInlineOpacity','forceRerendering','setContentZoom', 
    10771081 'collectTextNodes','collectTextNodesIgnoreClass','morph'].each(  
    10781082  function(f) { Element.Methods[f] = Element[f]; } 
     
    10801084 
    10811085Element.Methods.visualEffect = function(element, effect, options) { 
    1082   s = effect.gsub(/_/, '-').camelize(); 
     1086  s = effect.dasherize().camelize(); 
    10831087  effect_class = s.charAt(0).toUpperCase() + s.substring(1); 
    10841088  new Effect[effect_class](element, options); 
  • trunk/demo/public/javascripts/prototype.js