serenade 0.4.0 → 0.4.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,6 +1,6 @@
1
1
  /**
2
- * Serenade.js JavaScript Framework v0.4.0
3
- * Revision: 5301262146
2
+ * Serenade.js JavaScript Framework v0.4.1
3
+ * Revision: ae7d321b18
4
4
  * http://github.com/elabs/serenade.js
5
5
  *
6
6
  * Copyright 2011, Jonas Nicklas, Elabs AB
@@ -11,9 +11,9 @@
11
11
  var parser = (function(){
12
12
  var parser = {trace: function trace() { },
13
13
  yy: {},
14
- symbols_: {"error":2,"Root":3,"Element":4,"ElementIdentifier":5,"AnyIdentifier":6,"#":7,".":8,"[":9,"]":10,"PropertyList":11,"WHITESPACE":12,"Text":13,"INDENT":14,"ChildList":15,"OUTDENT":16,"TextList":17,"Bound":18,"STRING_LITERAL":19,"Child":20,"TERMINATOR":21,"IfInstruction":22,"Instruction":23,"Helper":24,"Property":25,"=":26,"!":27,":":28,"-":29,"VIEW":30,"COLLECTION":31,"UNLESS":32,"IN":33,"IDENTIFIER":34,"IF":35,"ElseInstruction":36,"ELSE":37,"@":38,"$accept":0,"$end":1},
15
- terminals_: {2:"error",7:"#",8:".",9:"[",10:"]",12:"WHITESPACE",14:"INDENT",16:"OUTDENT",19:"STRING_LITERAL",21:"TERMINATOR",26:"=",27:"!",28:":",29:"-",30:"VIEW",31:"COLLECTION",32:"UNLESS",33:"IN",34:"IDENTIFIER",35:"IF",37:"ELSE",38:"@"},
16
- productions_: [0,[3,0],[3,1],[5,1],[5,3],[5,2],[5,2],[5,3],[4,1],[4,3],[4,4],[4,3],[4,4],[17,1],[17,3],[13,1],[13,1],[15,1],[15,3],[20,1],[20,1],[20,1],[20,1],[20,1],[11,1],[11,3],[25,3],[25,3],[25,4],[25,4],[25,3],[25,3],[23,5],[23,5],[23,5],[23,5],[23,4],[24,3],[24,3],[24,4],[22,5],[22,4],[22,2],[36,6],[6,1],[6,1],[6,1],[6,1],[6,1],[6,1],[18,2],[18,1]],
14
+ symbols_: {"error":2,"Root":3,"ChildList":4,"ElementIdentifier":5,"AnyIdentifier":6,"#":7,".":8,"Element":9,"[":10,"]":11,"PropertyList":12,"WHITESPACE":13,"Text":14,"INDENT":15,"OUTDENT":16,"TextList":17,"Bound":18,"STRING_LITERAL":19,"Child":20,"TERMINATOR":21,"IfInstruction":22,"Instruction":23,"Helper":24,"Property":25,"=":26,"!":27,":":28,"-":29,"VIEW":30,"COLLECTION":31,"UNLESS":32,"IN":33,"IDENTIFIER":34,"IF":35,"ElseInstruction":36,"ELSE":37,"@":38,"$accept":0,"$end":1},
15
+ terminals_: {2:"error",7:"#",8:".",10:"[",11:"]",13:"WHITESPACE",15:"INDENT",16:"OUTDENT",19:"STRING_LITERAL",21:"TERMINATOR",26:"=",27:"!",28:":",29:"-",30:"VIEW",31:"COLLECTION",32:"UNLESS",33:"IN",34:"IDENTIFIER",35:"IF",37:"ELSE",38:"@"},
16
+ productions_: [0,[3,0],[3,1],[5,1],[5,3],[5,2],[5,2],[5,3],[9,1],[9,3],[9,4],[9,3],[9,4],[17,1],[17,3],[14,1],[14,1],[4,1],[4,3],[20,1],[20,1],[20,1],[20,1],[20,1],[12,1],[12,3],[25,3],[25,3],[25,4],[25,4],[25,3],[25,3],[23,5],[23,5],[23,5],[23,5],[23,4],[24,3],[24,3],[24,4],[22,5],[22,4],[22,2],[36,6],[6,1],[6,1],[6,1],[6,1],[6,1],[6,1],[18,2],[18,1]],
17
17
  performAction: function anonymous(yytext,yyleng,yylineno,yy,yystate,$$,_$) {
18
18
 
19
19
  var $0 = $$.length - 1;
@@ -237,7 +237,7 @@ case 51:this.$ = (function () {}());
237
237
  break;
238
238
  }
239
239
  },
240
- table: [{1:[2,1],3:1,4:2,5:3,6:4,7:[1,5],8:[1,6],30:[1,7],31:[1,8],32:[1,10],33:[1,11],34:[1,12],35:[1,9]},{1:[3]},{1:[2,2],9:[1,13],12:[1,14],14:[1,15]},{1:[2,8],8:[1,16],9:[2,8],12:[2,8],14:[2,8],16:[2,8],21:[2,8]},{1:[2,3],7:[1,17],8:[2,3],9:[2,3],12:[2,3],14:[2,3],16:[2,3],21:[2,3]},{6:18,30:[1,7],31:[1,8],32:[1,10],33:[1,11],34:[1,12],35:[1,9]},{6:19,30:[1,7],31:[1,8],32:[1,10],33:[1,11],34:[1,12],35:[1,9]},{1:[2,44],7:[2,44],8:[2,44],9:[2,44],10:[2,44],12:[2,44],14:[2,44],16:[2,44],21:[2,44],26:[2,44],27:[2,44],28:[2,44],29:[2,44]},{1:[2,45],7:[2,45],8:[2,45],9:[2,45],10:[2,45],12:[2,45],14:[2,45],16:[2,45],21:[2,45],26:[2,45],27:[2,45],28:[2,45],29:[2,45]},{1:[2,46],7:[2,46],8:[2,46],9:[2,46],10:[2,46],12:[2,46],14:[2,46],16:[2,46],21:[2,46],26:[2,46],27:[2,46],28:[2,46],29:[2,46]},{1:[2,47],7:[2,47],8:[2,47],9:[2,47],10:[2,47],12:[2,47],14:[2,47],16:[2,47],21:[2,47],26:[2,47],27:[2,47],28:[2,47],29:[2,47]},{1:[2,48],7:[2,48],8:[2,48],9:[2,48],10:[2,48],12:[2,48],14:[2,48],16:[2,48],21:[2,48],26:[2,48],27:[2,48],28:[2,48],29:[2,48]},{1:[2,49],7:[2,49],8:[2,49],9:[2,49],10:[2,49],12:[2,49],14:[2,49],16:[2,49],21:[2,49],26:[2,49],27:[2,49],28:[2,49],29:[2,49]},{6:23,10:[1,20],11:21,25:22,30:[1,7],31:[1,8],32:[1,10],33:[1,11],34:[1,12],35:[1,9]},{13:24,18:25,19:[1,26],38:[1,27]},{4:30,5:3,6:4,7:[1,5],8:[1,6],13:36,15:28,17:34,18:25,19:[1,26],20:29,22:31,23:32,24:33,29:[1,35],30:[1,7],31:[1,8],32:[1,10],33:[1,11],34:[1,12],35:[1,9],38:[1,27]},{6:37,30:[1,7],31:[1,8],32:[1,10],33:[1,11],34:[1,12],35:[1,9]},{6:38,30:[1,7],31:[1,8],32:[1,10],33:[1,11],34:[1,12],35:[1,9]},{1:[2,5],8:[2,5],9:[2,5],12:[2,5],14:[2,5],16:[2,5],21:[2,5]},{1:[2,6],8:[2,6],9:[2,6],12:[2,6],14:[2,6],16:[2,6],21:[2,6]},{1:[2,9],9:[2,9],12:[2,9],14:[2,9],16:[2,9],21:[2,9]},{10:[1,39],12:[1,40]},{10:[2,24],12:[2,24]},{26:[1,41],28:[1,42]},{1:[2,11],9:[2,11],12:[2,11],14:[2,11],16:[2,11],21:[2,11]},{1:[2,15],9:[2,15],12:[2,15],14:[2,15],16:[2,15],21:[2,15]},{1:[2,16],9:[2,16],12:[2,16],14:[2,16],16:[2,16],21:[2,16]},{1:[2,51],6:43,9:[2,51],10:[2,51],12:[2,51],14:[2,51],16:[2,51],21:[2,51],27:[2,51],29:[2,51],30:[1,7],31:[1,8],32:[1,10],33:[1,11],34:[1,12],35:[1,9]},{16:[1,44],21:[1,45]},{16:[2,17],21:[2,17]},{9:[1,13],12:[1,14],14:[1,15],16:[2,19],21:[2,19]},{14:[1,46],16:[2,20],21:[2,20],29:[1,48],36:47},{14:[1,49],16:[2,21],21:[2,21]},{12:[1,50],14:[1,51],16:[2,22],21:[2,22]},{12:[1,52],16:[2,23],21:[2,23]},{12:[1,53]},{12:[2,13],16:[2,13],21:[2,13]},{1:[2,7],8:[2,7],9:[2,7],12:[2,7],14:[2,7],16:[2,7],21:[2,7]},{1:[2,4],8:[2,4],9:[2,4],12:[2,4],14:[2,4],16:[2,4],21:[2,4]},{1:[2,10],9:[2,10],12:[2,10],14:[2,10],16:[2,10],21:[2,10]},{6:23,25:54,30:[1,7],31:[1,8],32:[1,10],33:[1,11],34:[1,12],35:[1,9]},{6:55,18:56,19:[1,57],30:[1,7],31:[1,8],32:[1,10],33:[1,11],34:[1,12],35:[1,9],38:[1,27]},{6:23,25:58,30:[1,7],31:[1,8],32:[1,10],33:[1,11],34:[1,12],35:[1,9]},{1:[2,50],9:[2,50],10:[2,50],12:[2,50],14:[2,50],16:[2,50],21:[2,50],27:[2,50],29:[2,50]},{1:[2,12],9:[2,12],12:[2,12],14:[2,12],16:[2,12],21:[2,12]},{4:30,5:3,6:4,7:[1,5],8:[1,6],13:36,17:34,18:25,19:[1,26],20:59,22:31,23:32,24:33,29:[1,35],30:[1,7],31:[1,8],32:[1,10],33:[1,11],34:[1,12],35:[1,9],38:[1,27]},{4:30,5:3,6:4,7:[1,5],8:[1,6],13:36,15:60,17:34,18:25,19:[1,26],20:29,22:31,23:32,24:33,29:[1,35],30:[1,7],31:[1,8],32:[1,10],33:[1,11],34:[1,12],35:[1,9],38:[1,27]},{14:[2,42],16:[2,42],21:[2,42],29:[2,42]},{12:[1,61]},{4:30,5:3,6:4,7:[1,5],8:[1,6],13:36,15:62,17:34,18:25,19:[1,26],20:29,22:31,23:32,24:33,29:[1,35],30:[1,7],31:[1,8],32:[1,10],33:[1,11],34:[1,12],35:[1,9],38:[1,27]},{13:63,18:25,19:[1,26],38:[1,27]},{4:30,5:3,6:4,7:[1,5],8:[1,6],13:36,15:64,17:34,18:25,19:[1,26],20:29,22:31,23:32,24:33,29:[1,35],30:[1,7],31:[1,8],32:[1,10],33:[1,11],34:[1,12],35:[1,9],38:[1,27]},{13:65,18:25,19:[1,26],38:[1,27]},{30:[1,67],31:[1,68],32:[1,69],33:[1,70],34:[1,71],35:[1,66]},{10:[2,25],12:[2,25]},{10:[2,26],12:[2,26],27:[1,72]},{10:[2,27],12:[2,27],27:[1,73]},{10:[2,30],12:[2,30]},{10:[2,31],12:[2,31]},{16:[2,18],21:[2,18]},{16:[1,74],21:[1,45]},{37:[1,75]},{16:[1,76],21:[1,45]},{12:[2,38],14:[2,38],16:[2,38],21:[2,38]},{16:[1,77],21:[1,45]},{12:[2,14],16:[2,14],21:[2,14]},{12:[1,78]},{12:[1,79]},{12:[1,80]},{12:[1,81]},{12:[1,82]},{12:[2,37],14:[2,37],16:[2,37],21:[2,37]},{10:[2,28],12:[2,28]},{10:[2,29],12:[2,29]},{14:[2,41],16:[2,41],21:[2,41],29:[2,41]},{14:[1,83]},{14:[2,36],16:[2,36],21:[2,36]},{12:[2,39],14:[2,39],16:[2,39],21:[2,39]},{18:84,38:[1,27]},{19:[1,85]},{18:86,38:[1,27]},{18:87,38:[1,27]},{18:88,38:[1,27]},{4:30,5:3,6:4,7:[1,5],8:[1,6],13:36,15:89,17:34,18:25,19:[1,26],20:29,22:31,23:32,24:33,29:[1,35],30:[1,7],31:[1,8],32:[1,10],33:[1,11],34:[1,12],35:[1,9],38:[1,27]},{14:[2,40],16:[2,40],21:[2,40],29:[2,40]},{14:[2,32],16:[2,32],21:[2,32]},{14:[2,33],16:[2,33],21:[2,33]},{14:[2,34],16:[2,34],21:[2,34]},{14:[2,35],16:[2,35],21:[2,35]},{16:[1,90],21:[1,45]},{14:[2,43],16:[2,43],21:[2,43],29:[2,43]}],
240
+ table: [{1:[2,1],3:1,4:2,5:9,6:12,7:[1,13],8:[1,14],9:4,14:11,17:8,18:15,19:[1,16],20:3,22:5,23:6,24:7,29:[1,10],30:[1,17],31:[1,18],32:[1,20],33:[1,21],34:[1,22],35:[1,19],38:[1,23]},{1:[3]},{1:[2,2],21:[1,24]},{1:[2,17],16:[2,17],21:[2,17]},{1:[2,19],10:[1,25],13:[1,26],15:[1,27],16:[2,19],21:[2,19]},{1:[2,20],15:[1,28],16:[2,20],21:[2,20],29:[1,30],36:29},{1:[2,21],15:[1,31],16:[2,21],21:[2,21]},{1:[2,22],13:[1,32],15:[1,33],16:[2,22],21:[2,22]},{1:[2,23],13:[1,34],16:[2,23],21:[2,23]},{1:[2,8],8:[1,35],10:[2,8],13:[2,8],15:[2,8],16:[2,8],21:[2,8]},{13:[1,36]},{1:[2,13],13:[2,13],16:[2,13],21:[2,13]},{1:[2,3],7:[1,37],8:[2,3],10:[2,3],13:[2,3],15:[2,3],16:[2,3],21:[2,3]},{6:38,30:[1,17],31:[1,18],32:[1,20],33:[1,21],34:[1,22],35:[1,19]},{6:39,30:[1,17],31:[1,18],32:[1,20],33:[1,21],34:[1,22],35:[1,19]},{1:[2,15],10:[2,15],13:[2,15],15:[2,15],16:[2,15],21:[2,15]},{1:[2,16],10:[2,16],13:[2,16],15:[2,16],16:[2,16],21:[2,16]},{1:[2,44],7:[2,44],8:[2,44],10:[2,44],11:[2,44],13:[2,44],15:[2,44],16:[2,44],21:[2,44],26:[2,44],27:[2,44],28:[2,44],29:[2,44]},{1:[2,45],7:[2,45],8:[2,45],10:[2,45],11:[2,45],13:[2,45],15:[2,45],16:[2,45],21:[2,45],26:[2,45],27:[2,45],28:[2,45],29:[2,45]},{1:[2,46],7:[2,46],8:[2,46],10:[2,46],11:[2,46],13:[2,46],15:[2,46],16:[2,46],21:[2,46],26:[2,46],27:[2,46],28:[2,46],29:[2,46]},{1:[2,47],7:[2,47],8:[2,47],10:[2,47],11:[2,47],13:[2,47],15:[2,47],16:[2,47],21:[2,47],26:[2,47],27:[2,47],28:[2,47],29:[2,47]},{1:[2,48],7:[2,48],8:[2,48],10:[2,48],11:[2,48],13:[2,48],15:[2,48],16:[2,48],21:[2,48],26:[2,48],27:[2,48],28:[2,48],29:[2,48]},{1:[2,49],7:[2,49],8:[2,49],10:[2,49],11:[2,49],13:[2,49],15:[2,49],16:[2,49],21:[2,49],26:[2,49],27:[2,49],28:[2,49],29:[2,49]},{1:[2,51],6:40,10:[2,51],11:[2,51],13:[2,51],15:[2,51],16:[2,51],21:[2,51],27:[2,51],29:[2,51],30:[1,17],31:[1,18],32:[1,20],33:[1,21],34:[1,22],35:[1,19]},{5:9,6:12,7:[1,13],8:[1,14],9:4,14:11,17:8,18:15,19:[1,16],20:41,22:5,23:6,24:7,29:[1,10],30:[1,17],31:[1,18],32:[1,20],33:[1,21],34:[1,22],35:[1,19],38:[1,23]},{6:45,11:[1,42],12:43,25:44,30:[1,17],31:[1,18],32:[1,20],33:[1,21],34:[1,22],35:[1,19]},{14:46,18:15,19:[1,16],38:[1,23]},{4:47,5:9,6:12,7:[1,13],8:[1,14],9:4,14:11,17:8,18:15,19:[1,16],20:3,22:5,23:6,24:7,29:[1,10],30:[1,17],31:[1,18],32:[1,20],33:[1,21],34:[1,22],35:[1,19],38:[1,23]},{4:48,5:9,6:12,7:[1,13],8:[1,14],9:4,14:11,17:8,18:15,19:[1,16],20:3,22:5,23:6,24:7,29:[1,10],30:[1,17],31:[1,18],32:[1,20],33:[1,21],34:[1,22],35:[1,19],38:[1,23]},{1:[2,42],15:[2,42],16:[2,42],21:[2,42],29:[2,42]},{13:[1,49]},{4:50,5:9,6:12,7:[1,13],8:[1,14],9:4,14:11,17:8,18:15,19:[1,16],20:3,22:5,23:6,24:7,29:[1,10],30:[1,17],31:[1,18],32:[1,20],33:[1,21],34:[1,22],35:[1,19],38:[1,23]},{14:51,18:15,19:[1,16],38:[1,23]},{4:52,5:9,6:12,7:[1,13],8:[1,14],9:4,14:11,17:8,18:15,19:[1,16],20:3,22:5,23:6,24:7,29:[1,10],30:[1,17],31:[1,18],32:[1,20],33:[1,21],34:[1,22],35:[1,19],38:[1,23]},{14:53,18:15,19:[1,16],38:[1,23]},{6:54,30:[1,17],31:[1,18],32:[1,20],33:[1,21],34:[1,22],35:[1,19]},{30:[1,56],31:[1,57],32:[1,58],33:[1,59],34:[1,60],35:[1,55]},{6:61,30:[1,17],31:[1,18],32:[1,20],33:[1,21],34:[1,22],35:[1,19]},{1:[2,5],8:[2,5],10:[2,5],13:[2,5],15:[2,5],16:[2,5],21:[2,5]},{1:[2,6],8:[2,6],10:[2,6],13:[2,6],15:[2,6],16:[2,6],21:[2,6]},{1:[2,50],10:[2,50],11:[2,50],13:[2,50],15:[2,50],16:[2,50],21:[2,50],27:[2,50],29:[2,50]},{1:[2,18],16:[2,18],21:[2,18]},{1:[2,9],10:[2,9],13:[2,9],15:[2,9],16:[2,9],21:[2,9]},{11:[1,62],13:[1,63]},{11:[2,24],13:[2,24]},{26:[1,64],28:[1,65]},{1:[2,11],10:[2,11],13:[2,11],15:[2,11],16:[2,11],21:[2,11]},{16:[1,66],21:[1,24]},{16:[1,67],21:[1,24]},{37:[1,68]},{16:[1,69],21:[1,24]},{1:[2,38],13:[2,38],15:[2,38],16:[2,38],21:[2,38]},{16:[1,70],21:[1,24]},{1:[2,14],13:[2,14],16:[2,14],21:[2,14]},{1:[2,7],8:[2,7],10:[2,7],13:[2,7],15:[2,7],16:[2,7],21:[2,7]},{13:[1,71]},{13:[1,72]},{13:[1,73]},{13:[1,74]},{13:[1,75]},{1:[2,37],13:[2,37],15:[2,37],16:[2,37],21:[2,37]},{1:[2,4],8:[2,4],10:[2,4],13:[2,4],15:[2,4],16:[2,4],21:[2,4]},{1:[2,10],10:[2,10],13:[2,10],15:[2,10],16:[2,10],21:[2,10]},{6:45,25:76,30:[1,17],31:[1,18],32:[1,20],33:[1,21],34:[1,22],35:[1,19]},{6:77,18:78,19:[1,79],30:[1,17],31:[1,18],32:[1,20],33:[1,21],34:[1,22],35:[1,19],38:[1,23]},{6:45,25:80,30:[1,17],31:[1,18],32:[1,20],33:[1,21],34:[1,22],35:[1,19]},{1:[2,12],10:[2,12],13:[2,12],15:[2,12],16:[2,12],21:[2,12]},{1:[2,41],15:[2,41],16:[2,41],21:[2,41],29:[2,41]},{15:[1,81]},{1:[2,36],15:[2,36],16:[2,36],21:[2,36]},{1:[2,39],13:[2,39],15:[2,39],16:[2,39],21:[2,39]},{18:82,38:[1,23]},{19:[1,83]},{18:84,38:[1,23]},{18:85,38:[1,23]},{18:86,38:[1,23]},{11:[2,25],13:[2,25]},{11:[2,26],13:[2,26],27:[1,87]},{11:[2,27],13:[2,27],27:[1,88]},{11:[2,30],13:[2,30]},{11:[2,31],13:[2,31]},{4:89,5:9,6:12,7:[1,13],8:[1,14],9:4,14:11,17:8,18:15,19:[1,16],20:3,22:5,23:6,24:7,29:[1,10],30:[1,17],31:[1,18],32:[1,20],33:[1,21],34:[1,22],35:[1,19],38:[1,23]},{1:[2,40],15:[2,40],16:[2,40],21:[2,40],29:[2,40]},{1:[2,32],15:[2,32],16:[2,32],21:[2,32]},{1:[2,33],15:[2,33],16:[2,33],21:[2,33]},{1:[2,34],15:[2,34],16:[2,34],21:[2,34]},{1:[2,35],15:[2,35],16:[2,35],21:[2,35]},{11:[2,28],13:[2,28]},{11:[2,29],13:[2,29]},{16:[1,90],21:[1,24]},{1:[2,43],15:[2,43],16:[2,43],21:[2,43],29:[2,43]}],
241
241
  defaultActions: {},
242
242
  parseError: function parseError(str, hash) {
243
243
  throw new Error(str);
@@ -354,7 +354,7 @@ exports.main = function commonjsMain(args) {
354
354
  if (typeof module !== 'undefined' && require.main === module) {
355
355
  exports.main(typeof process !== 'undefined' ? process.argv.slice(1) : require("system").args);
356
356
  }
357
- }var AssociationCollection, COMMENT, Cache, Collection, Compile, DynamicNode, Event, IDENTIFIER, KEYWORDS, LITERAL, Lexer, MULTI_DENT, Model, Node, Property, PropertyAccessor, PropertyDefinition, STRING, Serenade, View, WHITESPACE, capitalize, compile, compileAll, def, defineEvent, defineProperty, extend, format, getValue, globalDependencies, idCounter, isArray, isArrayIndex, normalize, pairToObject, safeDelete, safePush, serializeObject, settings, triggerGlobal,
357
+ }var AssociationCollection, COMMENT, Cache, Collection, Compile, CompiledView, DynamicNode, Event, IDENTIFIER, KEYWORDS, LITERAL, Lexer, MULTI_DENT, Model, Node, Property, PropertyAccessor, PropertyDefinition, STRING, Serenade, View, WHITESPACE, assignUnlessEqual, capitalize, compile, def, defineEvent, defineOptions, defineProperty, extend, format, getValue, globalDependencies, idCounter, isArray, isArrayIndex, merge, normalize, pairToObject, safeDelete, safePush, serializeObject, settings, triggerGlobal,
358
358
  __hasProp = {}.hasOwnProperty,
359
359
  __slice = [].slice,
360
360
  __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; },
@@ -366,25 +366,54 @@ settings = {
366
366
 
367
367
  def = Object.defineProperty;
368
368
 
369
+ defineOptions = function(object, name) {
370
+ return def(object, name, {
371
+ get: function() {
372
+ var options;
373
+ if (!this.hasOwnProperty("_" + name)) {
374
+ options = name in Object.getPrototypeOf(this) ? Object.create(Object.getPrototypeOf(this)[name]) : {};
375
+ def(this, "_" + name, {
376
+ configurable: true,
377
+ writable: true,
378
+ value: options
379
+ });
380
+ }
381
+ return this["_" + name];
382
+ }
383
+ });
384
+ };
385
+
369
386
  extend = function(target, source, enumerable) {
370
- var key, value, _results;
387
+ var key, value;
371
388
  if (enumerable == null) {
372
389
  enumerable = true;
373
390
  }
374
- _results = [];
375
391
  for (key in source) {
376
392
  if (!__hasProp.call(source, key)) continue;
377
393
  value = source[key];
378
394
  if (enumerable) {
379
- _results.push(target[key] = value);
395
+ target[key] = value;
380
396
  } else {
381
- _results.push(def(target, key, {
397
+ def(target, key, {
382
398
  value: value,
383
399
  configurable: true
384
- }));
400
+ });
385
401
  }
386
402
  }
387
- return _results;
403
+ return target;
404
+ };
405
+
406
+ assignUnlessEqual = function(object, prop, value) {
407
+ if (object[prop] !== value) {
408
+ return object[prop] = value;
409
+ }
410
+ };
411
+
412
+ merge = function(target, source, enumerable) {
413
+ if (enumerable == null) {
414
+ enumerable = true;
415
+ }
416
+ return extend(extend({}, target, enumerable), source, enumerable);
388
417
  };
389
418
 
390
419
  format = function(model, key) {
@@ -460,11 +489,18 @@ Event = (function() {
460
489
  this.object = object;
461
490
  this.name = name;
462
491
  this.options = options;
463
- this.prop = "_s_" + this.name + "_listeners";
464
- this.queueName = "_s_" + name + "_queue";
465
- this.async = "async" in this.options ? this.options.async : settings.async;
466
492
  }
467
493
 
494
+ def(Event.prototype, "async", {
495
+ get: function() {
496
+ if ("async" in this.options) {
497
+ return this.options.async;
498
+ } else {
499
+ return settings.async;
500
+ }
501
+ }
502
+ });
503
+
468
504
  Event.prototype.trigger = function() {
469
505
  var args, _base,
470
506
  _this = this;
@@ -483,7 +519,7 @@ Event = (function() {
483
519
  if (this.options.bind) {
484
520
  this.options.bind.call(this.object, fun);
485
521
  }
486
- return safePush(this.object, this.prop, fun);
522
+ return safePush(this.object._s, "listeners_" + this.name, fun);
487
523
  };
488
524
 
489
525
  Event.prototype.one = function(fun) {
@@ -499,7 +535,7 @@ Event = (function() {
499
535
  };
500
536
 
501
537
  Event.prototype.unbind = function(fun) {
502
- safeDelete(this.object, this.prop, fun);
538
+ safeDelete(this.object._s, "listeners_" + this.name, fun);
503
539
  if (this.options.unbind) {
504
540
  return this.options.unbind.call(this.object, fun);
505
541
  }
@@ -509,9 +545,9 @@ Event = (function() {
509
545
  var args, perform, _i, _len, _ref,
510
546
  _this = this;
511
547
  perform = function(args) {
512
- if (_this.object[_this.prop]) {
513
- return _this.object[_this.prop].forEach(function(fun) {
514
- return fun.apply(_this.object, args);
548
+ if (_this.listeners) {
549
+ return _this.listeners.forEach(function(listener) {
550
+ return listener.apply(_this.object, args);
515
551
  });
516
552
  }
517
553
  };
@@ -529,22 +565,19 @@ Event = (function() {
529
565
 
530
566
  def(Event.prototype, "listeners", {
531
567
  get: function() {
532
- return this.object[this.prop];
568
+ return this.object._s["listeners_" + this.name];
533
569
  }
534
570
  });
535
571
 
536
572
  def(Event.prototype, "queue", {
537
573
  get: function() {
538
- if (!this.object.hasOwnProperty(this.queueName)) {
574
+ if (!this.object._s.hasOwnProperty("queue_" + this.name)) {
539
575
  this.queue = [];
540
576
  }
541
- return this.object[this.queueName];
577
+ return this.object._s["queue_" + this.name];
542
578
  },
543
579
  set: function(val) {
544
- return def(this.object, this.queueName, {
545
- value: val,
546
- configurable: true
547
- });
580
+ return this.object._s["queue_" + this.name] = val;
548
581
  }
549
582
  });
550
583
 
@@ -556,6 +589,9 @@ defineEvent = function(object, name, options) {
556
589
  if (options == null) {
557
590
  options = {};
558
591
  }
592
+ if (!("_s" in object)) {
593
+ defineOptions(object, "_s");
594
+ }
559
595
  return def(object, name, {
560
596
  configurable: true,
561
597
  get: function() {
@@ -703,13 +739,17 @@ Collection = (function() {
703
739
  }
704
740
  };
705
741
 
706
- Collection.prototype.first = function() {
707
- return this[0];
708
- };
742
+ def(Collection.prototype, "first", {
743
+ get: function() {
744
+ return this[0];
745
+ }
746
+ });
709
747
 
710
- Collection.prototype.last = function() {
711
- return this[this.length - 1];
712
- };
748
+ def(Collection.prototype, "last", {
749
+ get: function() {
750
+ return this[this.length - 1];
751
+ }
752
+ });
713
753
 
714
754
  Collection.prototype.toArray = function() {
715
755
  var array, index, val;
@@ -974,18 +1014,24 @@ PropertyDefinition = (function() {
974
1014
  this.addDependency(name);
975
1015
  }
976
1016
  }
977
- this.async = "async" in options ? options.async : settings.async;
978
- this.eventOptions = {
979
- async: this.async,
980
- bind: function() {
981
- return this[name];
982
- },
983
- optimize: function(queue) {
984
- return queue[queue.length - 1];
985
- }
986
- };
987
1017
  }
988
1018
 
1019
+ def(PropertyDefinition.prototype, "eventOptions", {
1020
+ get: function() {
1021
+ var name;
1022
+ name = this.name;
1023
+ return {
1024
+ async: this.async != null ? this.async : settings.async,
1025
+ bind: function() {
1026
+ return this[name];
1027
+ },
1028
+ optimize: function(queue) {
1029
+ return queue[queue.length - 1];
1030
+ }
1031
+ };
1032
+ }
1033
+ });
1034
+
989
1035
  PropertyDefinition.prototype.addDependency = function(name) {
990
1036
  var subname, type, _ref, _ref1;
991
1037
  if (this.dependencies.indexOf(name) === -1) {
@@ -1021,18 +1067,22 @@ PropertyAccessor = (function() {
1021
1067
  this.definition = definition;
1022
1068
  this.object = object;
1023
1069
  this.name = this.definition.name;
1024
- this.valueName = "_s_" + this.name + "_val";
1070
+ this.valueName = "val_" + this.name;
1025
1071
  this.event = new Event(this.object, this.name + "_change", this.definition.eventOptions);
1026
1072
  }
1027
1073
 
1028
1074
  PropertyAccessor.prototype.set = function(value) {
1075
+ var val;
1029
1076
  if (typeof value === "function") {
1030
1077
  return this.definition.get = value;
1031
1078
  } else {
1079
+ if (this.definition.changed) {
1080
+ val = this.get();
1081
+ }
1032
1082
  if (this.definition.set) {
1033
1083
  this.definition.set.call(this.object, value);
1034
1084
  } else {
1035
- def(this.object, this.valueName, {
1085
+ def(this.object._s, this.valueName, {
1036
1086
  value: value,
1037
1087
  configurable: true
1038
1088
  });
@@ -1045,21 +1095,24 @@ PropertyAccessor = (function() {
1045
1095
  var listener, value,
1046
1096
  _this = this;
1047
1097
  this.registerGlobal();
1048
- if (this.definition.get) {
1098
+ if (this.definition.get && !(this.definition.cache && this.valueName in this.object._s)) {
1049
1099
  listener = function(name) {
1050
1100
  return _this.definition.addDependency(name);
1051
1101
  };
1052
1102
  if (!("dependsOn" in this.definition)) {
1053
- this.object._s_property_access.bind(listener);
1103
+ this.object._s.property_access.bind(listener);
1054
1104
  }
1055
1105
  value = this.definition.get.call(this.object);
1106
+ if (this.definition.cache) {
1107
+ this.object._s[this.valueName] = value;
1108
+ }
1056
1109
  if (!("dependsOn" in this.definition)) {
1057
- this.object._s_property_access.unbind(listener);
1110
+ this.object._s.property_access.unbind(listener);
1058
1111
  }
1059
1112
  } else {
1060
- value = this.object[this.valueName];
1113
+ value = this.object._s[this.valueName];
1061
1114
  }
1062
- this.object._s_property_access.trigger(this.name);
1115
+ this.object._s.property_access.trigger(this.name);
1063
1116
  return value;
1064
1117
  };
1065
1118
 
@@ -1073,11 +1126,8 @@ PropertyAccessor = (function() {
1073
1126
 
1074
1127
  PropertyAccessor.prototype.registerGlobal = function() {
1075
1128
  var name, subname, type, _i, _len, _ref, _ref1, _results;
1076
- if (!this.object["_s_glb_" + this.name]) {
1077
- def(this.object, "_s_glb_" + this.name, {
1078
- value: true,
1079
- configurable: true
1080
- });
1129
+ if (!this.object._s["glb_" + this.name]) {
1130
+ this.object._s["glb_" + this.name] = true;
1081
1131
  _ref = this.definition.globalDependencies;
1082
1132
  _results = [];
1083
1133
  for (_i = 0, _len = _ref.length; _i < _len; _i++) {
@@ -1096,26 +1146,36 @@ PropertyAccessor = (function() {
1096
1146
  };
1097
1147
 
1098
1148
  PropertyAccessor.prototype.trigger = function() {
1099
- var changes, name, names, value, _i, _len, _ref, _results;
1100
- names = [this.name].concat(this.dependents);
1101
- changes = {};
1102
- for (_i = 0, _len = names.length; _i < _len; _i++) {
1103
- name = names[_i];
1104
- changes[name] = this.object[name];
1105
- }
1106
- if ((_ref = this.object.changed) != null) {
1107
- if (typeof _ref.trigger === "function") {
1108
- _ref.trigger(changes);
1149
+ var changes, name, prop, value, _i, _len, _ref, _ref1;
1150
+ this.clearCache();
1151
+ if (this.hasChanged()) {
1152
+ value = this.get();
1153
+ changes = {};
1154
+ _ref = this.dependents;
1155
+ for (_i = 0, _len = _ref.length; _i < _len; _i++) {
1156
+ name = _ref[_i];
1157
+ if (name !== this.name) {
1158
+ changes[name] = this.object[name];
1159
+ }
1109
1160
  }
1161
+ this.event.trigger(value);
1162
+ for (name in changes) {
1163
+ if (!__hasProp.call(changes, name)) continue;
1164
+ value = changes[name];
1165
+ prop = this.object[name + "_property"];
1166
+ prop.clearCache();
1167
+ if (prop.hasChanged()) {
1168
+ prop.event.trigger(value);
1169
+ }
1170
+ }
1171
+ changes[this.name] = value;
1172
+ if ((_ref1 = this.object.changed) != null) {
1173
+ if (typeof _ref1.trigger === "function") {
1174
+ _ref1.trigger(changes);
1175
+ }
1176
+ }
1177
+ return triggerGlobal(this.object, Object.keys(changes));
1110
1178
  }
1111
- triggerGlobal(this.object, names);
1112
- _results = [];
1113
- for (name in changes) {
1114
- if (!__hasProp.call(changes, name)) continue;
1115
- value = changes[name];
1116
- _results.push(this.object[name + "_property"].event.trigger(value));
1117
- }
1118
- return _results;
1119
1179
  };
1120
1180
 
1121
1181
  PropertyAccessor.prototype.bind = function(fun) {
@@ -1137,7 +1197,7 @@ PropertyAccessor = (function() {
1137
1197
  deps = [];
1138
1198
  findDependencies = function(name) {
1139
1199
  var property, _i, _len, _ref, _ref1, _results;
1140
- _ref = _this.object._s_properties;
1200
+ _ref = _this.object._s.properties;
1141
1201
  _results = [];
1142
1202
  for (_i = 0, _len = _ref.length; _i < _len; _i++) {
1143
1203
  property = _ref[_i];
@@ -1161,6 +1221,27 @@ PropertyAccessor = (function() {
1161
1221
  }
1162
1222
  });
1163
1223
 
1224
+ PropertyAccessor.prototype.clearCache = function() {
1225
+ if (this.definition.cache && this.definition.get) {
1226
+ return delete this.object._s[this.valueName];
1227
+ }
1228
+ };
1229
+
1230
+ PropertyAccessor.prototype.hasChanged = function() {
1231
+ var changed, oldValueName, value;
1232
+ if (this.definition.changed === false) {
1233
+ return false;
1234
+ } else if (this.definition.changed) {
1235
+ value = this.get();
1236
+ oldValueName = "old_val_" + this.name;
1237
+ changed = this.object._s.hasOwnProperty(oldValueName) ? this.definition.changed.call(this.object, this.object._s[oldValueName], value) : true;
1238
+ this.object._s[oldValueName] = value;
1239
+ return changed;
1240
+ } else {
1241
+ return true;
1242
+ }
1243
+ };
1244
+
1164
1245
  return PropertyAccessor;
1165
1246
 
1166
1247
  })();
@@ -1171,8 +1252,11 @@ defineProperty = function(object, name, options) {
1171
1252
  options = {};
1172
1253
  }
1173
1254
  definition = new PropertyDefinition(name, options);
1174
- safePush(object, "_s_properties", definition);
1175
- defineEvent(object, "_s_property_access");
1255
+ if (!("_s" in object)) {
1256
+ defineOptions(object, "_s");
1257
+ }
1258
+ safePush(object._s, "properties", definition);
1259
+ defineEvent(object._s, "property_access");
1176
1260
  def(object, name, {
1177
1261
  get: function() {
1178
1262
  return this[name + "_property"].get();
@@ -1209,30 +1293,6 @@ idCounter = 1;
1209
1293
 
1210
1294
  Model = (function() {
1211
1295
 
1212
- defineEvent(Model.prototype, "saved");
1213
-
1214
- defineEvent(Model.prototype, "changed", {
1215
- optimize: function(queue) {
1216
- var item, result, _i, _len;
1217
- result = {};
1218
- for (_i = 0, _len = queue.length; _i < _len; _i++) {
1219
- item = queue[_i];
1220
- extend(result, item[0]);
1221
- }
1222
- return [result];
1223
- }
1224
- });
1225
-
1226
- Model.belongsTo = function() {
1227
- var _ref;
1228
- return (_ref = this.prototype).belongsTo.apply(_ref, arguments);
1229
- };
1230
-
1231
- Model.hasMany = function() {
1232
- var _ref;
1233
- return (_ref = this.prototype).hasMany.apply(_ref, arguments);
1234
- };
1235
-
1236
1296
  Model.identityMap = true;
1237
1297
 
1238
1298
  Model.find = function(id) {
@@ -1278,15 +1338,8 @@ Model = (function() {
1278
1338
  return _results;
1279
1339
  };
1280
1340
 
1281
- Model.properties = function() {
1282
- var name, names, _i, _len, _results;
1283
- names = 1 <= arguments.length ? __slice.call(arguments, 0) : [];
1284
- _results = [];
1285
- for (_i = 0, _len = names.length; _i < _len; _i++) {
1286
- name = names[_i];
1287
- _results.push(this.property(name));
1288
- }
1289
- return _results;
1341
+ Model.event = function(name, options) {
1342
+ return defineEvent(this.prototype, name, options);
1290
1343
  };
1291
1344
 
1292
1345
  Model.delegate = function() {
@@ -1295,7 +1348,7 @@ Model = (function() {
1295
1348
  names = 2 <= arguments.length ? __slice.call(arguments, 0, _i = arguments.length - 1) : (_i = 0, []), options = arguments[_i++];
1296
1349
  to = options.to;
1297
1350
  return names.forEach(function(name) {
1298
- var propName;
1351
+ var propName, propOptions;
1299
1352
  propName = name;
1300
1353
  if (options.prefix === true) {
1301
1354
  propName = to + capitalize(name);
@@ -1307,8 +1360,8 @@ Model = (function() {
1307
1360
  } else if (options.suffix) {
1308
1361
  propName = propName + options.suffix;
1309
1362
  }
1310
- return _this.property(propName, {
1311
- dependsOn: "" + to + "." + name,
1363
+ propOptions = merge(options, {
1364
+ dependsOn: options.dependsOn || ("" + to + "." + name),
1312
1365
  get: function() {
1313
1366
  var _ref;
1314
1367
  return (_ref = this[to]) != null ? _ref[name] : void 0;
@@ -1318,31 +1371,33 @@ Model = (function() {
1318
1371
  return (_ref = this[to]) != null ? _ref[name] = value : void 0;
1319
1372
  }
1320
1373
  });
1374
+ return _this.property(propName, propOptions);
1321
1375
  });
1322
1376
  };
1323
1377
 
1324
1378
  Model.collection = function(name, options) {
1379
+ var propOptions;
1325
1380
  if (options == null) {
1326
1381
  options = {};
1327
1382
  }
1328
- extend(options, {
1383
+ propOptions = merge(options, {
1329
1384
  get: function() {
1330
1385
  var valueName,
1331
1386
  _this = this;
1332
- valueName = "_s_" + name + "_val";
1333
- if (!this[valueName]) {
1334
- this[valueName] = new Collection([]);
1335
- this[valueName].change.bind(function() {
1387
+ valueName = "val_" + name;
1388
+ if (!this._s[valueName]) {
1389
+ this._s[valueName] = new Collection([]);
1390
+ this._s[valueName].change.bind(function() {
1336
1391
  return _this[name + "_property"].trigger();
1337
1392
  });
1338
1393
  }
1339
- return this[valueName];
1394
+ return this._s[valueName];
1340
1395
  },
1341
1396
  set: function(value) {
1342
1397
  return this[name].update(value);
1343
1398
  }
1344
1399
  });
1345
- this.property(name, options);
1400
+ this.property(name, propOptions);
1346
1401
  return this.property(name + 'Count', {
1347
1402
  get: function() {
1348
1403
  return this[name].length;
@@ -1351,28 +1406,29 @@ Model = (function() {
1351
1406
  });
1352
1407
  };
1353
1408
 
1354
- Model.belongsTo = function(name, attributes) {
1355
- if (attributes == null) {
1356
- attributes = {};
1409
+ Model.belongsTo = function(name, options) {
1410
+ var propOptions;
1411
+ if (options == null) {
1412
+ options = {};
1357
1413
  }
1358
- extend(attributes, {
1414
+ propOptions = merge(options, {
1359
1415
  set: function(model) {
1360
1416
  var previous, valueName;
1361
- valueName = "_s_" + name + "_val";
1362
- if (model && model.constructor === Object && attributes.as) {
1363
- model = new (attributes.as())(model);
1417
+ valueName = "val_" + name;
1418
+ if (model && model.constructor === Object && options.as) {
1419
+ model = new (options.as())(model);
1364
1420
  }
1365
- previous = this[valueName];
1366
- this[valueName] = model;
1367
- if (attributes.inverseOf && !model[attributes.inverseOf].includes(this)) {
1421
+ previous = this._s[valueName];
1422
+ this._s[valueName] = model;
1423
+ if (options.inverseOf && !model[options.inverseOf].includes(this)) {
1368
1424
  if (previous) {
1369
- previous[attributes.inverseOf]["delete"](this);
1425
+ previous[options.inverseOf]["delete"](this);
1370
1426
  }
1371
- return model[attributes.inverseOf].push(this);
1427
+ return model[options.inverseOf].push(this);
1372
1428
  }
1373
1429
  }
1374
1430
  });
1375
- this.property(name, attributes);
1431
+ this.property(name, propOptions);
1376
1432
  return this.property(name + 'Id', {
1377
1433
  get: function() {
1378
1434
  var _ref;
@@ -1380,36 +1436,37 @@ Model = (function() {
1380
1436
  },
1381
1437
  set: function(id) {
1382
1438
  if (id != null) {
1383
- return this[name] = attributes.as().find(id);
1439
+ return this[name] = options.as().find(id);
1384
1440
  }
1385
1441
  },
1386
1442
  dependsOn: name,
1387
- serialize: attributes.serializeId
1443
+ serialize: options.serializeId
1388
1444
  });
1389
1445
  };
1390
1446
 
1391
- Model.hasMany = function(name, attributes) {
1392
- if (attributes == null) {
1393
- attributes = {};
1447
+ Model.hasMany = function(name, options) {
1448
+ var propOptions;
1449
+ if (options == null) {
1450
+ options = {};
1394
1451
  }
1395
- extend(attributes, {
1452
+ propOptions = merge(options, {
1396
1453
  get: function() {
1397
1454
  var valueName,
1398
1455
  _this = this;
1399
- valueName = "_s_" + name + "_val";
1400
- if (!this[valueName]) {
1401
- this[valueName] = new AssociationCollection(this, attributes, []);
1402
- this[valueName].change.bind(function() {
1456
+ valueName = "val_" + name;
1457
+ if (!this._s[valueName]) {
1458
+ this._s[valueName] = new AssociationCollection(this, options, []);
1459
+ this._s[valueName].change.bind(function() {
1403
1460
  return _this[name + "_property"].trigger();
1404
1461
  });
1405
1462
  }
1406
- return this[valueName];
1463
+ return this._s[valueName];
1407
1464
  },
1408
1465
  set: function(value) {
1409
1466
  return this[name].update(value);
1410
1467
  }
1411
1468
  });
1412
- this.property(name, attributes);
1469
+ this.property(name, propOptions);
1413
1470
  this.property(name + 'Ids', {
1414
1471
  get: function() {
1415
1472
  return new Collection(this[name]).map(function(item) {
@@ -1423,14 +1480,14 @@ Model = (function() {
1423
1480
  _results = [];
1424
1481
  for (_i = 0, _len = ids.length; _i < _len; _i++) {
1425
1482
  id = ids[_i];
1426
- _results.push(attributes.as().find(id));
1483
+ _results.push(options.as().find(id));
1427
1484
  }
1428
1485
  return _results;
1429
1486
  })();
1430
1487
  return this[name].update(objects);
1431
1488
  },
1432
1489
  dependsOn: name,
1433
- serialize: attributes.serializeIds
1490
+ serialize: options.serializeIds
1434
1491
  });
1435
1492
  return this.property(name + 'Count', {
1436
1493
  get: function() {
@@ -1441,10 +1498,11 @@ Model = (function() {
1441
1498
  };
1442
1499
 
1443
1500
  Model.selection = function(name, options) {
1501
+ var propOptions;
1444
1502
  if (options == null) {
1445
1503
  options = {};
1446
1504
  }
1447
- this.property(name, {
1505
+ propOptions = merge(options, {
1448
1506
  get: function() {
1449
1507
  return this[options.from].filter(function(item) {
1450
1508
  return item[options.filter];
@@ -1452,6 +1510,7 @@ Model = (function() {
1452
1510
  },
1453
1511
  dependsOn: "" + options.from + ":" + options.filter
1454
1512
  });
1513
+ this.property(name, propOptions);
1455
1514
  return this.property(name + 'Count', {
1456
1515
  get: function() {
1457
1516
  return this[name].length;
@@ -1473,13 +1532,24 @@ Model = (function() {
1473
1532
  set: function(val) {
1474
1533
  Cache.unset(this.constructor, this.id);
1475
1534
  Cache.set(this.constructor, val, this);
1476
- return def(this, "_s_id_val", {
1477
- value: val,
1478
- configurable: true
1479
- });
1535
+ return this._s.val_id = val;
1480
1536
  },
1481
1537
  get: function() {
1482
- return this._s_id_val;
1538
+ return this._s.val_id;
1539
+ }
1540
+ });
1541
+
1542
+ Model.event("saved");
1543
+
1544
+ Model.event("changed", {
1545
+ optimize: function(queue) {
1546
+ var item, result, _i, _len;
1547
+ result = {};
1548
+ for (_i = 0, _len = queue.length; _i < _len; _i++) {
1549
+ item = queue[_i];
1550
+ extend(result, item[0]);
1551
+ }
1552
+ return [result];
1483
1553
  }
1484
1554
  });
1485
1555
 
@@ -1518,7 +1588,7 @@ Model = (function() {
1518
1588
  Model.prototype.toJSON = function() {
1519
1589
  var key, property, serialized, value, _i, _len, _ref, _ref1;
1520
1590
  serialized = {};
1521
- _ref = this._s_properties;
1591
+ _ref = this._s.properties;
1522
1592
  for (_i = 0, _len = _ref.length; _i < _len; _i++) {
1523
1593
  property = _ref[_i];
1524
1594
  if (typeof property.serialize === 'string') {
@@ -1748,9 +1818,12 @@ Node = (function() {
1748
1818
  return (_ref = this.element.parentNode) != null ? _ref.removeChild(this.element) : void 0;
1749
1819
  };
1750
1820
 
1751
- Node.prototype.lastElement = function() {
1752
- return this.element;
1753
- };
1821
+ def(Node.prototype, "lastElement", {
1822
+ configurable: true,
1823
+ get: function() {
1824
+ return this.element;
1825
+ }
1826
+ });
1754
1827
 
1755
1828
  Node.prototype.nodes = function() {
1756
1829
  return this.children;
@@ -1795,8 +1868,9 @@ Node = (function() {
1795
1868
  if (this.boundClasses.length) {
1796
1869
  classes = classes.concat(this.boundClasses.toArray());
1797
1870
  }
1871
+ classes.sort();
1798
1872
  if (classes.length) {
1799
- return this.element.className = classes.join(' ');
1873
+ return assignUnlessEqual(this.element, "className", classes.join(' '));
1800
1874
  } else {
1801
1875
  return this.element.removeAttribute("class");
1802
1876
  }
@@ -1839,7 +1913,7 @@ DynamicNode = (function(_super) {
1839
1913
  for (_i = 0, _len = _ref.length; _i < _len; _i++) {
1840
1914
  node = _ref[_i];
1841
1915
  node.insertAfter(last);
1842
- _results.push(last = node.lastElement());
1916
+ _results.push(last = node.lastElement);
1843
1917
  }
1844
1918
  return _results;
1845
1919
  }
@@ -1876,11 +1950,11 @@ DynamicNode = (function(_super) {
1876
1950
 
1877
1951
  DynamicNode.prototype.insertNodeSet = function(index, nodes) {
1878
1952
  var last, node, _i, _len, _ref, _ref1;
1879
- last = ((_ref = this.nodeSets[index - 1]) != null ? (_ref1 = _ref.last()) != null ? _ref1.lastElement() : void 0 : void 0) || this.anchor;
1953
+ last = ((_ref = this.nodeSets[index - 1]) != null ? (_ref1 = _ref.last) != null ? _ref1.lastElement : void 0 : void 0) || this.anchor;
1880
1954
  for (_i = 0, _len = nodes.length; _i < _len; _i++) {
1881
1955
  node = nodes[_i];
1882
1956
  node.insertAfter(last);
1883
- last = node.lastElement();
1957
+ last = node.lastElement;
1884
1958
  }
1885
1959
  return this.nodeSets.insertAt(index, new Collection(nodes));
1886
1960
  };
@@ -1911,10 +1985,13 @@ DynamicNode = (function(_super) {
1911
1985
  return this.rebuild();
1912
1986
  };
1913
1987
 
1914
- DynamicNode.prototype.lastElement = function() {
1915
- var _ref, _ref1;
1916
- return ((_ref = this.nodeSets.last()) != null ? (_ref1 = _ref.last()) != null ? _ref1.lastElement() : void 0 : void 0) || this.anchor;
1917
- };
1988
+ def(DynamicNode.prototype, "lastElement", {
1989
+ configurable: true,
1990
+ get: function() {
1991
+ var _ref, _ref1;
1992
+ return ((_ref = this.nodeSets.last) != null ? (_ref1 = _ref.last) != null ? _ref1.lastElement : void 0 : void 0) || this.anchor;
1993
+ }
1994
+ });
1918
1995
 
1919
1996
  return DynamicNode;
1920
1997
 
@@ -1934,7 +2011,7 @@ Property = {
1934
2011
  style: function(ast, node, model, controller) {
1935
2012
  var update;
1936
2013
  update = function() {
1937
- return node.element.style[ast.name] = getValue(ast, model);
2014
+ return assignUnlessEqual(node.element.style, ast.name, getValue(ast, model));
1938
2015
  };
1939
2016
  update();
1940
2017
  if (ast.bound) {
@@ -1953,7 +2030,9 @@ Property = {
1953
2030
  var update;
1954
2031
  update = function() {
1955
2032
  if (model[ast.value]) {
1956
- node.boundClasses.push(ast.name);
2033
+ if (!node.boundClasses.includes(ast.name)) {
2034
+ node.boundClasses.push(ast.name);
2035
+ }
1957
2036
  } else {
1958
2037
  node.boundClasses["delete"](ast.name);
1959
2038
  }
@@ -1987,9 +2066,7 @@ Property = {
1987
2066
  if (val === void 0) {
1988
2067
  val = "";
1989
2068
  }
1990
- if (element.value !== val) {
1991
- return element.value = val;
1992
- }
2069
+ return assignUnlessEqual(element, "value", val);
1993
2070
  }
1994
2071
  };
1995
2072
  modelUpdated();
@@ -2018,19 +2095,23 @@ Property = {
2018
2095
  var value;
2019
2096
  value = getValue(ast, model);
2020
2097
  if (ast.name === 'value') {
2021
- return element.value = value || '';
2098
+ return assignUnlessEqual(element, "value", value || '');
2022
2099
  } else if (node.ast.name === 'input' && ast.name === 'checked') {
2023
- return element.checked = !!value;
2100
+ return assignUnlessEqual(element, "checked", !!value);
2024
2101
  } else if (ast.name === 'class') {
2025
2102
  node.attributeClasses = value;
2026
2103
  return node.updateClass();
2027
2104
  } else if (value === void 0) {
2028
- return element.removeAttribute(ast.name);
2105
+ if (element.hasAttribute(ast.name)) {
2106
+ return element.removeAttribute(ast.name);
2107
+ }
2029
2108
  } else {
2030
2109
  if (value === 0) {
2031
2110
  value = "0";
2032
2111
  }
2033
- return element.setAttribute(ast.name, value);
2112
+ if (element.getAttribute(ast.name) !== value) {
2113
+ return element.setAttribute(ast.name, value);
2114
+ }
2034
2115
  }
2035
2116
  };
2036
2117
  if (ast.bound) {
@@ -2052,7 +2133,7 @@ Property = {
2052
2133
 
2053
2134
  Compile = {
2054
2135
  element: function(ast, model, controller) {
2055
- var action, child, childNode, element, node, property, _i, _j, _len, _len1, _ref, _ref1, _ref2;
2136
+ var action, child, element, node, property, _i, _j, _len, _len1, _ref, _ref1, _ref2;
2056
2137
  element = Serenade.document.createElement(ast.name);
2057
2138
  node = new Node(ast, element);
2058
2139
  if (ast.id) {
@@ -2061,12 +2142,11 @@ Compile = {
2061
2142
  if ((_ref = ast.classes) != null ? _ref.length : void 0) {
2062
2143
  element.setAttribute('class', ast.classes.join(' '));
2063
2144
  }
2064
- _ref1 = ast.children;
2145
+ node.children = compile(ast.children, model, controller);
2146
+ _ref1 = node.children;
2065
2147
  for (_i = 0, _len = _ref1.length; _i < _len; _i++) {
2066
2148
  child = _ref1[_i];
2067
- childNode = compile(child, model, controller);
2068
- childNode.append(element);
2069
- node.children.push(childNode);
2149
+ child.append(element);
2070
2150
  }
2071
2151
  _ref2 = ast.properties;
2072
2152
  for (_j = 0, _len1 = _ref2.length; _j < _len1; _j++) {
@@ -2082,19 +2162,21 @@ Compile = {
2082
2162
  return node;
2083
2163
  },
2084
2164
  view: function(ast, model, parent) {
2085
- var controller, skipCallback;
2165
+ var controller, dynamic, skipCallback;
2086
2166
  controller = Serenade.controllerFor(ast.argument);
2087
2167
  if (!controller) {
2088
2168
  skipCallback = true;
2089
2169
  controller = parent;
2090
2170
  }
2091
- return Serenade._views[ast.argument].node(model, controller, parent, skipCallback);
2171
+ dynamic = new DynamicNode(ast);
2172
+ dynamic.replace([Serenade._views[ast.argument].nodes(model, controller, parent, skipCallback)]);
2173
+ return dynamic;
2092
2174
  },
2093
2175
  helper: function(ast, model, controller) {
2094
2176
  var argument, context, dynamic, helperFunction, render, update, _i, _len, _ref;
2095
2177
  dynamic = new DynamicNode(ast);
2096
2178
  render = function(model, controller) {
2097
- var child, fragment, node, _i, _len, _ref;
2179
+ var child, children, fragment, _i, _len;
2098
2180
  if (model == null) {
2099
2181
  model = model;
2100
2182
  }
@@ -2102,11 +2184,10 @@ Compile = {
2102
2184
  controller = controller;
2103
2185
  }
2104
2186
  fragment = Serenade.document.createDocumentFragment();
2105
- _ref = ast.children;
2106
- for (_i = 0, _len = _ref.length; _i < _len; _i++) {
2107
- child = _ref[_i];
2108
- node = compile(child, model, controller);
2109
- node.append(fragment);
2187
+ children = compile(ast.children, model, controller);
2188
+ for (_i = 0, _len = children.length; _i < _len; _i++) {
2189
+ child = children[_i];
2190
+ child.append(fragment);
2110
2191
  }
2111
2192
  return fragment;
2112
2193
  };
@@ -2163,7 +2244,7 @@ Compile = {
2163
2244
  node = new Node(ast, textNode);
2164
2245
  if (ast.bound) {
2165
2246
  node.bindEvent(model["" + ast.value + "_property"], function() {
2166
- return textNode.nodeValue = getText();
2247
+ return assignUnlessEqual(textNode, "nodeValue", getText());
2167
2248
  });
2168
2249
  }
2169
2250
  return node;
@@ -2172,7 +2253,7 @@ Compile = {
2172
2253
  var collection, compileItem, dynamic, update,
2173
2254
  _this = this;
2174
2255
  compileItem = function(item) {
2175
- return compileAll(ast.children, item, controller);
2256
+ return compile(ast.children, item, controller);
2176
2257
  };
2177
2258
  update = function(dynamic, collection) {
2178
2259
  var item;
@@ -2226,7 +2307,7 @@ Compile = {
2226
2307
  "in": function(ast, model, controller) {
2227
2308
  return this.bound(ast, model, controller, function(dynamic, value) {
2228
2309
  if (value) {
2229
- return dynamic.replace([compileAll(ast.children, value, controller)]);
2310
+ return dynamic.replace([compile(ast.children, value, controller)]);
2230
2311
  } else {
2231
2312
  return dynamic.clear();
2232
2313
  }
@@ -2235,9 +2316,9 @@ Compile = {
2235
2316
  "if": function(ast, model, controller) {
2236
2317
  return this.bound(ast, model, controller, function(dynamic, value) {
2237
2318
  if (value) {
2238
- return dynamic.replace([compileAll(ast.children, model, controller)]);
2319
+ return dynamic.replace([compile(ast.children, model, controller)]);
2239
2320
  } else if (ast["else"]) {
2240
- return dynamic.replace([compileAll(ast["else"].children, model, controller)]);
2321
+ return dynamic.replace([compile(ast["else"].children, model, controller)]);
2241
2322
  } else {
2242
2323
  return dynamic.clear();
2243
2324
  }
@@ -2245,31 +2326,26 @@ Compile = {
2245
2326
  },
2246
2327
  unless: function(ast, model, controller) {
2247
2328
  return this.bound(ast, model, controller, function(dynamic, value) {
2248
- var child, nodes;
2329
+ var nodes;
2249
2330
  if (value) {
2250
2331
  return dynamic.clear();
2251
2332
  } else {
2252
- nodes = (function() {
2253
- var _i, _len, _ref, _results;
2254
- _ref = ast.children;
2255
- _results = [];
2256
- for (_i = 0, _len = _ref.length; _i < _len; _i++) {
2257
- child = _ref[_i];
2258
- _results.push(compile(child, model, controller));
2259
- }
2260
- return _results;
2261
- })();
2333
+ nodes = compile(ast.children, model, controller);
2262
2334
  return dynamic.replace([nodes]);
2263
2335
  }
2264
2336
  });
2265
2337
  },
2266
2338
  bound: function(ast, model, controller, callback) {
2267
- var dynamic, update;
2339
+ var dynamic, lastValue, update;
2268
2340
  dynamic = new DynamicNode(ast);
2341
+ lastValue = {};
2269
2342
  update = function() {
2270
2343
  var value;
2271
2344
  value = model[ast.argument];
2272
- return callback(dynamic, value);
2345
+ if (value !== lastValue) {
2346
+ callback(dynamic, value);
2347
+ }
2348
+ return lastValue = value;
2273
2349
  };
2274
2350
  update();
2275
2351
  dynamic.bindEvent(model["" + ast.argument + "_property"], update);
@@ -2283,7 +2359,7 @@ normalize = function(val) {
2283
2359
  return [];
2284
2360
  }
2285
2361
  reduction = function(aggregate, element) {
2286
- var child, div, _i, _len, _ref;
2362
+ var child, div, _i, _j, _len, _len1, _ref, _ref1;
2287
2363
  if (typeof element === "string") {
2288
2364
  div = Serenade.document.createElement("div");
2289
2365
  div.innerHTML = element;
@@ -2292,6 +2368,12 @@ normalize = function(val) {
2292
2368
  child = _ref[_i];
2293
2369
  aggregate.push(child);
2294
2370
  }
2371
+ } else if (element.nodeName === "#document-fragment") {
2372
+ _ref1 = element.childNodes;
2373
+ for (_j = 0, _len1 = _ref1.length; _j < _len1; _j++) {
2374
+ child = _ref1[_j];
2375
+ aggregate.push(child);
2376
+ }
2295
2377
  } else {
2296
2378
  aggregate.push(element);
2297
2379
  }
@@ -2300,16 +2382,12 @@ normalize = function(val) {
2300
2382
  return [].concat(val).reduce(reduction, []);
2301
2383
  };
2302
2384
 
2303
- compile = function(ast, model, controller) {
2304
- return Compile[ast.type](ast, model, controller);
2305
- };
2306
-
2307
- compileAll = function(asts, model, controller) {
2385
+ compile = function(asts, model, controller) {
2308
2386
  var ast, _i, _len, _results;
2309
2387
  _results = [];
2310
2388
  for (_i = 0, _len = asts.length; _i < _len; _i++) {
2311
2389
  ast = asts[_i];
2312
- _results.push(compile(ast, model, controller));
2390
+ _results.push(Compile[ast.type](ast, model, controller));
2313
2391
  }
2314
2392
  return _results;
2315
2393
  };
@@ -2329,6 +2407,41 @@ parser.lexer = {
2329
2407
  }
2330
2408
  };
2331
2409
 
2410
+ CompiledView = (function() {
2411
+
2412
+ function CompiledView(nodes) {
2413
+ this.nodes = nodes;
2414
+ }
2415
+
2416
+ CompiledView.prototype.remove = function() {
2417
+ var node, _i, _len, _ref, _results;
2418
+ _ref = this.nodes;
2419
+ _results = [];
2420
+ for (_i = 0, _len = _ref.length; _i < _len; _i++) {
2421
+ node = _ref[_i];
2422
+ _results.push(node.remove());
2423
+ }
2424
+ return _results;
2425
+ };
2426
+
2427
+ def(CompiledView.prototype, "fragment", {
2428
+ enumerable: true,
2429
+ get: function() {
2430
+ var fragment, node, _i, _len, _ref;
2431
+ fragment = Serenade.document.createDocumentFragment();
2432
+ _ref = this.nodes;
2433
+ for (_i = 0, _len = _ref.length; _i < _len; _i++) {
2434
+ node = _ref[_i];
2435
+ node.append(fragment);
2436
+ }
2437
+ return fragment;
2438
+ }
2439
+ });
2440
+
2441
+ return CompiledView;
2442
+
2443
+ })();
2444
+
2332
2445
  View = (function() {
2333
2446
 
2334
2447
  function View(name, view) {
@@ -2354,11 +2467,11 @@ View = (function() {
2354
2467
  View.prototype.render = function() {
2355
2468
  var args;
2356
2469
  args = 1 <= arguments.length ? __slice.call(arguments, 0) : [];
2357
- return this.node.apply(this, args).element;
2470
+ return this.compile.apply(this, args).fragment;
2358
2471
  };
2359
2472
 
2360
- View.prototype.node = function(model, controller, parent, skipCallback) {
2361
- var node;
2473
+ View.prototype.nodes = function(model, controller, parent, skipCallback) {
2474
+ var nodes;
2362
2475
  if (this.name) {
2363
2476
  controller || (controller = Serenade.controllerFor(this.name, model));
2364
2477
  }
@@ -2366,13 +2479,21 @@ View = (function() {
2366
2479
  if (typeof controller === "function") {
2367
2480
  controller = new controller(model, parent);
2368
2481
  }
2369
- node = compile(this.parse(), model, controller);
2482
+ nodes = compile(this.parse(), model, controller);
2370
2483
  if (!skipCallback) {
2371
2484
  if (typeof controller.loaded === "function") {
2372
- controller.loaded(node.element, model);
2485
+ controller.loaded.apply(controller, __slice.call(nodes.map(function(node) {
2486
+ return node.element;
2487
+ })).concat([model]));
2373
2488
  }
2374
2489
  }
2375
- return node;
2490
+ return nodes;
2491
+ };
2492
+
2493
+ View.prototype.compile = function() {
2494
+ var args;
2495
+ args = 1 <= arguments.length ? __slice.call(arguments, 0) : [];
2496
+ return new CompiledView(this.nodes.apply(this, args));
2376
2497
  };
2377
2498
 
2378
2499
  return View;
@@ -2392,7 +2513,7 @@ Serenade = function(wrapped) {
2392
2513
  };
2393
2514
 
2394
2515
  extend(Serenade, {
2395
- VERSION: '0.4.0',
2516
+ VERSION: '0.4.1',
2396
2517
  _views: {},
2397
2518
  _controllers: {},
2398
2519
  document: typeof window !== "undefined" && window !== null ? window.document : void 0,
@@ -2419,13 +2540,9 @@ extend(Serenade, {
2419
2540
  clearIdentityMap: function() {
2420
2541
  return Cache._identityMap = {};
2421
2542
  },
2422
- clearLocalStorage: function() {
2423
- return Cache._storage.clear();
2424
- },
2425
2543
  clearCache: function() {
2426
2544
  var key, value, _i, _len, _results;
2427
2545
  Serenade.clearIdentityMap();
2428
- Serenade.clearLocalStorage();
2429
2546
  _results = [];
2430
2547
  for (key = _i = 0, _len = globalDependencies.length; _i < _len; key = ++_i) {
2431
2548
  value = globalDependencies[key];
@@ -1,4 +1,4 @@
1
1
  module Serenade
2
2
  # Serenade.js version this gem is bundled with.
3
- VERSION = "0.4.0"
3
+ VERSION = "0.4.1"
4
4
  end
@@ -6,7 +6,7 @@ describe Serenade do
6
6
  describe Serenade::Renderer do
7
7
  describe "#parse" do
8
8
  it "returns a parsed Sereande template" do
9
- result = Serenade::Renderer.new("foo", 'h1 "Hello world"').parse
9
+ result = Serenade::Renderer.new("foo", 'h1 "Hello world"').parse[0]
10
10
  result["name"].should eq "h1"
11
11
  result["children"][0]["type"].should eq "text"
12
12
  result["children"][0]["value"].should eq "Hello world"
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: serenade
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.0
4
+ version: 0.4.1
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -10,88 +10,88 @@ authors:
10
10
  autorequire:
11
11
  bindir: bin
12
12
  cert_chain: []
13
- date: 2013-01-15 00:00:00.000000000 Z
13
+ date: 2013-02-08 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: execjs
17
- prerelease: false
18
17
  requirement: !ruby/object:Gem::Requirement
18
+ none: false
19
19
  requirements:
20
20
  - - ! '>='
21
21
  - !ruby/object:Gem::Version
22
22
  version: 0.3.0
23
- none: false
24
23
  type: :runtime
24
+ prerelease: false
25
25
  version_requirements: !ruby/object:Gem::Requirement
26
+ none: false
26
27
  requirements:
27
28
  - - ! '>='
28
29
  - !ruby/object:Gem::Version
29
30
  version: 0.3.0
30
- none: false
31
31
  - !ruby/object:Gem::Dependency
32
32
  name: multi_json
33
- prerelease: false
34
33
  requirement: !ruby/object:Gem::Requirement
34
+ none: false
35
35
  requirements:
36
36
  - - ! '>='
37
37
  - !ruby/object:Gem::Version
38
38
  version: '0'
39
- none: false
40
39
  type: :runtime
40
+ prerelease: false
41
41
  version_requirements: !ruby/object:Gem::Requirement
42
+ none: false
42
43
  requirements:
43
44
  - - ! '>='
44
45
  - !ruby/object:Gem::Version
45
46
  version: '0'
46
- none: false
47
47
  - !ruby/object:Gem::Dependency
48
48
  name: rspec
49
- prerelease: false
50
49
  requirement: !ruby/object:Gem::Requirement
50
+ none: false
51
51
  requirements:
52
52
  - - ~>
53
53
  - !ruby/object:Gem::Version
54
54
  version: '2.0'
55
- none: false
56
55
  type: :development
56
+ prerelease: false
57
57
  version_requirements: !ruby/object:Gem::Requirement
58
+ none: false
58
59
  requirements:
59
60
  - - ~>
60
61
  - !ruby/object:Gem::Version
61
62
  version: '2.0'
62
- none: false
63
63
  - !ruby/object:Gem::Dependency
64
64
  name: sprockets
65
- prerelease: false
66
65
  requirement: !ruby/object:Gem::Requirement
66
+ none: false
67
67
  requirements:
68
68
  - - ~>
69
69
  - !ruby/object:Gem::Version
70
70
  version: '2.0'
71
- none: false
72
71
  type: :development
72
+ prerelease: false
73
73
  version_requirements: !ruby/object:Gem::Requirement
74
+ none: false
74
75
  requirements:
75
76
  - - ~>
76
77
  - !ruby/object:Gem::Version
77
78
  version: '2.0'
78
- none: false
79
79
  - !ruby/object:Gem::Dependency
80
80
  name: rails
81
- prerelease: false
82
81
  requirement: !ruby/object:Gem::Requirement
82
+ none: false
83
83
  requirements:
84
84
  - - ~>
85
85
  - !ruby/object:Gem::Version
86
86
  version: '3.1'
87
- none: false
88
87
  type: :development
88
+ prerelease: false
89
89
  version_requirements: !ruby/object:Gem::Requirement
90
+ none: false
90
91
  requirements:
91
92
  - - ~>
92
93
  - !ruby/object:Gem::Version
93
94
  version: '3.1'
94
- none: false
95
95
  description: ! '- Use serenade.js with the Rails asset pipeline.
96
96
 
97
97
  - Use serenade.js with any sprockets application (middlemanapp, sinatra).
@@ -129,20 +129,20 @@ rdoc_options: []
129
129
  require_paths:
130
130
  - lib
131
131
  required_ruby_version: !ruby/object:Gem::Requirement
132
+ none: false
132
133
  requirements:
133
134
  - - ! '>='
134
135
  - !ruby/object:Gem::Version
135
136
  version: '0'
136
- none: false
137
137
  required_rubygems_version: !ruby/object:Gem::Requirement
138
+ none: false
138
139
  requirements:
139
140
  - - ! '>='
140
141
  - !ruby/object:Gem::Version
141
142
  version: '0'
142
- none: false
143
143
  requirements: []
144
144
  rubyforge_project:
145
- rubygems_version: 1.8.24
145
+ rubygems_version: 1.8.25
146
146
  signing_key:
147
147
  specification_version: 3
148
148
  summary: Serenade.js for Ruby, Rails, and Sprockets