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

Changeset 5528

Show
Ignore:
Timestamp:
11/15/06 18:45:41 (3 years ago)
Author:
madrobby
Message:

script.aculo.us effects world domination attempt with new CSS-rule based Effect.Transform engine

Files:

Legend:

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

    r5511 r5528  
    1 * Update to Prototype 1.5.0_rc2 
     1* Add Effect.Transform that generates parallel executing Effect.Morph sets 
     2    Example: 
     3      // set up transformation 
     4      var transformation = new Effect.Transform([ 
     5        { 'div.morphing': 'font-size:20px;padding-left:40em' }, 
     6        { 'blah'        : 'width:480px;border-width:10px;border-right-width:20px;margin:200px;margin-bottom:-20px;font-size:30px' } 
     7      ],{ duration: 0.5 }); 
     8      // play transformation (can be called more than once) 
     9      transformation.play(); 
     10 
     11* Add Effect.Morph core effect that morphs to a given CSS style rule. Effect.Morph does take orginal styles given by CSS style rules or the style attribute into consideration when calculating the transforms. It works with all length and color based CSS properties, including margins, paddings, borders, opacity and text/background colors. 
     12    Example: 
     13      new Effect.Morph('mydiv',{ 
     14        style: 'font:3em/4em Verdana;color:#f00;border-width:2em', 
     15        duration: 2.0 
     16      }); 
     17 
     18* Update to Prototype 1.5.0_rc2 revision [5527] 
    219 
    320*V1.6.5* (November 8, 2006) 
  • spinoffs/scriptaculous/lib/prototype.js

    r5511 r5528  
    260260 
    261261    return camelizedString; 
     262  }, 
     263 
     264  underscore: function() { 
     265    return this.gsub(/::/, '/').gsub(/([A-Z]+)([A-Z][a-z])/,'#{1}_#{2}').gsub(/([a-z\d])([A-Z])/,'#{1}_#{2}').gsub(/-/,'-').toLowerCase(); 
     266  }, 
     267 
     268  dasherize: function() { 
     269    return this.gsub(/_/,'-'); 
    262270  }, 
    263271 
  • spinoffs/scriptaculous/src/effects.js

    r5468 r5528  
    940940}; 
    941941 
     942Effect.Morph = Class.create(); 
     943Object.extend(Object.extend(Effect.Morph.prototype, Effect.Base.prototype), { 
     944  initialize: function(element) { 
     945    this.element = $(element); 
     946    if(!this.element) throw(Effect._elementDoesNotExistError); 
     947    var options = Object.extend({ 
     948      style: '' 
     949    }, arguments[1] || {}); 
     950    this.start(options); 
     951  }, 
     952  setup: function(){ 
     953    function parseColor(color){ 
     954      return $R(0,2).map(function(i){ 
     955        return parseInt( ((!color || color=='transparent') ? '#ffffff' : color).parseColor().slice(i*2+1,i*2+3), 16 )  
     956      }); 
     957    } 
     958    this.transforms = this.options.style.split(';').map(function(style){       
     959      return style.parseStyle().map(function(property){ 
     960        var originalValue = this.element.getStyle(property[0]); 
     961        return $H({  
     962          style: property[0],  
     963          originalValue: property[1].unit=='color' ?  
     964            parseColor(originalValue) : parseFloat(originalValue || 0),  
     965          targetValue: property[1].unit=='color' ?  
     966            parseColor(property[1].value) : property[1].value, 
     967          unit: property[1].unit 
     968        }); 
     969      }.bind(this)); 
     970    }.bind(this)).flatten(); 
     971  }, 
     972  update: function(position) { 
     973    var style = $H(), value = null; 
     974    this.transforms.each(function(transform){ 
     975      value = transform.unit=='color' ? 
     976        $R(0,2).inject('#',function(m,v,i){ 
     977          return m+(Math.round(transform.originalValue[i]+ 
     978            (transform.targetValue[i] - transform.originalValue[i])*position)).toColorPart() }) :  
     979        value = transform.originalValue + Math.round( 
     980            ((transform.targetValue - transform.originalValue) * position) * 1000)/1000 + transform.unit; 
     981      style[transform.style] = value; 
     982    }); 
     983    this.element.setStyle(style); 
     984  } 
     985}); 
     986 
     987Effect.Transform = Class.create(); 
     988Object.extend(Effect.Transform.prototype, { 
     989  initialize: function(tracks){ 
     990    this.tracks  = []; 
     991    this.options = arguments[1] || {}; 
     992    this.addTracks(tracks); 
     993  }, 
     994  addTracks: function(tracks){ 
     995    tracks.each(function(track){ 
     996      var data = $H(track).values().first(); 
     997      this.tracks.push($H({ 
     998        ids:     $H(track).keys().first(), 
     999        effect:  Effect.Morph, 
     1000        options: { style: data } 
     1001      })); 
     1002    }.bind(this)); 
     1003    return this; 
     1004  }, 
     1005  play: function(){ 
     1006    return new Effect.Parallel( 
     1007      this.tracks.map(function(track){ 
     1008        var elements = [$(track.ids) || $$(track.ids)].flatten(); 
     1009        return elements.map(function(e){ return new track.effect(e, Object.extend({ sync:true }, track.options)) }); 
     1010      }).flatten(), 
     1011      this.options 
     1012    ); 
     1013  } 
     1014}); 
     1015 
     1016String.CSS_PROPERTIES = ['azimuth', 'backgroundAttachment', 'backgroundColor', 'backgroundImage',  
     1017  'backgroundPosition', 'backgroundRepeat', 'borderBottomColor', 'borderBottomStyle',  
     1018  'borderBottomWidth', 'borderCollapse', 'borderLeftColor', 'borderLeftStyle', 'borderLeftWidth', 
     1019  'borderRightColor', 'borderRightStyle', 'borderRightWidth', 'borderSpacing', 'borderTopColor', 
     1020  'borderTopStyle', 'borderTopWidth', 'bottom', 'captionSide', 'clear', 'clip', 'color', 'content', 
     1021  'counterIncrement', 'counterReset', 'cssFloat', 'cueAfter', 'cueBefore', 'cursor', 'direction', 
     1022  'display', 'elevation', 'emptyCells', 'fontFamily', 'fontSize', 'fontSizeAdjust', 'fontStretch', 
     1023  'fontStyle', 'fontVariant', 'fontWeight', 'height', 'left', 'letterSpacing', 'lineHeight', 
     1024  'listStyleImage', 'listStylePosition', 'listStyleType', 'marginBottom', 'marginLeft', 'marginRight', 
     1025  'marginTop', 'markerOffset', 'marks', 'maxHeight', 'maxWidth', 'minHeight', 'minWidth', 'opacity', 
     1026  'orphans', 'outlineColor', 'outlineOffset', 'outlineStyle', 'outlineWidth', 'overflowX', 'overflowY', 
     1027  'paddingBottom', 'paddingLeft', 'paddingRight', 'paddingTop', 'page', 'pageBreakAfter', 'pageBreakBefore', 
     1028  'pageBreakInside', 'pauseAfter', 'pauseBefore', 'pitch', 'pitchRange', 'position', 'quotes', 
     1029  'richness', 'right', 'size', 'speakHeader', 'speakNumeral', 'speakPunctuation', 'speechRate', 'stress', 
     1030  'tableLayout', 'textAlign', 'textDecoration', 'textIndent', 'textShadow', 'textTransform', 'top', 
     1031  'unicodeBidi', 'verticalAlign', 'visibility', 'voiceFamily', 'volume', 'whiteSpace', 'widows', 
     1032  'width', 'wordSpacing', 'zIndex']; 
     1033 
     1034String.prototype.parseStyle = function(){ 
     1035  var element = Element.extend(document.createElement('div')); 
     1036  element.innerHTML = '<div style="' + this + '"></div>'; 
     1037  var style = element.down().style, styleRules = $H(); 
     1038   
     1039  String.CSS_PROPERTIES.each(function(property){ 
     1040   if(style[property]) styleRules[property] = style[property];  
     1041  }); 
     1042   
     1043  var CSS_LENGTH = /^(([\+\-]?[0-9\.]+)(em|ex|px|in|cm|mm|pt|pc|\%))|0$/; 
     1044  var CSS_COLOR = /^#([A-Fa-f0-9]{3}|[A-Fa-f0-9]{6}|rgb(\d,\d,\d))$/;  
     1045  var result = $H(); 
     1046   
     1047  styleRules.each(function(pair){ 
     1048    var property = pair[0], value = pair[1], unit = null; 
     1049     
     1050    if(CSS_LENGTH.test(value))  
     1051      var components = value.match(/([\+\-]?[0-9\.]+)(.*)/), 
     1052          value = parseFloat(components[1]), unit = (components.length == 3) ? components[2] : null; 
     1053    else 
     1054      if(value.parseColor('#zzzzzz') != '#zzzzzz') { 
     1055        value = value.parseColor(); 
     1056        unit  = 'color'; 
     1057      } 
     1058     
     1059    result[property.underscore().dasherize()] = $H({ value:value, unit:unit }); 
     1060  }.bind(this)); 
     1061   
     1062  return result; 
     1063}; 
     1064 
    9421065['setOpacity','getOpacity','getInlineOpacity','forceRerendering','setContentZoom', 
    9431066 'collectTextNodes','collectTextNodesIgnoreClass'].each(  
  • spinoffs/scriptaculous/src/unittest.js

    r5468 r5528  
    294294    catch(e) { this.error(e); } 
    295295  }, 
     296  assertInspect: function(expected, actual) { 
     297    var message = arguments[2] || "assertInspect"; 
     298    try { (expected == actual.inspect()) ? this.pass() : 
     299      this.fail(message + ': expected "' + Test.Unit.inspect(expected) +  
     300        '", actual "' + Test.Unit.inspect(actual) + '"'); } 
     301    catch(e) { this.error(e); } 
     302  }, 
    296303  assertEnumEqual: function(expected, actual) { 
    297304    var message = arguments[2] || "assertEnumEqual"; 
     
    404411      this.fail(message + ": exception expected but none was raised"); } 
    405412    catch(e) { 
    406       (e.name==exceptionName) ? this.pass() : this.error(e);  
     413      ((exceptionName == null) || (e.name==exceptionName)) ? this.pass() : this.error(e);  
    407414    } 
    408415  }, 
  • spinoffs/scriptaculous/test/unit/index.html

    r4863 r5528  
    6262<ul> 
    6363   <li><a href="effects_test.html" target="test">Effects test</a></li> 
     64   <li><a href="transform_test.html" target="test">Transform test</a></li> 
    6465</ul> 
    6566 
  • spinoffs/scriptaculous/test/unit/string_test.html

    r5375 r5528  
    4949      assertEqual('#00ff00', "rgb(0,255,0)".parseColor()); 
    5050      assertEqual('#0000ff', "rgb(0,0,255)".parseColor()); 
     51    }}, 
     52     
     53    testStringParseStyle: function() { with(this) { 
     54      var expected = "#<Hash:{'font-size': #<Hash:{'value': 11, 'unit': 'px'}>}>"; 
     55 
     56      // basics 
     57      assertInspect(expected, "font-size:11px".parseStyle()); 
     58      assertInspect(expected, "font-SIZE:  11px".parseStyle()); 
     59      assertInspect(expected, "font-size:11px  ".parseStyle()); 
     60      assertInspect(expected, " Font-size: 11px  ".parseStyle()); 
     61 
     62      // values 
     63      assertEqual(-1, "margin: -1px".parseStyle().values().first().value); 
     64      assertEqual( 0, "margin: 0px".parseStyle().values().first().value); 
     65      assertEqual( 0, "margin: 0".parseStyle().values().first().value); 
     66      assertEqual( 1, "margin: 1px".parseStyle().values().first().value); 
     67 
     68      // need units on non-zero lengths 
     69      assertRaise(null, "margin: -1".parseStyle()); 
     70      assertRaise(null, "margin: 1".parseStyle()); 
     71       
     72      // CSS units should work 
     73      ['em','ex','px','in','cm','mm','pt','pc','%'].each(function(unit){ 
     74        assertEqual( unit, ("font-size: 1"+unit).parseStyle().values().first().unit); 
     75        assertEqual( unit, ("display:none;font-size: 1"+unit).parseStyle().values().last().unit); 
     76      }); 
     77       
     78      // non-CSS units should raise 
     79      ['apples','pears','monkeys','mx','yz'].each(function(unit){ 
     80        assertRaise(null, ("font-size: 1"+unit).parseStyle()); 
     81      }); 
     82      
     83      // color parsing galore 
     84      ['#fff','#ffffff','rgb(255,255,255)','rgb(255, 255, 255)'].each(function(color){ 
     85        assertEqual('#ffffff', ('color:'+color).parseStyle().color.value); 
     86      }); 
     87       
     88      expected = "#<Hash:{'value': 22, 'unit': 'pt'}>"; 
     89      assertInspect(expected, "border:22pt".parseStyle()['border-bottom-width']); 
     90      assertInspect(expected, "border-width:22pt".parseStyle()['border-bottom-width']); 
     91 
     92      expected = "#<Hash:{'value': 4.5, 'unit': 'em'}>"; 
     93      assertInspect(expected, "border-bottom-width: 4.5em".parseStyle()['border-bottom-width']); 
     94      assertInspect(expected, "border-bottom: 4.5em".parseStyle()['border-bottom-width']); 
     95      assertInspect(expected, " border-bottom-width:4.5em ".parseStyle()['border-bottom-width']); 
     96      assertInspect(expected, "border:99px solid red;border-width:22pt;border-bottom-width:4.5em".parseStyle()['border-bottom-width']); 
     97      // test with ; at end 
     98      assertInspect(expected, "border:99px solid red;border-width:22pt;border-bottom-width:4.5em;".parseStyle()['border-bottom-width']); 
     99 
    51100    }} 
    52101