Ruby on Rails | Screencasts | Download | Documentation | Weblog | Community | Source

Changeset 6236

Show
Ignore:
Timestamp:
02/25/07 23:40:43 (3 years ago)
Author:
madrobby
Message:

script.aculo.us: Various effects engine optimizations [Tobie Langel, Thomas Fuchs]

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • spinoffs/scriptaculous/CHANGELOG

    r6191 r6236  
    11*SVN* 
     2 
     3* Various effects engine optimizations [Tobie Langel, Thomas Fuchs] 
    24 
    35* Update to new Prototype Browser detection 
  • spinoffs/scriptaculous/lib/prototype.js

    r6191 r6236  
    14331433  setStyle: function(element, style) { 
    14341434    element = $(element); 
     1435    var elementStyle = element.style; 
    14351436    for (var name in style) { 
    14361437      var value = style[name]; 
    1437       if(name == 'opacity') { 
    1438         if (value == 1) { 
    1439           value = (/Gecko/.test(navigator.userAgent) && 
    1440             !/Konqueror|Safari|KHTML/.test(navigator.userAgent)) ? 0.999999 : 1.0; 
    1441           if(/MSIE/.test(navigator.userAgent) && !window.opera) 
    1442             element.style.filter = element.getStyle('filter').replace(/alpha\([^\)]*\)/gi,''); 
    1443         } else if(value === '') { 
    1444           if(/MSIE/.test(navigator.userAgent) && !window.opera) 
    1445             element.style.filter = element.getStyle('filter').replace(/alpha\([^\)]*\)/gi,''); 
    1446         } else { 
    1447           if(value < 0.00001) value = 0; 
    1448           if(/MSIE/.test(navigator.userAgent) && !window.opera) 
    1449             element.style.filter = element.getStyle('filter').replace(/alpha\([^\)]*\)/gi,'') + 
    1450               'alpha(opacity='+value*100+')'; 
    1451         } 
    1452       } else if(['float','cssFloat'].include(name)) name = (typeof element.style.styleFloat != 'undefined') ? 'styleFloat' : 'cssFloat'; 
    1453       element.style[name.camelize()] = value; 
    1454     } 
     1438      if (name == 'opacity') element.setOpacity(value); 
     1439      if (name == 'float' || name == 'cssFloat') { 
     1440        name = (typeof elementStyle.styleFloat != 'undefined') ? 
     1441          'styleFloat' : 'cssFloat'; 
     1442      } 
     1443      elementStyle[name.camelize()] = value; 
     1444    } 
     1445    return element; 
     1446  }, 
     1447 
     1448  setOpacity: function(element, value) { 
     1449    element = $(element); 
     1450    element.style.opacity = (value < 0.00001) ? 0 : value; 
    14551451    return element; 
    14561452  }, 
     
    15271523 
    15281524Object.extend(Element.Methods, {childOf: Element.Methods.descendantOf}); 
     1525 
     1526if (Prototype.Browser.IE) { 
     1527  Element.Methods.setOpacity = function(element, value) { 
     1528    element = $(element); 
     1529    var filter = element.getStyle('filter'), style = element.style; 
     1530    if (value == 1 || value === '') { 
     1531      style.filter = filter.replace(/alpha\([^\)]*\)/gi,''); 
     1532      return element; 
     1533    } else if (value < 0.00001) value = 0; 
     1534    style.filter = filter.replace(/alpha\([^\)]*\)/gi, '') + 
     1535      'alpha(opacity=' + (value * 100) + ')'; 
     1536    return element; 
     1537  }; 
     1538} 
     1539 
     1540if (Prototype.Browser.Gecko) { 
     1541  Element.Methods.setOpacity = function(element, value) { 
     1542    element = $(element); 
     1543    var style = element.style; 
     1544    if (value == 1) value = 0.999999; 
     1545    else if (value < 0.00001) value = 0; 
     1546    style.opacity = value; 
     1547    return element; 
     1548  }; 
     1549} 
    15291550 
    15301551Element._attributeTranslations = {}; 
  • spinoffs/scriptaculous/src/effects.js

    r6191 r6236  
    4949 
    5050Element.getOpacity = function(element){ 
    51   return $(element).getStyle('opacity'); 
    52 
    53  
    54 Element.setOpacity = function(element, value){ 
    55   return $(element).setStyle({opacity:value}); 
     51  return Element.getStyle(element,'opacity'); 
    5652} 
    5753 
     
    151147  }, 
    152148  flicker: function(pos) { 
    153     return ((-Math.cos(pos*Math.PI)/4) + 0.75) + Math.random()/4; 
     149    var pos = ((-Math.cos(pos*Math.PI)/4) + 0.75) + Math.random()/4; 
     150    return (pos > 1 ? 1 : pos); 
    154151  }, 
    155152  wobble: function(pos) { 
     
    257254  position: null, 
    258255  start: function(options) { 
     256    function codeForEvent(options,eventName){ 
     257      return ( 
     258        (options[eventName+'Internal'] ? 'this.options.'+eventName+'Internal(this);' : '') + 
     259        (options[eventName] ? 'this.options.'+eventName+'(this);' : '') 
     260      ); 
     261    } 
     262    if(options.transition === false) options.transition = Effect.Transitions.linear; 
    259263    this.options      = Object.extend(Object.extend({},Effect.DefaultOptions), options || {}); 
    260264    this.currentFrame = 0; 
    261265    this.state        = 'idle'; 
    262266    this.startOn      = this.options.delay*1000; 
    263     this.finishOn     = this.startOn + (this.options.duration*1000); 
     267    this.finishOn     = this.startOn+(this.options.duration*1000); 
     268    this.fromToDelta  = this.options.to-this.options.from; 
     269    this.totalTime    = this.finishOn-this.startOn; 
     270    this.totalFrames  = this.options.fps*this.options.duration; 
     271     
     272    eval('this.render = function(pos){ '+ 
     273      'if(this.state=="idle"){this.state="running";'+ 
     274      codeForEvent(options,'beforeSetup')+ 
     275      (this.setup ? 'this.setup();':'')+  
     276      codeForEvent(options,'afterSetup')+ 
     277      '};if(this.state=="running"){'+ 
     278      'pos=this.options.transition(pos)*'+this.fromToDelta+'+'+this.options.from+';'+ 
     279      'this.position=pos;'+ 
     280      codeForEvent(options,'beforeUpdate')+ 
     281      (this.update ? 'this.update(pos);':'')+ 
     282      codeForEvent(options,'afterUpdate')+ 
     283      '}}'); 
     284     
    264285    this.event('beforeStart'); 
    265286    if(!this.options.sync) 
     
    277298        return;   
    278299      } 
    279       var pos   = (timePos - this.startOn) / (this.finishOn - this.startOn); 
    280       var frame = Math.round(pos * this.options.fps * this.options.duration); 
     300      var pos   = (timePos - this.startOn) / this.totalTime, 
     301          frame = Math.round(pos * this.totalFrames); 
    281302      if(frame > this.currentFrame) { 
    282303        this.render(pos); 
    283304        this.currentFrame = frame; 
    284305      } 
    285     } 
    286   }, 
    287   render: function(pos) { 
    288     if(this.state == 'idle') { 
    289       this.state = 'running'; 
    290       this.event('beforeSetup'); 
    291       if(this.setup) this.setup(); 
    292       this.event('afterSetup'); 
    293     } 
    294     if(this.state == 'running') { 
    295       if(this.options.transition) pos = this.options.transition(pos); 
    296       pos *= (this.options.to-this.options.from); 
    297       pos += this.options.from; 
    298       this.position = pos; 
    299       this.event('beforeUpdate'); 
    300       if(this.update) this.update(pos); 
    301       this.event('afterUpdate'); 
    302306    } 
    303307  }, 
     
    952956          effect.transforms.each(function(transform) { 
    953957            if(transform.style != 'opacity') 
    954               effect.element.style[transform.style.camelize()] = ''; 
     958              effect.element.style[transform.style] = ''; 
    955959          }); 
    956960        } 
     
    968972    } 
    969973    this.transforms = this.style.map(function(pair){ 
    970       var property = pair[0].underscore().dasherize(), value = pair[1], unit = null; 
     974      var property = pair[0], value = pair[1], unit = null; 
    971975 
    972976      if(value.parseColor('#zzzzzz') != '#zzzzzz') { 
     
    984988 
    985989      var originalValue = this.element.getStyle(property); 
    986       return $H({  
     990      return {  
    987991        style: property,  
    988992        originalValue: unit=='color' ? parseColor(originalValue) : parseFloat(originalValue || 0),  
    989993        targetValue: unit=='color' ? parseColor(value) : value, 
    990994        unit: unit 
    991       })
     995      }
    992996    }.bind(this)).reject(function(transform){ 
    993997      return ( 
     
    10011005  }, 
    10021006  update: function(position) { 
    1003     var style = $H(), value = null; 
     1007    var style = {}, value = null; 
    10041008    this.transforms.each(function(transform){ 
    10051009      value = transform.unit=='color' ? 
     
    10581062 
    10591063String.prototype.parseStyle = function(){ 
    1060   var element = Element.extend(document.createElement('div')); 
     1064  var element = document.createElement('div'); 
    10611065  element.innerHTML = '<div style="' + this + '"></div>'; 
    1062   var style = element.down().style, styleRules = $H(); 
     1066  var style = element.childNodes[0].style, styleRules = $H(); 
    10631067   
    10641068  Element.CSS_PROPERTIES.each(function(property){ 
     
    10761080}; 
    10771081 
    1078 ['setOpacity','getOpacity','getInlineOpacity','forceRerendering','setContentZoom', 
     1082['getOpacity', 'getInlineOpacity','forceRerendering','setContentZoom', 
    10791083 'collectTextNodes','collectTextNodesIgnoreClass','morph'].each(  
    10801084  function(f) { Element.Methods[f] = Element[f]; } 
     
    10821086 
    10831087Element.Methods.visualEffect = function(element, effect, options) { 
    1084   s = effect.gsub(/_/, '-').camelize(); 
     1088  s = effect.dasherize().camelize(); 
    10851089  effect_class = s.charAt(0).toUpperCase() + s.substring(1); 
    10861090  new Effect[effect_class](element, options); 
  • spinoffs/scriptaculous/test/unit/effects_test.html

    r5742 r6236  
    3232    ['Fade','Appear','BlindUp','BlindDown','Puff','SwitchOff','DropOut','Shake', 
    3333     'SlideUp','SlideDown','Pulsate','Squish','Fold','Grow','Shrink']; 
     34   
     35  var COMBINED_RJS_EFFECTS = $w(''+ 
     36    'fade appear blind_up blind_down puff switch_off drop_out shake '+ 
     37    'slide_up slide_down pulsate squish fold grow shrink' 
     38  ); 
    3439      
    3540  var tmp, tmp2; 
     
    9196    }}, 
    9297     
     98    testTransition: function() { with(this) { 
     99      // false implies linear 
     100      var e = new Effect.Opacity('sandbox',{transition:false,from:0.0,to:0.25,duration:0.5}); 
     101      assert(e.options.transition == Effect.Transitions.linear); 
     102       
     103      wait(1000, function() { 
     104        assertEqual(0.25, $('sandbox').getStyle('opacity')); 
     105        // default to sinoidal 
     106        var e = new Effect.Opacity('sandbox',{from:0.0,to:0.25,duration:0.5}); 
     107        assert(e.options.transition == Effect.Transitions.sinoidal); 
     108        wait(1000, function() { 
     109          assertEqual(0.25, $('sandbox').getStyle('opacity')); 
     110           
     111          var transitions = [ 
     112            { transition: Effect.Transitions.linear,   expected: 1 }, 
     113            { transition: Effect.Transitions.sinoidal, expected: 1 }, 
     114            { transition: Effect.Transitions.reverse,  expected: 0 }, 
     115            { transition: Effect.Transitions.flicker,  expected: 1 }, 
     116            { transition: Effect.Transitions.wobble,   expected: 1 }, 
     117            { transition: Effect.Transitions.pulse,    expected: 1 }, 
     118            { transition: Effect.Transitions.none,     expected: 0 } 
     119          ]; 
     120           
     121          transitions.each(function(t){ 
     122            var e = new Effect.Opacity('sandbox',{sync:true, from:0, to: 1, transition:t.transition}); 
     123            assert(e.options.transition == t.transition); 
     124            e.render(1.0); 
     125            assertEqual(t.expected, e.position, t.transition); 
     126          }); 
     127           
     128        }); 
     129      }); 
     130    }}, 
     131     
    93132    testInspect: function() { with(this) { 
    94133      var e1 = new Effect.Opacity('sandbox',{from:1.0,to:0.5,duration:0.5}); 
     
    231270    // test if all combined effects correctly initialize themselves 
    232271    testCombinedEffectsInitialize: function() { with(this) { 
    233       COMBINED_EFFECTS.each(function(fx){ 
     272      COMBINED_EFFECTS.each(function(fx,idx){ 
    234273        info('Effect.'+fx); 
    235274        $('sandbox').innerHTML = ""; 
     
    246285        assertEqual(0, effect.currentFrame); 
    247286         
     287        // and, for visualEffect 
     288        assert($('test_element') == $('test_element').visualEffect(COMBINED_RJS_EFFECTS[idx])); 
     289         
    248290        // options parsing (shake, squish and grow are special here) 
    249291        if(!['Shake','Squish','Grow'].include(fx)) { 
     
    284326        assertEqual('finished', testeffect.state); 
    285327      }); 
     328    }}, 
     329     
     330    testRenderPerformance: function() { with(this) { 
     331      info('The render() method is generated on a per-effect basis') 
     332      var e = new Effect.Opacity('sandbox',{sync:true}); 
     333      benchmark(function(){ 
     334        e.render(0.5); 
     335      },1000, 'Without events'); 
     336      var e = new Effect.Opacity('sandbox',{sync:true,afterUpdate:function(){return}}); 
     337      benchmark(function(){ 
     338        e.render(0.5); 
     339      },1000, 'With afterUpdate event');       
    286340    }} 
    287341 
  • spinoffs/scriptaculous/test/unit/element_test.html

    r6192 r6236  
    104104        assertEqual(0.3, Element.getOpacity('op4-ie')); 
    105105      } 
     106    }}, 
     107     
     108    testVisualEffect: function() { with(this) { 
     109      assert($('style_test_3') == $('style_test_3').visualEffect('fade')); 
     110      wait(1500,function(){ 
     111        assert(!$('style_test_3').visible()) 
     112      }); 
     113    }}, 
     114     
     115    testParseStylePerformance: function() { with(this) { 
     116      benchmark(function(){ 
     117        "font:12px/15pt Verdana;opacity:0.4;border:4px dotted red".parseStyle(); 
     118      },100); 
    106119    }} 
    107120 
  • spinoffs/scriptaculous/test/unit/transform_test.html

    r5733 r6236  
    7070    }); 
    7171    $('error_message_3').morph('final', {duration:0.5}); 
    72     wait(600,function(){ 
     72    wait(1000,function(){ 
    7373      assertEqual('17px', $('error_test_ul').getStyle('margin-right')); 
    7474      assertEqual('40px', $('error_test_ul').getStyle('font-size')); 
     
    7979      assertEqual(.5, $('error_message_3').getStyle('opacity')); 
    8080      assertEqual('', $('error_message_3').style.fontSize); 
    81       // chaining morphs 
    82       $('error_message').morph('font-size:17px').morph('opacity:0',{delay:3}); 
    83       wait(4100,function(){ // 3000ms delay + 1000ms default duration 
    84         assertEqual(0, $('error_message').getOpacity()); 
    85       }); 
     81    }); 
     82  }}, 
     83   
     84  testElementMorphChaining: function() { with(this) { 
     85    $('error_message').morph('font-size:17px').morph('opacity:0',{delay:3}); 
     86    wait(4100,function(){ // 3000ms delay + 1000ms default duration 
     87      assertEqual(0, $('error_message').getOpacity()); 
    8688    }); 
    8789  }}, 
     
    137139      assertEnumEqual([255,255,255],  
    138140        generatedEffect.effects[2].transforms.detect( function(transform){ 
    139           return (transform.style == 'background-color') 
     141          return (transform.style == 'backgroundColor') 
    140142        }).originalValue); 
    141143      assertEnumEqual([153,85,68],  
    142144        generatedEffect.effects[2].transforms.detect( function(transform){ 
    143           return (transform.style == 'background-color') 
     145          return (transform.style == 'backgroundColor') 
    144146      }).targetValue); 
    145147