seed.test.js 68 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550
  1. /**
  2. * Require the given path.
  3. *
  4. * @param {String} path
  5. * @return {Object} exports
  6. * @api public
  7. */
  8. function require(path, parent, orig) {
  9. var resolved = require.resolve(path);
  10. // lookup failed
  11. if (null == resolved) {
  12. orig = orig || path;
  13. parent = parent || 'root';
  14. var err = new Error('Failed to require "' + orig + '" from "' + parent + '"');
  15. err.path = orig;
  16. err.parent = parent;
  17. err.require = true;
  18. throw err;
  19. }
  20. var module = require.modules[resolved];
  21. // perform real require()
  22. // by invoking the module's
  23. // registered function
  24. if (!module._resolving && !module.exports) {
  25. var mod = {};
  26. mod.exports = {};
  27. mod.client = mod.component = true;
  28. module._resolving = true;
  29. module.call(this, mod.exports, require.relative(resolved), mod);
  30. delete module._resolving;
  31. module.exports = mod.exports;
  32. }
  33. return module.exports;
  34. }
  35. /**
  36. * Registered modules.
  37. */
  38. require.modules = {};
  39. /**
  40. * Registered aliases.
  41. */
  42. require.aliases = {};
  43. /**
  44. * Resolve `path`.
  45. *
  46. * Lookup:
  47. *
  48. * - PATH/index.js
  49. * - PATH.js
  50. * - PATH
  51. *
  52. * @param {String} path
  53. * @return {String} path or null
  54. * @api private
  55. */
  56. require.resolve = function(path) {
  57. if (path.charAt(0) === '/') path = path.slice(1);
  58. var paths = [
  59. path,
  60. path + '.js',
  61. path + '.json',
  62. path + '/index.js',
  63. path + '/index.json'
  64. ];
  65. for (var i = 0; i < paths.length; i++) {
  66. var path = paths[i];
  67. if (require.modules.hasOwnProperty(path)) return path;
  68. if (require.aliases.hasOwnProperty(path)) return require.aliases[path];
  69. }
  70. };
  71. /**
  72. * Normalize `path` relative to the current path.
  73. *
  74. * @param {String} curr
  75. * @param {String} path
  76. * @return {String}
  77. * @api private
  78. */
  79. require.normalize = function(curr, path) {
  80. var segs = [];
  81. if ('.' != path.charAt(0)) return path;
  82. curr = curr.split('/');
  83. path = path.split('/');
  84. for (var i = 0; i < path.length; ++i) {
  85. if ('..' == path[i]) {
  86. curr.pop();
  87. } else if ('.' != path[i] && '' != path[i]) {
  88. segs.push(path[i]);
  89. }
  90. }
  91. return curr.concat(segs).join('/');
  92. };
  93. /**
  94. * Register module at `path` with callback `definition`.
  95. *
  96. * @param {String} path
  97. * @param {Function} definition
  98. * @api private
  99. */
  100. require.register = function(path, definition) {
  101. require.modules[path] = definition;
  102. };
  103. /**
  104. * Alias a module definition.
  105. *
  106. * @param {String} from
  107. * @param {String} to
  108. * @api private
  109. */
  110. require.alias = function(from, to) {
  111. if (!require.modules.hasOwnProperty(from)) {
  112. throw new Error('Failed to alias "' + from + '", it does not exist');
  113. }
  114. require.aliases[to] = from;
  115. };
  116. /**
  117. * Return a require function relative to the `parent` path.
  118. *
  119. * @param {String} parent
  120. * @return {Function}
  121. * @api private
  122. */
  123. require.relative = function(parent) {
  124. var p = require.normalize(parent, '..');
  125. /**
  126. * lastIndexOf helper.
  127. */
  128. function lastIndexOf(arr, obj) {
  129. var i = arr.length;
  130. while (i--) {
  131. if (arr[i] === obj) return i;
  132. }
  133. return -1;
  134. }
  135. /**
  136. * The relative require() itself.
  137. */
  138. function localRequire(path) {
  139. var resolved = localRequire.resolve(path);
  140. return require(resolved, parent, path);
  141. }
  142. /**
  143. * Resolve relative to the parent.
  144. */
  145. localRequire.resolve = function(path) {
  146. var c = path.charAt(0);
  147. if ('/' == c) return path.slice(1);
  148. if ('.' == c) return require.normalize(p, path);
  149. // resolve deps by returning
  150. // the dep in the nearest "deps"
  151. // directory
  152. var segs = parent.split('/');
  153. var i = lastIndexOf(segs, 'deps') + 1;
  154. if (!i) i = 0;
  155. path = segs.slice(0, i + 1).join('/') + '/deps/' + path;
  156. return path;
  157. };
  158. /**
  159. * Check if module is defined at `path`.
  160. */
  161. localRequire.exists = function(path) {
  162. return require.modules.hasOwnProperty(localRequire.resolve(path));
  163. };
  164. return localRequire;
  165. };
  166. require.register("component-indexof/index.js", function(exports, require, module){
  167. var indexOf = [].indexOf;
  168. module.exports = function(arr, obj){
  169. if (indexOf) return arr.indexOf(obj);
  170. for (var i = 0; i < arr.length; ++i) {
  171. if (arr[i] === obj) return i;
  172. }
  173. return -1;
  174. };
  175. });
  176. require.register("component-emitter/index.js", function(exports, require, module){
  177. /**
  178. * Module dependencies.
  179. */
  180. var index = require('indexof');
  181. /**
  182. * Expose `Emitter`.
  183. */
  184. module.exports = Emitter;
  185. /**
  186. * Initialize a new `Emitter`.
  187. *
  188. * @api public
  189. */
  190. function Emitter(obj) {
  191. if (obj) return mixin(obj);
  192. };
  193. /**
  194. * Mixin the emitter properties.
  195. *
  196. * @param {Object} obj
  197. * @return {Object}
  198. * @api private
  199. */
  200. function mixin(obj) {
  201. for (var key in Emitter.prototype) {
  202. obj[key] = Emitter.prototype[key];
  203. }
  204. return obj;
  205. }
  206. /**
  207. * Listen on the given `event` with `fn`.
  208. *
  209. * @param {String} event
  210. * @param {Function} fn
  211. * @return {Emitter}
  212. * @api public
  213. */
  214. Emitter.prototype.on = function(event, fn){
  215. this._callbacks = this._callbacks || {};
  216. (this._callbacks[event] = this._callbacks[event] || [])
  217. .push(fn);
  218. return this;
  219. };
  220. /**
  221. * Adds an `event` listener that will be invoked a single
  222. * time then automatically removed.
  223. *
  224. * @param {String} event
  225. * @param {Function} fn
  226. * @return {Emitter}
  227. * @api public
  228. */
  229. Emitter.prototype.once = function(event, fn){
  230. var self = this;
  231. this._callbacks = this._callbacks || {};
  232. function on() {
  233. self.off(event, on);
  234. fn.apply(this, arguments);
  235. }
  236. fn._off = on;
  237. this.on(event, on);
  238. return this;
  239. };
  240. /**
  241. * Remove the given callback for `event` or all
  242. * registered callbacks.
  243. *
  244. * @param {String} event
  245. * @param {Function} fn
  246. * @return {Emitter}
  247. * @api public
  248. */
  249. Emitter.prototype.off =
  250. Emitter.prototype.removeListener =
  251. Emitter.prototype.removeAllListeners = function(event, fn){
  252. this._callbacks = this._callbacks || {};
  253. // all
  254. if (0 == arguments.length) {
  255. this._callbacks = {};
  256. return this;
  257. }
  258. // specific event
  259. var callbacks = this._callbacks[event];
  260. if (!callbacks) return this;
  261. // remove all handlers
  262. if (1 == arguments.length) {
  263. delete this._callbacks[event];
  264. return this;
  265. }
  266. // remove specific handler
  267. var i = index(callbacks, fn._off || fn);
  268. if (~i) callbacks.splice(i, 1);
  269. return this;
  270. };
  271. /**
  272. * Emit `event` with the given args.
  273. *
  274. * @param {String} event
  275. * @param {Mixed} ...
  276. * @return {Emitter}
  277. */
  278. Emitter.prototype.emit = function(event){
  279. this._callbacks = this._callbacks || {};
  280. var args = [].slice.call(arguments, 1)
  281. , callbacks = this._callbacks[event];
  282. if (callbacks) {
  283. callbacks = callbacks.slice(0);
  284. for (var i = 0, len = callbacks.length; i < len; ++i) {
  285. callbacks[i].apply(this, args);
  286. }
  287. }
  288. return this;
  289. };
  290. /**
  291. * Return array of callbacks for `event`.
  292. *
  293. * @param {String} event
  294. * @return {Array}
  295. * @api public
  296. */
  297. Emitter.prototype.listeners = function(event){
  298. this._callbacks = this._callbacks || {};
  299. return this._callbacks[event] || [];
  300. };
  301. /**
  302. * Check if this emitter has `event` handlers.
  303. *
  304. * @param {String} event
  305. * @return {Boolean}
  306. * @api public
  307. */
  308. Emitter.prototype.hasListeners = function(event){
  309. return !! this.listeners(event).length;
  310. };
  311. });
  312. require.register("seed/src/main.js", function(exports, require, module){
  313. var config = require('./config'),
  314. ViewModel = require('./viewmodel'),
  315. directives = require('./directives'),
  316. filters = require('./filters'),
  317. utils = require('./utils')
  318. /**
  319. * Set config options
  320. */
  321. ViewModel.config = function (opts) {
  322. if (opts) {
  323. utils.extend(config, opts)
  324. }
  325. return this
  326. }
  327. /**
  328. * Allows user to register/retrieve a directive definition
  329. */
  330. ViewModel.directive = function (id, fn) {
  331. if (!fn) return directives[id]
  332. directives[id] = fn
  333. return this
  334. }
  335. /**
  336. * Allows user to register/retrieve a filter function
  337. */
  338. ViewModel.filter = function (id, fn) {
  339. if (!fn) return filters[id]
  340. filters[id] = fn
  341. return this
  342. }
  343. /**
  344. * Allows user to register/retrieve a ViewModel constructor
  345. */
  346. ViewModel.viewmodel = function (id, Ctor) {
  347. if (!Ctor) return utils.vms[id]
  348. utils.vms[id] = Ctor
  349. return this
  350. }
  351. /**
  352. * Allows user to register/retrieve a template partial
  353. */
  354. ViewModel.partial = function (id, partial) {
  355. if (!partial) return utils.partials[id]
  356. utils.partials[id] = templateToFragment(partial)
  357. return this
  358. }
  359. /**
  360. * Allows user to register/retrieve a transition definition object
  361. */
  362. ViewModel.transition = function (id, transition) {
  363. if (!transition) return utils.transitions[id]
  364. utils.transitions[id] = transition
  365. return this
  366. }
  367. ViewModel.extend = extend
  368. /**
  369. * Expose the main ViewModel class
  370. * and add extend method
  371. */
  372. function extend (options) {
  373. var ParentVM = this
  374. // inherit options
  375. options = inheritOptions(options, ParentVM.options, true)
  376. var ExtendedVM = function (opts) {
  377. opts = inheritOptions(opts, options, true)
  378. ParentVM.call(this, opts)
  379. }
  380. // inherit prototype props
  381. var proto = ExtendedVM.prototype = Object.create(ParentVM.prototype)
  382. utils.defProtected(proto, 'constructor', ExtendedVM)
  383. // copy prototype props
  384. var protoMixins = options.proto
  385. if (protoMixins) {
  386. for (var key in protoMixins) {
  387. if (!(key in ViewModel.prototype)) {
  388. proto[key] = protoMixins[key]
  389. }
  390. }
  391. }
  392. // convert template to documentFragment
  393. if (options.template) {
  394. options.templateFragment = templateToFragment(options.template)
  395. }
  396. // allow extended VM to be further extended
  397. ExtendedVM.extend = extend
  398. ExtendedVM.super = ParentVM
  399. ExtendedVM.options = options
  400. return ExtendedVM
  401. }
  402. /**
  403. * Inherit options
  404. *
  405. * For options such as `scope`, `vms`, `directives`, 'partials',
  406. * they should be further extended. However extending should only
  407. * be done at top level.
  408. *
  409. * `proto` is an exception because it's handled directly on the
  410. * prototype.
  411. *
  412. * `el` is an exception because it's not allowed as an
  413. * extension option, but only as an instance option.
  414. */
  415. function inheritOptions (child, parent, topLevel) {
  416. child = child || {}
  417. convertPartials(child.partials)
  418. if (!parent) return child
  419. for (var key in parent) {
  420. if (key === 'el' || key === 'proto') continue
  421. if (!child[key]) { // child has priority
  422. child[key] = parent[key]
  423. } else if (topLevel && utils.typeOf(child[key]) === 'Object') {
  424. inheritOptions(child[key], parent[key], false)
  425. }
  426. }
  427. return child
  428. }
  429. /**
  430. * Convert an object of partials to dom fragments
  431. */
  432. function convertPartials (partials) {
  433. if (!partials) return
  434. for (var key in partials) {
  435. if (typeof partials[key] === 'string') {
  436. partials[key] = templateToFragment(partials[key])
  437. }
  438. }
  439. }
  440. /**
  441. * Convert a string template to a dom fragment
  442. */
  443. function templateToFragment (template) {
  444. if (template.charAt(0) === '#') {
  445. var templateNode = document.querySelector(template)
  446. if (!templateNode) return
  447. template = templateNode.innerHTML
  448. }
  449. var node = document.createElement('div'),
  450. frag = document.createDocumentFragment(),
  451. child
  452. node.innerHTML = template.trim()
  453. /* jshint boss: true */
  454. while (child = node.firstChild) {
  455. frag.appendChild(child)
  456. }
  457. return frag
  458. }
  459. module.exports = ViewModel
  460. });
  461. require.register("seed/src/emitter.js", function(exports, require, module){
  462. // shiv to make this work for Component, Browserify and Node at the same time.
  463. var Emitter,
  464. componentEmitter = 'emitter'
  465. try {
  466. // Requiring without a string literal will make browserify
  467. // unable to parse the dependency, thus preventing it from
  468. // stopping the compilation after a failed lookup.
  469. Emitter = require(componentEmitter)
  470. } catch (e) {}
  471. module.exports = Emitter || require('events').EventEmitter
  472. });
  473. require.register("seed/src/config.js", function(exports, require, module){
  474. module.exports = {
  475. prefix : 'sd',
  476. debug : false
  477. }
  478. });
  479. require.register("seed/src/utils.js", function(exports, require, module){
  480. var config = require('./config'),
  481. toString = Object.prototype.toString,
  482. join = Array.prototype.join,
  483. console = window.console
  484. module.exports = {
  485. // global storage for user-registered
  486. // vms, partials and transitions
  487. vms : {},
  488. partials : {},
  489. transitions : {},
  490. /**
  491. * Define an ienumerable property
  492. * This avoids it being included in JSON.stringify
  493. * or for...in loops.
  494. */
  495. defProtected: function (obj, key, val, enumerable) {
  496. if (obj.hasOwnProperty(key)) return
  497. Object.defineProperty(obj, key, {
  498. enumerable: !!enumerable,
  499. configurable: false,
  500. value: val
  501. })
  502. },
  503. /**
  504. * Accurate type check
  505. */
  506. typeOf: function (obj) {
  507. return toString.call(obj).slice(8, -1)
  508. },
  509. /**
  510. * Make sure only strings and numbers are output to html
  511. * output empty string is value is not string or number
  512. */
  513. toText: function (value) {
  514. /* jshint eqeqeq: false */
  515. return (typeof value === 'string' ||
  516. (typeof value === 'number' && value == value)) // deal with NaN
  517. ? value
  518. : ''
  519. },
  520. /**
  521. * simple extend
  522. */
  523. extend: function (obj, ext, protective) {
  524. if (!ext) return
  525. for (var key in ext) {
  526. if (protective && obj[key]) continue
  527. obj[key] = ext[key]
  528. }
  529. },
  530. /**
  531. * log for debugging
  532. */
  533. log: function () {
  534. if (config.debug && console) {
  535. console.log(join.call(arguments, ' '))
  536. }
  537. },
  538. /**
  539. * warn for debugging
  540. */
  541. warn: function() {
  542. if (config.debug && console) {
  543. console.warn(join.call(arguments, ' '))
  544. }
  545. }
  546. }
  547. });
  548. require.register("seed/src/compiler.js", function(exports, require, module){
  549. var Emitter = require('./emitter'),
  550. Observer = require('./observer'),
  551. config = require('./config'),
  552. utils = require('./utils'),
  553. Binding = require('./binding'),
  554. Directive = require('./directive'),
  555. TextParser = require('./text-parser'),
  556. DepsParser = require('./deps-parser'),
  557. ExpParser = require('./exp-parser'),
  558. slice = Array.prototype.slice,
  559. log = utils.log,
  560. def = utils.defProtected,
  561. vmAttr,
  562. repeatAttr,
  563. partialAttr,
  564. transitionAttr,
  565. preAttr
  566. /**
  567. * The DOM compiler
  568. * scans a DOM node and compile bindings for a ViewModel
  569. */
  570. function Compiler (vm, options) {
  571. refreshPrefix()
  572. var compiler = this
  573. // extend options
  574. options = compiler.options = options || {}
  575. utils.extend(compiler, options.compilerOptions)
  576. // initialize element
  577. compiler.setupElement(options)
  578. log('\nnew VM instance:', compiler.el.tagName, '\n')
  579. // copy scope properties to vm
  580. var scope = options.scope
  581. if (scope) utils.extend(vm, scope, true)
  582. compiler.vm = vm
  583. // special VM properties are inumerable
  584. def(vm, '$compiler', compiler)
  585. def(vm, '$el', compiler.el)
  586. // keep track of directives and expressions
  587. // so they can be unbound during destroy()
  588. compiler.dirs = []
  589. compiler.exps = []
  590. compiler.childCompilers = [] // keep track of child compilers
  591. compiler.emitter = new Emitter() // the emitter used for nested VM communication
  592. // Store things during parsing to be processed afterwards,
  593. // because we want to have created all bindings before
  594. // observing values / parsing dependencies.
  595. var observables = compiler.observables = [],
  596. computed = compiler.computed = []
  597. // prototypal inheritance of bindings
  598. var parent = compiler.parentCompiler
  599. compiler.bindings = parent
  600. ? Object.create(parent.bindings)
  601. : {}
  602. compiler.rootCompiler = parent
  603. ? getRoot(parent)
  604. : compiler
  605. // setup observer
  606. compiler.setupObserver()
  607. // call user init. this will capture some initial values.
  608. if (options.init) {
  609. options.init.apply(vm, options.args || [])
  610. }
  611. // create bindings for keys set on the vm by the user
  612. var key, keyPrefix
  613. for (key in vm) {
  614. keyPrefix = key.charAt(0)
  615. if (keyPrefix !== '$' && keyPrefix !== '_') {
  616. compiler.createBinding(key)
  617. }
  618. }
  619. // for repeated items, create an index binding
  620. if (compiler.repeat) {
  621. vm[compiler.repeatPrefix].$index = compiler.repeatIndex
  622. }
  623. // now parse the DOM, during which we will create necessary bindings
  624. // and bind the parsed directives
  625. compiler.compile(compiler.el, true)
  626. // observe root values so that they emit events when
  627. // their nested values change (for an Object)
  628. // or when they mutate (for an Array)
  629. var i = observables.length, binding
  630. while (i--) {
  631. binding = observables[i]
  632. Observer.observe(binding.value, binding.key, compiler.observer)
  633. }
  634. // extract dependencies for computed properties
  635. if (computed.length) DepsParser.parse(computed)
  636. }
  637. var CompilerProto = Compiler.prototype
  638. /**
  639. * Initialize the VM/Compiler's element.
  640. * Fill it in with the template if necessary.
  641. */
  642. CompilerProto.setupElement = function (options) {
  643. // create the node first
  644. var el = this.el = typeof options.el === 'string'
  645. ? document.querySelector(options.el)
  646. : options.el || document.createElement(options.tagName || 'div')
  647. // apply element options
  648. if (options.id) el.id = options.id
  649. if (options.className) el.className = options.className
  650. var attrs = options.attributes
  651. if (attrs) {
  652. for (var attr in attrs) {
  653. el.setAttribute(attr, attrs[attr])
  654. }
  655. }
  656. // initialize template
  657. var template = options.template
  658. if (typeof template === 'string') {
  659. if (template.charAt(0) === '#') {
  660. var templateNode = document.querySelector(template)
  661. if (templateNode) {
  662. el.innerHTML = templateNode.innerHTML
  663. }
  664. } else {
  665. el.innerHTML = template
  666. }
  667. } else if (options.templateFragment) {
  668. el.innerHTML = ''
  669. el.appendChild(options.templateFragment.cloneNode(true))
  670. }
  671. }
  672. /**
  673. * Setup observer.
  674. * The observer listens for get/set/mutate events on all VM
  675. * values/objects and trigger corresponding binding updates.
  676. */
  677. CompilerProto.setupObserver = function () {
  678. var bindings = this.bindings,
  679. observer = this.observer = new Emitter(),
  680. depsOb = DepsParser.observer
  681. // a hash to hold event proxies for each root level key
  682. // so they can be referenced and removed later
  683. observer.proxies = {}
  684. // add own listeners which trigger binding updates
  685. observer
  686. .on('get', function (key) {
  687. if (bindings[key] && depsOb.isObserving) {
  688. depsOb.emit('get', bindings[key])
  689. }
  690. })
  691. .on('set', function (key, val) {
  692. observer.emit('change:' + key, val)
  693. if (bindings[key]) bindings[key].update(val)
  694. })
  695. .on('mutate', function (key, val, mutation) {
  696. observer.emit('change:' + key, val, mutation)
  697. if (bindings[key]) bindings[key].pub()
  698. })
  699. }
  700. /**
  701. * Compile a DOM node (recursive)
  702. */
  703. CompilerProto.compile = function (node, root) {
  704. var compiler = this
  705. if (node.nodeType === 1) {
  706. // a normal node
  707. if (node.hasAttribute(preAttr)) return
  708. var repeatExp = node.getAttribute(repeatAttr),
  709. vmId = node.getAttribute(vmAttr),
  710. partialId = node.getAttribute(partialAttr)
  711. // we need to check for any possbile special directives
  712. // e.g. sd-repeat, sd-viewmodel & sd-partial
  713. if (repeatExp) { // repeat block
  714. var directive = Directive.parse(repeatAttr, repeatExp, compiler, node)
  715. if (directive) {
  716. compiler.bindDirective(directive)
  717. }
  718. } else if (vmId && !root) { // child ViewModels
  719. node.removeAttribute(vmAttr)
  720. var ChildVM = compiler.getOption('vms', vmId)
  721. if (ChildVM) {
  722. var child = new ChildVM({
  723. el: node,
  724. child: true,
  725. compilerOptions: {
  726. parentCompiler: compiler
  727. }
  728. })
  729. compiler.childCompilers.push(child.$compiler)
  730. }
  731. } else {
  732. if (partialId) { // replace innerHTML with partial
  733. node.removeAttribute(partialAttr)
  734. var partial = compiler.getOption('partials', partialId)
  735. if (partial) {
  736. node.innerHTML = ''
  737. node.appendChild(partial.cloneNode(true))
  738. }
  739. }
  740. // finally, only normal directives left!
  741. compiler.compileNode(node)
  742. }
  743. } else if (node.nodeType === 3) { // text node
  744. compiler.compileTextNode(node)
  745. }
  746. }
  747. /**
  748. * Compile a normal node
  749. */
  750. CompilerProto.compileNode = function (node) {
  751. var i, j
  752. // parse if has attributes
  753. if (node.attributes && node.attributes.length) {
  754. var attrs = slice.call(node.attributes),
  755. attr, valid, exps, exp
  756. // loop through all attributes
  757. i = attrs.length
  758. while (i--) {
  759. attr = attrs[i]
  760. valid = false
  761. exps = attr.value.split(',')
  762. // loop through clauses (separated by ",")
  763. // inside each attribute
  764. j = exps.length
  765. while (j--) {
  766. exp = exps[j]
  767. var directive = Directive.parse(attr.name, exp, this, node)
  768. if (directive) {
  769. valid = true
  770. this.bindDirective(directive)
  771. }
  772. }
  773. if (valid) node.removeAttribute(attr.name)
  774. }
  775. }
  776. // recursively compile childNodes
  777. if (node.childNodes.length) {
  778. var nodes = slice.call(node.childNodes)
  779. for (i = 0, j = nodes.length; i < j; i++) {
  780. this.compile(nodes[i])
  781. }
  782. }
  783. }
  784. /**
  785. * Compile a text node
  786. */
  787. CompilerProto.compileTextNode = function (node) {
  788. var tokens = TextParser.parse(node.nodeValue)
  789. if (!tokens) return
  790. var dirname = config.prefix + '-text',
  791. el, token, directive
  792. for (var i = 0, l = tokens.length; i < l; i++) {
  793. token = tokens[i]
  794. if (token.key) { // a binding
  795. if (token.key.charAt(0) === '>') { // a partial
  796. var partialId = token.key.slice(1).trim(),
  797. partial = this.getOption('partials', partialId)
  798. if (partial) {
  799. el = partial.cloneNode(true)
  800. this.compileNode(el)
  801. }
  802. } else { // a binding
  803. el = document.createTextNode('')
  804. directive = Directive.parse(dirname, token.key, this, el)
  805. if (directive) {
  806. this.bindDirective(directive)
  807. }
  808. }
  809. } else { // a plain string
  810. el = document.createTextNode(token)
  811. }
  812. node.parentNode.insertBefore(el, node)
  813. }
  814. node.parentNode.removeChild(node)
  815. }
  816. /**
  817. * Add a directive instance to the correct binding & viewmodel
  818. */
  819. CompilerProto.bindDirective = function (directive) {
  820. var binding,
  821. compiler = this,
  822. key = directive.key,
  823. baseKey = key.split('.')[0],
  824. ownerCompiler = traceOwnerCompiler(directive, compiler)
  825. compiler.dirs.push(directive)
  826. if (directive.isExp) {
  827. binding = compiler.createBinding(key, true)
  828. } else if (ownerCompiler.vm.hasOwnProperty(baseKey)) {
  829. // if the value is present in the target VM, we create the binding on its compiler
  830. binding = ownerCompiler.bindings.hasOwnProperty(key)
  831. ? ownerCompiler.bindings[key]
  832. : ownerCompiler.createBinding(key)
  833. } else {
  834. // due to prototypal inheritance of bindings, if a key doesn't exist here,
  835. // it doesn't exist in the whole prototype chain. Therefore in that case
  836. // we create the new binding at the root level.
  837. binding = ownerCompiler.bindings[key] || compiler.rootCompiler.createBinding(key)
  838. }
  839. binding.instances.push(directive)
  840. directive.binding = binding
  841. // for newly inserted sub-VMs (repeat items), need to bind deps
  842. // because they didn't get processed when the parent compiler
  843. // was binding dependencies.
  844. var i, dep, deps = binding.contextDeps
  845. if (deps) {
  846. i = deps.length
  847. while (i--) {
  848. dep = compiler.bindings[deps[i]]
  849. dep.subs.push(directive)
  850. }
  851. }
  852. var value = binding.value
  853. // invoke bind hook if exists
  854. if (directive.bind) {
  855. directive.bind(value)
  856. }
  857. // set initial value
  858. if (binding.isComputed) {
  859. directive.refresh(value)
  860. } else {
  861. directive.update(value, true)
  862. }
  863. }
  864. /**
  865. * Create binding and attach getter/setter for a key to the viewmodel object
  866. */
  867. CompilerProto.createBinding = function (key, isExp) {
  868. var compiler = this,
  869. bindings = compiler.bindings,
  870. binding = new Binding(compiler, key, isExp)
  871. if (isExp) {
  872. // a complex expression binding
  873. // we need to generate an anonymous computed property for it
  874. var result = ExpParser.parse(key)
  875. if (result) {
  876. log(' created anonymous binding: ' + key)
  877. binding.value = { get: result.getter }
  878. compiler.markComputed(binding)
  879. compiler.exps.push(binding)
  880. // need to create the bindings for keys
  881. // that do not exist yet
  882. var i = result.vars.length, v
  883. while (i--) {
  884. v = result.vars[i]
  885. if (!bindings[v]) {
  886. compiler.rootCompiler.createBinding(v)
  887. }
  888. }
  889. } else {
  890. utils.warn(' invalid expression: ' + key)
  891. }
  892. } else {
  893. log(' created binding: ' + key)
  894. bindings[key] = binding
  895. // make sure the key exists in the object so it can be observed
  896. // by the Observer!
  897. compiler.ensurePath(key)
  898. if (binding.root) {
  899. // this is a root level binding. we need to define getter/setters for it.
  900. compiler.define(key, binding)
  901. } else {
  902. var parentKey = key.slice(0, key.lastIndexOf('.'))
  903. if (!bindings.hasOwnProperty(parentKey)) {
  904. // this is a nested value binding, but the binding for its parent
  905. // has not been created yet. We better create that one too.
  906. compiler.createBinding(parentKey)
  907. }
  908. }
  909. }
  910. return binding
  911. }
  912. /**
  913. * Sometimes when a binding is found in the template, the value might
  914. * have not been set on the VM yet. To ensure computed properties and
  915. * dependency extraction can work, we have to create a dummy value for
  916. * any given path.
  917. */
  918. CompilerProto.ensurePath = function (key) {
  919. var path = key.split('.'), sec, obj = this.vm
  920. for (var i = 0, d = path.length - 1; i < d; i++) {
  921. sec = path[i]
  922. if (!obj[sec]) obj[sec] = {}
  923. obj = obj[sec]
  924. }
  925. if (utils.typeOf(obj) === 'Object') {
  926. sec = path[i]
  927. if (!(sec in obj)) obj[sec] = undefined
  928. }
  929. }
  930. /**
  931. * Defines the getter/setter for a root-level binding on the VM
  932. * and observe the initial value
  933. */
  934. CompilerProto.define = function (key, binding) {
  935. log(' defined root binding: ' + key)
  936. var compiler = this,
  937. vm = compiler.vm,
  938. ob = compiler.observer,
  939. value = binding.value = vm[key], // save the value before redefinening it
  940. type = utils.typeOf(value)
  941. if (type === 'Object' && value.get) {
  942. // computed property
  943. compiler.markComputed(binding)
  944. } else if (type === 'Object' || type === 'Array') {
  945. // observe objects later, becase there might be more keys
  946. // to be added to it. we also want to emit all the set events
  947. // after all values are available.
  948. compiler.observables.push(binding)
  949. }
  950. Object.defineProperty(vm, key, {
  951. enumerable: true,
  952. get: function () {
  953. var value = binding.value
  954. if ((!binding.isComputed && (!value || !value.__observer__)) ||
  955. Array.isArray(value)) {
  956. // only emit non-computed, non-observed (primitive) values, or Arrays.
  957. // because these are the cleanest dependencies
  958. ob.emit('get', key)
  959. }
  960. return binding.isComputed
  961. ? value.get()
  962. : value
  963. },
  964. set: function (newVal) {
  965. var value = binding.value
  966. if (binding.isComputed) {
  967. if (value.set) {
  968. value.set(newVal)
  969. }
  970. } else if (newVal !== value) {
  971. // unwatch the old value
  972. Observer.unobserve(value, key, ob)
  973. // set new value
  974. binding.value = newVal
  975. ob.emit('set', key, newVal)
  976. // now watch the new value, which in turn emits 'set'
  977. // for all its nested values
  978. Observer.observe(newVal, key, ob)
  979. }
  980. }
  981. })
  982. }
  983. /**
  984. * Process a computed property binding
  985. */
  986. CompilerProto.markComputed = function (binding) {
  987. var value = binding.value,
  988. vm = this.vm
  989. binding.isComputed = true
  990. // bind the accessors to the vm
  991. value.get = value.get.bind(vm)
  992. if (value.set) value.set = value.set.bind(vm)
  993. // keep track for dep parsing later
  994. this.computed.push(binding)
  995. }
  996. /**
  997. * Process subscriptions for computed properties that has
  998. * dynamic context dependencies
  999. */
  1000. CompilerProto.bindContexts = function (bindings) {
  1001. var i = bindings.length, j, k, binding, depKey, dep, ins
  1002. while (i--) {
  1003. binding = bindings[i]
  1004. j = binding.contextDeps.length
  1005. while (j--) {
  1006. depKey = binding.contextDeps[j]
  1007. k = binding.instances.length
  1008. while (k--) {
  1009. ins = binding.instances[k]
  1010. dep = ins.compiler.bindings[depKey]
  1011. dep.subs.push(ins)
  1012. }
  1013. }
  1014. }
  1015. }
  1016. /**
  1017. * Retrive an option from the compiler
  1018. */
  1019. CompilerProto.getOption = function (type, id) {
  1020. var opts = this.options
  1021. return (opts[type] && opts[type][id]) || (utils[type] && utils[type][id])
  1022. }
  1023. /**
  1024. * Unbind and remove element
  1025. */
  1026. CompilerProto.destroy = function () {
  1027. var compiler = this
  1028. log('compiler destroyed: ', compiler.vm.$el)
  1029. // unwatch
  1030. compiler.observer.off()
  1031. compiler.emitter.off()
  1032. var i, key, dir, inss, binding,
  1033. el = compiler.el,
  1034. directives = compiler.dirs,
  1035. exps = compiler.exps,
  1036. bindings = compiler.bindings
  1037. // remove all directives that are instances of external bindings
  1038. i = directives.length
  1039. while (i--) {
  1040. dir = directives[i]
  1041. if (dir.binding.compiler !== compiler) {
  1042. inss = dir.binding.instances
  1043. if (inss) inss.splice(inss.indexOf(dir), 1)
  1044. }
  1045. dir.unbind()
  1046. }
  1047. // unbind all expressions (anonymous bindings)
  1048. i = exps.length
  1049. while (i--) {
  1050. exps[i].unbind()
  1051. }
  1052. // unbind/unobserve all own bindings
  1053. for (key in bindings) {
  1054. if (bindings.hasOwnProperty(key)) {
  1055. binding = bindings[key]
  1056. if (binding.root) {
  1057. Observer.unobserve(binding.value, binding.key, compiler.observer)
  1058. }
  1059. binding.unbind()
  1060. }
  1061. }
  1062. // remove self from parentCompiler
  1063. var parent = compiler.parentCompiler
  1064. if (parent) {
  1065. parent.childCompilers.splice(parent.childCompilers.indexOf(compiler), 1)
  1066. }
  1067. // remove el
  1068. if (el === document.body) {
  1069. el.innerHTML = ''
  1070. } else if (el.parentNode) {
  1071. el.parentNode.removeChild(el)
  1072. }
  1073. }
  1074. // Helpers --------------------------------------------------------------------
  1075. /**
  1076. * Refresh prefix in case it has been changed
  1077. * during compilations
  1078. */
  1079. function refreshPrefix () {
  1080. var prefix = config.prefix
  1081. repeatAttr = prefix + '-repeat'
  1082. vmAttr = prefix + '-viewmodel'
  1083. partialAttr = prefix + '-partial'
  1084. transitionAttr = prefix + '-transition'
  1085. preAttr = prefix + '-pre'
  1086. }
  1087. /**
  1088. * determine which viewmodel a key belongs to based on nesting symbols
  1089. */
  1090. function traceOwnerCompiler (key, compiler) {
  1091. if (key.nesting) {
  1092. var levels = key.nesting
  1093. while (compiler.parentCompiler && levels--) {
  1094. compiler = compiler.parentCompiler
  1095. }
  1096. } else if (key.root) {
  1097. while (compiler.parentCompiler) {
  1098. compiler = compiler.parentCompiler
  1099. }
  1100. }
  1101. return compiler
  1102. }
  1103. /**
  1104. * shorthand for getting root compiler
  1105. */
  1106. function getRoot (compiler) {
  1107. return traceOwnerCompiler({ root: true }, compiler)
  1108. }
  1109. module.exports = Compiler
  1110. });
  1111. require.register("seed/src/viewmodel.js", function(exports, require, module){
  1112. var Compiler = require('./compiler'),
  1113. def = require('./utils').defProtected
  1114. /**
  1115. * ViewModel exposed to the user that holds data,
  1116. * computed properties, event handlers
  1117. * and a few reserved methods
  1118. */
  1119. function ViewModel (options) {
  1120. // just compile. options are passed directly to compiler
  1121. new Compiler(this, options)
  1122. }
  1123. // All VM prototype methods are inenumerable
  1124. // so it can be stringified/looped through as raw data
  1125. var VMProto = ViewModel.prototype
  1126. /**
  1127. * Convenience function to set an actual nested value
  1128. * from a flat key string. Used in directives.
  1129. */
  1130. def(VMProto, '$set', function (key, value) {
  1131. var path = key.split('.'),
  1132. obj = getTargetVM(this, path)
  1133. if (!obj) return
  1134. for (var d = 0, l = path.length - 1; d < l; d++) {
  1135. obj = obj[path[d]]
  1136. }
  1137. obj[path[d]] = value
  1138. })
  1139. /**
  1140. * The function for getting a key
  1141. * which will go up along the prototype chain of the bindings
  1142. * Used in exp-parser.
  1143. */
  1144. def(VMProto, '$get', function (key) {
  1145. var path = key.split('.'),
  1146. obj = getTargetVM(this, path),
  1147. vm = obj
  1148. if (!obj) return
  1149. for (var d = 0, l = path.length; d < l; d++) {
  1150. obj = obj[path[d]]
  1151. }
  1152. if (typeof obj === 'function') obj = obj.bind(vm)
  1153. return obj
  1154. })
  1155. /**
  1156. * watch a key on the viewmodel for changes
  1157. * fire callback with new value
  1158. */
  1159. def(VMProto, '$watch', function (key, callback) {
  1160. this.$compiler.observer.on('change:' + key, callback)
  1161. })
  1162. /**
  1163. * unwatch a key
  1164. */
  1165. def(VMProto, '$unwatch', function (key, callback) {
  1166. // workaround here
  1167. // since the emitter module checks callback existence
  1168. // by checking the length of arguments
  1169. var args = ['change:' + key],
  1170. ob = this.$compiler.observer
  1171. if (callback) args.push(callback)
  1172. ob.off.apply(ob, args)
  1173. })
  1174. /**
  1175. * unbind everything, remove everything
  1176. */
  1177. def(VMProto, '$destroy', function () {
  1178. this.$compiler.destroy()
  1179. })
  1180. /**
  1181. * broadcast an event to all child VMs recursively.
  1182. */
  1183. def(VMProto, '$broadcast', function () {
  1184. var children = this.$compiler.childCompilers,
  1185. i = children.length,
  1186. child
  1187. while (i--) {
  1188. child = children[i]
  1189. child.emitter.emit.apply(child.emitter, arguments)
  1190. child.vm.$broadcast.apply(child.vm, arguments)
  1191. }
  1192. })
  1193. /**
  1194. * emit an event that propagates all the way up to parent VMs.
  1195. */
  1196. def(VMProto, '$emit', function () {
  1197. var parent = this.$compiler.parentCompiler
  1198. if (parent) {
  1199. parent.emitter.emit.apply(parent.emitter, arguments)
  1200. parent.vm.$emit.apply(parent.vm, arguments)
  1201. }
  1202. })
  1203. /**
  1204. * delegate on/off/once to the compiler's emitter
  1205. */
  1206. ;['on', 'off', 'once'].forEach(function (method) {
  1207. def(VMProto, '$' + method, function () {
  1208. var emitter = this.$compiler.emitter
  1209. emitter[method].apply(emitter, arguments)
  1210. })
  1211. })
  1212. /**
  1213. * If a VM doesn't contain a path, go up the prototype chain
  1214. * to locate the ancestor that has it.
  1215. */
  1216. function getTargetVM (vm, path) {
  1217. var baseKey = path[0],
  1218. binding = vm.$compiler.bindings[baseKey]
  1219. return binding
  1220. ? binding.compiler.vm
  1221. : null
  1222. }
  1223. module.exports = ViewModel
  1224. });
  1225. require.register("seed/src/binding.js", function(exports, require, module){
  1226. /**
  1227. * Binding class.
  1228. *
  1229. * each property on the viewmodel has one corresponding Binding object
  1230. * which has multiple directive instances on the DOM
  1231. * and multiple computed property dependents
  1232. */
  1233. function Binding (compiler, key, isExp) {
  1234. this.value = undefined
  1235. this.isExp = !!isExp
  1236. this.root = !this.isExp && key.indexOf('.') === -1
  1237. this.compiler = compiler
  1238. this.key = key
  1239. this.instances = []
  1240. this.subs = []
  1241. this.deps = []
  1242. }
  1243. var BindingProto = Binding.prototype
  1244. /**
  1245. * Process the value, then trigger updates on all dependents
  1246. */
  1247. BindingProto.update = function (value) {
  1248. this.value = value
  1249. var i = this.instances.length
  1250. while (i--) {
  1251. this.instances[i].update(value)
  1252. }
  1253. this.pub()
  1254. }
  1255. /**
  1256. * -- computed property only --
  1257. * Force all instances to re-evaluate themselves
  1258. */
  1259. BindingProto.refresh = function () {
  1260. var i = this.instances.length
  1261. while (i--) {
  1262. this.instances[i].refresh()
  1263. }
  1264. this.pub()
  1265. }
  1266. /**
  1267. * Notify computed properties that depend on this binding
  1268. * to update themselves
  1269. */
  1270. BindingProto.pub = function () {
  1271. var i = this.subs.length
  1272. while (i--) {
  1273. this.subs[i].refresh()
  1274. }
  1275. }
  1276. /**
  1277. * Unbind the binding, remove itself from all of its dependencies
  1278. */
  1279. BindingProto.unbind = function () {
  1280. var i = this.instances.length
  1281. while (i--) {
  1282. this.instances[i].unbind()
  1283. }
  1284. i = this.deps.length
  1285. var subs
  1286. while (i--) {
  1287. subs = this.deps[i].subs
  1288. subs.splice(subs.indexOf(this), 1)
  1289. }
  1290. }
  1291. module.exports = Binding
  1292. });
  1293. require.register("seed/src/observer.js", function(exports, require, module){
  1294. /* jshint proto:true */
  1295. var Emitter = require('./emitter'),
  1296. utils = require('./utils'),
  1297. typeOf = utils.typeOf,
  1298. def = utils.defProtected,
  1299. slice = Array.prototype.slice,
  1300. methods = ['push','pop','shift','unshift','splice','sort','reverse'],
  1301. hasProto = ({}).__proto__ // fix for IE9
  1302. // The proxy prototype to replace the __proto__ of
  1303. // an observed array
  1304. var ArrayProxy = Object.create(Array.prototype)
  1305. // Define mutation interceptors so we can emit the mutation info
  1306. methods.forEach(function (method) {
  1307. def(ArrayProxy, method, function () {
  1308. var result = Array.prototype[method].apply(this, arguments)
  1309. this.__observer__.emit('mutate', this.__observer__.path, this, {
  1310. method: method,
  1311. args: slice.call(arguments),
  1312. result: result
  1313. })
  1314. return result
  1315. }, !hasProto)
  1316. })
  1317. // Augment it with several convenience methods
  1318. var extensions = {
  1319. remove: function (index) {
  1320. if (typeof index !== 'number') index = this.indexOf(index)
  1321. return this.splice(index, 1)[0]
  1322. },
  1323. replace: function (index, data) {
  1324. if (typeof index !== 'number') index = this.indexOf(index)
  1325. if (this[index] !== undefined) return this.splice(index, 1, data)[0]
  1326. },
  1327. mutateFilter: function (fn) {
  1328. var i = this.length
  1329. while (i--) {
  1330. if (!fn(this[i])) this.splice(i, 1)
  1331. }
  1332. return this
  1333. }
  1334. }
  1335. for (var method in extensions) {
  1336. def(ArrayProxy, method, extensions[method], !hasProto)
  1337. }
  1338. /**
  1339. * Watch an object based on type
  1340. */
  1341. function watch (obj, path, observer) {
  1342. var type = typeOf(obj)
  1343. if (type === 'Object') {
  1344. watchObject(obj, path, observer)
  1345. } else if (type === 'Array') {
  1346. watchArray(obj, path, observer)
  1347. }
  1348. }
  1349. /**
  1350. * Watch an Object, recursive.
  1351. */
  1352. function watchObject (obj, path, observer) {
  1353. for (var key in obj) {
  1354. var keyPrefix = key.charAt(0)
  1355. if (keyPrefix !== '$' && keyPrefix !== '_') {
  1356. bind(obj, key, path, observer)
  1357. }
  1358. }
  1359. }
  1360. /**
  1361. * Watch an Array, overload mutation methods
  1362. * and add augmentations by intercepting the prototype chain
  1363. */
  1364. function watchArray (arr, path, observer) {
  1365. def(arr, '__observer__', observer)
  1366. observer.path = path
  1367. if (hasProto) {
  1368. arr.__proto__ = ArrayProxy
  1369. } else {
  1370. for (var key in ArrayProxy) {
  1371. def(arr, key, ArrayProxy[key])
  1372. }
  1373. }
  1374. }
  1375. /**
  1376. * Define accessors for a property on an Object
  1377. * so it emits get/set events.
  1378. * Then watch the value itself.
  1379. */
  1380. function bind (obj, key, path, observer) {
  1381. var val = obj[key],
  1382. watchable = isWatchable(val),
  1383. values = observer.values,
  1384. fullKey = (path ? path + '.' : '') + key
  1385. values[fullKey] = val
  1386. // emit set on bind
  1387. // this means when an object is observed it will emit
  1388. // a first batch of set events.
  1389. observer.emit('set', fullKey, val)
  1390. Object.defineProperty(obj, key, {
  1391. enumerable: true,
  1392. get: function () {
  1393. // only emit get on tip values
  1394. if (!watchable) observer.emit('get', fullKey)
  1395. return values[fullKey]
  1396. },
  1397. set: function (newVal) {
  1398. values[fullKey] = newVal
  1399. observer.emit('set', fullKey, newVal)
  1400. watch(newVal, fullKey, observer)
  1401. }
  1402. })
  1403. watch(val, fullKey, observer)
  1404. }
  1405. /**
  1406. * Check if a value is watchable
  1407. */
  1408. function isWatchable (obj) {
  1409. var type = typeOf(obj)
  1410. return type === 'Object' || type === 'Array'
  1411. }
  1412. /**
  1413. * When a value that is already converted is
  1414. * observed again by another observer, we can skip
  1415. * the watch conversion and simply emit set event for
  1416. * all of its properties.
  1417. */
  1418. function emitSet (obj, observer) {
  1419. if (typeOf(obj) === 'Array') {
  1420. observer.emit('set', 'length', obj.length)
  1421. } else {
  1422. var key, val, values = observer.values
  1423. for (key in observer.values) {
  1424. val = values[key]
  1425. observer.emit('set', key, val)
  1426. }
  1427. }
  1428. }
  1429. module.exports = {
  1430. // used in sd-repeat
  1431. watchArray: watchArray,
  1432. /**
  1433. * Observe an object with a given path,
  1434. * and proxy get/set/mutate events to the provided observer.
  1435. */
  1436. observe: function (obj, rawPath, observer) {
  1437. if (isWatchable(obj)) {
  1438. var path = rawPath + '.',
  1439. ob, alreadyConverted = !!obj.__observer__
  1440. if (!alreadyConverted) {
  1441. def(obj, '__observer__', new Emitter())
  1442. }
  1443. ob = obj.__observer__
  1444. ob.values = ob.values || {}
  1445. var proxies = observer.proxies[path] = {
  1446. get: function (key) {
  1447. observer.emit('get', path + key)
  1448. },
  1449. set: function (key, val) {
  1450. observer.emit('set', path + key, val)
  1451. },
  1452. mutate: function (key, val, mutation) {
  1453. // if the Array is a root value
  1454. // the key will be null
  1455. var fixedPath = key ? path + key : rawPath
  1456. observer.emit('mutate', fixedPath, val, mutation)
  1457. // also emit set for Array's length when it mutates
  1458. var m = mutation.method
  1459. if (m !== 'sort' && m !== 'reverse') {
  1460. observer.emit('set', fixedPath + '.length', val.length)
  1461. }
  1462. }
  1463. }
  1464. ob
  1465. .on('get', proxies.get)
  1466. .on('set', proxies.set)
  1467. .on('mutate', proxies.mutate)
  1468. if (alreadyConverted) {
  1469. emitSet(obj, ob, rawPath)
  1470. } else {
  1471. watch(obj, null, ob)
  1472. }
  1473. }
  1474. },
  1475. /**
  1476. * Cancel observation, turn off the listeners.
  1477. */
  1478. unobserve: function (obj, path, observer) {
  1479. if (!obj || !obj.__observer__) return
  1480. path = path + '.'
  1481. var proxies = observer.proxies[path]
  1482. obj.__observer__
  1483. .off('get', proxies.get)
  1484. .off('set', proxies.set)
  1485. .off('mutate', proxies.mutate)
  1486. observer.proxies[path] = null
  1487. }
  1488. }
  1489. });
  1490. require.register("seed/src/directive.js", function(exports, require, module){
  1491. var config = require('./config'),
  1492. utils = require('./utils'),
  1493. directives = require('./directives'),
  1494. filters = require('./filters')
  1495. var KEY_RE = /^[^\|]+/,
  1496. ARG_RE = /([^:]+):(.+)$/,
  1497. FILTERS_RE = /\|[^\|]+/g,
  1498. FILTER_TOKEN_RE = /[^\s']+|'[^']+'/g,
  1499. NESTING_RE = /^\^+/,
  1500. SINGLE_VAR_RE = /^[\w\.\$]+$/
  1501. /**
  1502. * Directive class
  1503. * represents a single directive instance in the DOM
  1504. */
  1505. function Directive (definition, directiveName, expression, rawKey, compiler, node) {
  1506. this.compiler = compiler
  1507. this.vm = compiler.vm
  1508. this.el = node
  1509. // mix in properties from the directive definition
  1510. if (typeof definition === 'function') {
  1511. this._update = definition
  1512. } else {
  1513. for (var prop in definition) {
  1514. if (prop === 'unbind' || prop === 'update') {
  1515. this['_' + prop] = definition[prop]
  1516. } else {
  1517. this[prop] = definition[prop]
  1518. }
  1519. }
  1520. }
  1521. this.name = directiveName
  1522. this.expression = expression.trim()
  1523. this.rawKey = rawKey
  1524. parseKey(this, rawKey)
  1525. this.isExp = !SINGLE_VAR_RE.test(this.key)
  1526. var filterExps = expression.match(FILTERS_RE)
  1527. if (filterExps) {
  1528. this.filters = []
  1529. var i = 0, l = filterExps.length, filter
  1530. for (; i < l; i++) {
  1531. filter = parseFilter(filterExps[i], this.compiler)
  1532. if (filter) this.filters.push(filter)
  1533. }
  1534. if (!this.filters.length) this.filters = null
  1535. } else {
  1536. this.filters = null
  1537. }
  1538. }
  1539. var DirProto = Directive.prototype
  1540. /**
  1541. * parse a key, extract argument and nesting/root info
  1542. */
  1543. function parseKey (dir, rawKey) {
  1544. var argMatch = rawKey.match(ARG_RE)
  1545. var key = argMatch
  1546. ? argMatch[2].trim()
  1547. : rawKey.trim()
  1548. dir.arg = argMatch
  1549. ? argMatch[1].trim()
  1550. : null
  1551. var nesting = key.match(NESTING_RE)
  1552. dir.nesting = nesting
  1553. ? nesting[0].length
  1554. : false
  1555. dir.root = key.charAt(0) === '$'
  1556. if (dir.nesting) {
  1557. key = key.replace(NESTING_RE, '')
  1558. } else if (dir.root) {
  1559. key = key.slice(1)
  1560. }
  1561. dir.key = key
  1562. }
  1563. /**
  1564. * parse a filter expression
  1565. */
  1566. function parseFilter (filter, compiler) {
  1567. var tokens = filter.slice(1).match(FILTER_TOKEN_RE)
  1568. if (!tokens) return
  1569. tokens = tokens.map(function (token) {
  1570. return token.replace(/'/g, '').trim()
  1571. })
  1572. var name = tokens[0],
  1573. apply = compiler.getOption('filters', name) || filters[name]
  1574. if (!apply) {
  1575. utils.warn('Unknown filter: ' + name)
  1576. return
  1577. }
  1578. return {
  1579. name : name,
  1580. apply : apply,
  1581. args : tokens.length > 1
  1582. ? tokens.slice(1)
  1583. : null
  1584. }
  1585. }
  1586. /**
  1587. * called when a new value is set
  1588. * for computed properties, this will only be called once
  1589. * during initialization.
  1590. */
  1591. DirProto.update = function (value, init) {
  1592. if (!init && value === this.value) return
  1593. this.value = value
  1594. this.apply(value)
  1595. }
  1596. /**
  1597. * -- computed property only --
  1598. * called when a dependency has changed
  1599. */
  1600. DirProto.refresh = function (value) {
  1601. // pass element and viewmodel info to the getter
  1602. // enables context-aware bindings
  1603. if (value) this.value = value
  1604. value = this.value.get({
  1605. el: this.el,
  1606. vm: this.vm
  1607. })
  1608. if (value && value === this.computedValue) return
  1609. this.computedValue = value
  1610. this.apply(value)
  1611. }
  1612. /**
  1613. * Actually invoking the _update from the directive's definition
  1614. */
  1615. DirProto.apply = function (value) {
  1616. this._update(
  1617. this.filters
  1618. ? this.applyFilters(value)
  1619. : value
  1620. )
  1621. }
  1622. /**
  1623. * pipe the value through filters
  1624. */
  1625. DirProto.applyFilters = function (value) {
  1626. var filtered = value, filter
  1627. for (var i = 0, l = this.filters.length; i < l; i++) {
  1628. filter = this.filters[i]
  1629. filtered = filter.apply(filtered, filter.args)
  1630. }
  1631. return filtered
  1632. }
  1633. /**
  1634. * Unbind diretive
  1635. * @ param {Boolean} update
  1636. * Sometimes we call unbind before an update (i.e. not destroy)
  1637. * just to teardown previous stuff, in that case we do not want
  1638. * to null everything.
  1639. */
  1640. DirProto.unbind = function (update) {
  1641. // this can be called before the el is even assigned...
  1642. if (!this.el) return
  1643. if (this._unbind) this._unbind(update)
  1644. if (!update) this.vm = this.el = this.binding = this.compiler = null
  1645. }
  1646. /**
  1647. * make sure the directive and expression is valid
  1648. * before we create an instance
  1649. */
  1650. Directive.parse = function (dirname, expression, compiler, node) {
  1651. var prefix = config.prefix
  1652. if (dirname.indexOf(prefix) === -1) return null
  1653. dirname = dirname.slice(prefix.length + 1)
  1654. var dir = compiler.getOption('directives', dirname) || directives[dirname],
  1655. keyMatch = expression.match(KEY_RE),
  1656. rawKey = keyMatch && keyMatch[0].trim()
  1657. if (!dir) utils.warn('unknown directive: ' + dirname)
  1658. if (!rawKey) utils.warn('invalid directive expression: ' + expression)
  1659. return dir && rawKey
  1660. ? new Directive(dir, dirname, expression, rawKey, compiler, node)
  1661. : null
  1662. }
  1663. module.exports = Directive
  1664. });
  1665. require.register("seed/src/exp-parser.js", function(exports, require, module){
  1666. // Variable extraction scooped from https://github.com/RubyLouvre/avalon
  1667. var KEYWORDS =
  1668. // keywords
  1669. 'break,case,catch,continue,debugger,default,delete,do,else,false'
  1670. + ',finally,for,function,if,in,instanceof,new,null,return,switch,this'
  1671. + ',throw,true,try,typeof,var,void,while,with'
  1672. // reserved
  1673. + ',abstract,boolean,byte,char,class,const,double,enum,export,extends'
  1674. + ',final,float,goto,implements,import,int,interface,long,native'
  1675. + ',package,private,protected,public,short,static,super,synchronized'
  1676. + ',throws,transient,volatile'
  1677. // ECMA 5 - use strict
  1678. + ',arguments,let,yield'
  1679. + ',undefined',
  1680. KEYWORDS_RE = new RegExp(["\\b" + KEYWORDS.replace(/,/g, '\\b|\\b') + "\\b"].join('|'), 'g'),
  1681. REMOVE_RE = /\/\*(?:.|\n)*?\*\/|\/\/[^\n]*\n|\/\/[^\n]*$|'[^']*'|"[^"]*"|[\s\t\n]*\.[\s\t\n]*[$\w\.]+/g,
  1682. SPLIT_RE = /[^\w$]+/g,
  1683. NUMBER_RE = /\b\d[^,]*/g,
  1684. BOUNDARY_RE = /^,+|,+$/g
  1685. function getVariables (code) {
  1686. code = code
  1687. .replace(REMOVE_RE, '')
  1688. .replace(SPLIT_RE, ',')
  1689. .replace(KEYWORDS_RE, '')
  1690. .replace(NUMBER_RE, '')
  1691. .replace(BOUNDARY_RE, '')
  1692. return code
  1693. ? code.split(/,+/)
  1694. : []
  1695. }
  1696. module.exports = {
  1697. /**
  1698. * Parse and create an anonymous computed property getter function
  1699. * from an arbitrary expression.
  1700. */
  1701. parse: function (exp) {
  1702. // extract variable names
  1703. var vars = getVariables(exp)
  1704. if (!vars.length) return null
  1705. var args = [],
  1706. v, i, keyPrefix,
  1707. l = vars.length,
  1708. hash = {}
  1709. for (i = 0; i < l; i++) {
  1710. v = vars[i]
  1711. // avoid duplicate keys
  1712. if (hash[v]) continue
  1713. hash[v] = v
  1714. // push assignment
  1715. keyPrefix = v.charAt(0)
  1716. args.push(v + (
  1717. (keyPrefix === '$' || keyPrefix === '_')
  1718. ? '=this.' + v
  1719. : '=this.$get("' + v + '")'
  1720. ))
  1721. }
  1722. args = 'var ' + args.join(',') + ';return ' + exp
  1723. /* jshint evil: true */
  1724. return {
  1725. getter: new Function(args),
  1726. vars: Object.keys(hash)
  1727. }
  1728. }
  1729. }
  1730. });
  1731. require.register("seed/src/text-parser.js", function(exports, require, module){
  1732. var BINDING_RE = /\{\{(.+?)\}\}/
  1733. module.exports = {
  1734. /**
  1735. * Parse a piece of text, return an array of tokens
  1736. */
  1737. parse: function (text) {
  1738. if (!BINDING_RE.test(text)) return null
  1739. var m, i, tokens = []
  1740. do {
  1741. m = text.match(BINDING_RE)
  1742. if (!m) break
  1743. i = m.index
  1744. if (i > 0) tokens.push(text.slice(0, i))
  1745. tokens.push({ key: m[1].trim() })
  1746. text = text.slice(i + m[0].length)
  1747. } while (true)
  1748. if (text.length) tokens.push(text)
  1749. return tokens
  1750. }
  1751. }
  1752. });
  1753. require.register("seed/src/deps-parser.js", function(exports, require, module){
  1754. var Emitter = require('./emitter'),
  1755. utils = require('./utils'),
  1756. observer = new Emitter()
  1757. /**
  1758. * Auto-extract the dependencies of a computed property
  1759. * by recording the getters triggered when evaluating it.
  1760. */
  1761. function catchDeps (binding) {
  1762. utils.log('\n─ ' + binding.key)
  1763. var depsHash = {}
  1764. observer.on('get', function (dep) {
  1765. if (depsHash[dep.key]) return
  1766. depsHash[dep.key] = 1
  1767. utils.log(' └─ ' + dep.key)
  1768. binding.deps.push(dep)
  1769. dep.subs.push(binding)
  1770. })
  1771. binding.value.get()
  1772. observer.off('get')
  1773. }
  1774. module.exports = {
  1775. /**
  1776. * the observer that catches events triggered by getters
  1777. */
  1778. observer: observer,
  1779. /**
  1780. * parse a list of computed property bindings
  1781. */
  1782. parse: function (bindings) {
  1783. utils.log('\nparsing dependencies...')
  1784. observer.isObserving = true
  1785. bindings.forEach(catchDeps)
  1786. observer.isObserving = false
  1787. utils.log('\ndone.')
  1788. }
  1789. }
  1790. });
  1791. require.register("seed/src/filters.js", function(exports, require, module){
  1792. var keyCodes = {
  1793. enter : 13,
  1794. tab : 9,
  1795. 'delete' : 46,
  1796. up : 38,
  1797. left : 37,
  1798. right : 39,
  1799. down : 40,
  1800. esc : 27
  1801. }
  1802. module.exports = {
  1803. capitalize: function (value) {
  1804. if (!value && value !== 0) return ''
  1805. value = value.toString()
  1806. return value.charAt(0).toUpperCase() + value.slice(1)
  1807. },
  1808. uppercase: function (value) {
  1809. return (value || value === 0)
  1810. ? value.toString().toUpperCase()
  1811. : ''
  1812. },
  1813. lowercase: function (value) {
  1814. return (value || value === 0)
  1815. ? value.toString().toLowerCase()
  1816. : ''
  1817. },
  1818. /**
  1819. * args: an array of strings corresponding to
  1820. * the single, double, triple ... forms of the word to
  1821. * be pluralized. When the number to be pluralized
  1822. * exceeds the length of the args, it will use the last
  1823. * entry in the array.
  1824. *
  1825. * e.g. ['single', 'double', 'triple', 'multiple']
  1826. */
  1827. pluralize: function (value, args) {
  1828. return args.length > 1
  1829. ? (args[value - 1] || args[args.length - 1])
  1830. : (args[value - 1] || args[0] + 's')
  1831. },
  1832. currency: function (value, args) {
  1833. if (!value && value !== 0) return ''
  1834. var sign = (args && args[0]) || '$',
  1835. s = Math.floor(value).toString(),
  1836. i = s.length % 3,
  1837. h = i > 0 ? (s.slice(0, i) + (s.length > 3 ? ',' : '')) : '',
  1838. f = '.' + value.toFixed(2).slice(-2)
  1839. return sign + h + s.slice(i).replace(/(\d{3})(?=\d)/g, '$1,') + f
  1840. },
  1841. key: function (handler, args) {
  1842. if (!handler) return
  1843. var code = keyCodes[args[0]]
  1844. if (!code) {
  1845. code = parseInt(args[0], 10)
  1846. }
  1847. return function (e) {
  1848. if (e.keyCode === code) {
  1849. handler.call(this, e)
  1850. }
  1851. }
  1852. }
  1853. }
  1854. });
  1855. require.register("seed/src/directives/index.js", function(exports, require, module){
  1856. var utils = require('../utils')
  1857. module.exports = {
  1858. on : require('./on'),
  1859. repeat : require('./repeat'),
  1860. model : require('./model'),
  1861. attr: function (value) {
  1862. this.el.setAttribute(this.arg, value)
  1863. },
  1864. text: function (value) {
  1865. this.el.textContent = utils.toText(value)
  1866. },
  1867. html: function (value) {
  1868. this.el.innerHTML = utils.toText(value)
  1869. },
  1870. style: {
  1871. bind: function () {
  1872. this.arg = convertCSSProperty(this.arg)
  1873. },
  1874. update: function (value) {
  1875. this.el.style[this.arg] = value
  1876. }
  1877. },
  1878. show: function (value) {
  1879. this.el.style.display = value ? '' : 'none'
  1880. },
  1881. visible: function (value) {
  1882. this.el.style.visibility = value ? '' : 'hidden'
  1883. },
  1884. class: function (value) {
  1885. if (this.arg) {
  1886. this.el.classList[value ? 'add' : 'remove'](this.arg)
  1887. } else {
  1888. if (this.lastVal) {
  1889. this.el.classList.remove(this.lastVal)
  1890. }
  1891. this.el.classList.add(value)
  1892. this.lastVal = value
  1893. }
  1894. },
  1895. 'if': {
  1896. bind: function () {
  1897. this.parent = this.el.parentNode
  1898. this.ref = document.createComment('sd-if-' + this.key)
  1899. },
  1900. update: function (value) {
  1901. var attached = !!this.el.parentNode
  1902. if (!this.parent) { // the node was detached when bound
  1903. if (!attached) {
  1904. return
  1905. } else {
  1906. this.parent = this.el.parentNode
  1907. }
  1908. }
  1909. // should always have this.parent if we reach here
  1910. if (!value) {
  1911. if (attached) {
  1912. // insert the reference node
  1913. var next = this.el.nextSibling
  1914. if (next) {
  1915. this.parent.insertBefore(this.ref, next)
  1916. } else {
  1917. this.parent.appendChild(this.ref)
  1918. }
  1919. this.parent.removeChild(this.el)
  1920. }
  1921. } else if (!attached) {
  1922. this.parent.insertBefore(this.el, this.ref)
  1923. this.parent.removeChild(this.ref)
  1924. }
  1925. }
  1926. }
  1927. }
  1928. /**
  1929. * convert hyphen style CSS property to Camel style
  1930. */
  1931. var CONVERT_RE = /-(.)/g
  1932. function convertCSSProperty (prop) {
  1933. if (prop.charAt(0) === '-') prop = prop.slice(1)
  1934. return prop.replace(CONVERT_RE, function (m, char) {
  1935. return char.toUpperCase()
  1936. })
  1937. }
  1938. });
  1939. require.register("seed/src/directives/repeat.js", function(exports, require, module){
  1940. var config = require('../config'),
  1941. Observer = require('../observer'),
  1942. Emitter = require('../emitter'),
  1943. ViewModel // lazy def to avoid circular dependency
  1944. /**
  1945. * Mathods that perform precise DOM manipulation
  1946. * based on mutator method triggered
  1947. */
  1948. var mutationHandlers = {
  1949. push: function (m) {
  1950. var i, l = m.args.length,
  1951. base = this.collection.length - l
  1952. for (i = 0; i < l; i++) {
  1953. this.buildItem(m.args[i], base + i)
  1954. }
  1955. },
  1956. pop: function () {
  1957. var vm = this.vms.pop()
  1958. if (vm) vm.$destroy()
  1959. },
  1960. unshift: function (m) {
  1961. var i, l = m.args.length
  1962. for (i = 0; i < l; i++) {
  1963. this.buildItem(m.args[i], i)
  1964. }
  1965. },
  1966. shift: function () {
  1967. var vm = this.vms.shift()
  1968. if (vm) vm.$destroy()
  1969. },
  1970. splice: function (m) {
  1971. var i, l,
  1972. index = m.args[0],
  1973. removed = m.args[1],
  1974. added = m.args.length - 2,
  1975. removedVMs = this.vms.splice(index, removed)
  1976. for (i = 0, l = removedVMs.length; i < l; i++) {
  1977. removedVMs[i].$destroy()
  1978. }
  1979. for (i = 0; i < added; i++) {
  1980. this.buildItem(m.args[i + 2], index + i)
  1981. }
  1982. },
  1983. sort: function () {
  1984. var key = this.arg,
  1985. vms = this.vms,
  1986. col = this.collection,
  1987. l = col.length,
  1988. sorted = new Array(l),
  1989. i, j, vm, data
  1990. for (i = 0; i < l; i++) {
  1991. data = col[i]
  1992. for (j = 0; j < l; j++) {
  1993. vm = vms[j]
  1994. if (vm[key] === data) {
  1995. sorted[i] = vm
  1996. break
  1997. }
  1998. }
  1999. }
  2000. for (i = 0; i < l; i++) {
  2001. this.container.insertBefore(sorted[i].$el, this.ref)
  2002. }
  2003. this.vms = sorted
  2004. },
  2005. reverse: function () {
  2006. var vms = this.vms
  2007. vms.reverse()
  2008. for (var i = 0, l = vms.length; i < l; i++) {
  2009. this.container.insertBefore(vms[i].$el, this.ref)
  2010. }
  2011. }
  2012. }
  2013. module.exports = {
  2014. bind: function () {
  2015. this.el.removeAttribute(config.prefix + '-repeat')
  2016. var ctn = this.container = this.el.parentNode
  2017. // create a comment node as a reference node for DOM insertions
  2018. this.ref = document.createComment('sd-repeat-' + this.arg)
  2019. ctn.insertBefore(this.ref, this.el)
  2020. ctn.removeChild(this.el)
  2021. this.collection = null
  2022. this.vms = null
  2023. var self = this
  2024. this.mutationListener = function (path, arr, mutation) {
  2025. self.detach()
  2026. var method = mutation.method
  2027. mutationHandlers[method].call(self, mutation)
  2028. if (method !== 'push' && method !== 'pop') {
  2029. self.updateIndexes()
  2030. }
  2031. self.retach()
  2032. }
  2033. },
  2034. update: function (collection) {
  2035. this.unbind(true)
  2036. // attach an object to container to hold handlers
  2037. this.container.sd_dHandlers = {}
  2038. // if initiating with an empty collection, we need to
  2039. // force a compile so that we get all the bindings for
  2040. // dependency extraction.
  2041. if (!this.collection && !collection.length) {
  2042. this.buildItem()
  2043. }
  2044. this.collection = collection
  2045. this.vms = []
  2046. // listen for collection mutation events
  2047. // the collection has been augmented during Binding.set()
  2048. if (!collection.__observer__) Observer.watchArray(collection, null, new Emitter())
  2049. collection.__observer__.on('mutate', this.mutationListener)
  2050. // create child-seeds and append to DOM
  2051. this.detach()
  2052. for (var i = 0, l = collection.length; i < l; i++) {
  2053. this.buildItem(collection[i], i)
  2054. }
  2055. this.retach()
  2056. },
  2057. /**
  2058. * Create a new child VM from a data object
  2059. * passing along compiler options indicating this
  2060. * is a sd-repeat item.
  2061. */
  2062. buildItem: function (data, index) {
  2063. ViewModel = ViewModel || require('../viewmodel')
  2064. var node = this.el.cloneNode(true),
  2065. ctn = this.container,
  2066. vmID = node.getAttribute(config.prefix + '-viewmodel'),
  2067. ChildVM = this.compiler.getOption('vms', vmID) || ViewModel,
  2068. scope = {}
  2069. scope[this.arg] = data || {}
  2070. var item = new ChildVM({
  2071. el: node,
  2072. scope: scope,
  2073. compilerOptions: {
  2074. repeat: true,
  2075. repeatIndex: index,
  2076. repeatPrefix: this.arg,
  2077. parentCompiler: this.compiler,
  2078. delegator: ctn
  2079. }
  2080. })
  2081. if (!data) {
  2082. item.$destroy()
  2083. } else {
  2084. var ref = this.vms.length > index
  2085. ? this.vms[index].$el
  2086. : this.ref
  2087. ctn.insertBefore(node, ref)
  2088. this.vms.splice(index, 0, item)
  2089. }
  2090. },
  2091. /**
  2092. * Update index of each item after a mutation
  2093. */
  2094. updateIndexes: function () {
  2095. var i = this.vms.length
  2096. while (i--) {
  2097. this.vms[i][this.arg].$index = i
  2098. }
  2099. },
  2100. /**
  2101. * Detach/ the container from the DOM before mutation
  2102. * so that batch DOM updates are done in-memory and faster
  2103. */
  2104. detach: function () {
  2105. var c = this.container,
  2106. p = this.parent = c.parentNode
  2107. this.next = c.nextSibling
  2108. if (p) p.removeChild(c)
  2109. },
  2110. retach: function () {
  2111. var n = this.next,
  2112. p = this.parent,
  2113. c = this.container
  2114. if (!p) return
  2115. if (n) {
  2116. p.insertBefore(c, n)
  2117. } else {
  2118. p.appendChild(c)
  2119. }
  2120. },
  2121. unbind: function () {
  2122. if (this.collection) {
  2123. this.collection.__observer__.off('mutate', this.mutationListener)
  2124. var i = this.vms.length
  2125. while (i--) {
  2126. this.vms[i].$destroy()
  2127. }
  2128. }
  2129. var ctn = this.container,
  2130. handlers = ctn.sd_dHandlers
  2131. for (var key in handlers) {
  2132. ctn.removeEventListener(handlers[key].event, handlers[key])
  2133. }
  2134. ctn.sd_dHandlers = null
  2135. }
  2136. }
  2137. });
  2138. require.register("seed/src/directives/on.js", function(exports, require, module){
  2139. var utils = require('../utils')
  2140. function delegateCheck (current, top, identifier) {
  2141. if (current[identifier]) {
  2142. return current
  2143. } else if (current === top) {
  2144. return false
  2145. } else {
  2146. return delegateCheck(current.parentNode, top, identifier)
  2147. }
  2148. }
  2149. module.exports = {
  2150. bind: function () {
  2151. if (this.compiler.repeat) {
  2152. // attach an identifier to the el
  2153. // so it can be matched during event delegation
  2154. this.el[this.expression] = true
  2155. // attach the owner viewmodel of this directive
  2156. this.el.sd_viewmodel = this.vm
  2157. }
  2158. },
  2159. update: function (handler) {
  2160. this.unbind(true)
  2161. if (typeof handler !== 'function') {
  2162. return utils.warn('Directive "on" expects a function value.')
  2163. }
  2164. var compiler = this.compiler,
  2165. event = this.arg,
  2166. ownerVM = this.binding.compiler.vm
  2167. if (compiler.repeat && event !== 'blur' && event !== 'focus') {
  2168. // for each blocks, delegate for better performance
  2169. // focus and blur events dont bubble so exclude them
  2170. var delegator = compiler.delegator,
  2171. identifier = this.expression,
  2172. dHandler = delegator.sd_dHandlers[identifier]
  2173. if (dHandler) return
  2174. // the following only gets run once for the entire each block
  2175. dHandler = delegator.sd_dHandlers[identifier] = function (e) {
  2176. var target = delegateCheck(e.target, delegator, identifier)
  2177. if (target) {
  2178. e.el = target
  2179. e.vm = target.sd_viewmodel
  2180. e.item = e.vm[compiler.repeatPrefix]
  2181. handler.call(ownerVM, e)
  2182. }
  2183. }
  2184. dHandler.event = event
  2185. delegator.addEventListener(event, dHandler)
  2186. } else {
  2187. // a normal, single element handler
  2188. var vm = this.vm
  2189. this.handler = function (e) {
  2190. e.el = e.currentTarget
  2191. e.vm = vm
  2192. if (compiler.repeat) {
  2193. e.item = vm[compiler.repeatPrefix]
  2194. }
  2195. handler.call(ownerVM, e)
  2196. }
  2197. this.el.addEventListener(event, this.handler)
  2198. }
  2199. },
  2200. unbind: function (update) {
  2201. this.el.removeEventListener(this.arg, this.handler)
  2202. this.handler = null
  2203. if (!update) this.el.sd_viewmodel = null
  2204. }
  2205. }
  2206. });
  2207. require.register("seed/src/directives/model.js", function(exports, require, module){
  2208. var utils = require('../utils')
  2209. module.exports = {
  2210. bind: function () {
  2211. var self = this,
  2212. el = self.el,
  2213. type = el.type
  2214. self.lock = false
  2215. // determine what event to listen to
  2216. self.event =
  2217. (self.compiler.options.lazy ||
  2218. el.tagName === 'SELECT' ||
  2219. type === 'checkbox' ||
  2220. type === 'radio')
  2221. ? 'change'
  2222. : 'keyup'
  2223. // determin the attribute to change when updating
  2224. var attr = type === 'checkbox'
  2225. ? 'checked'
  2226. : 'value'
  2227. // attach listener
  2228. self.set = function () {
  2229. self.lock = true
  2230. self.vm.$set(self.key, el[attr])
  2231. self.lock = false
  2232. }
  2233. el.addEventListener(self.event, self.set)
  2234. },
  2235. update: function (value) {
  2236. /* jshint eqeqeq: false */
  2237. var self = this,
  2238. el = self.el
  2239. if (self.lock) return
  2240. if (el.tagName === 'SELECT') { // select dropdown
  2241. // setting <select>'s value in IE9 doesn't work
  2242. var o = el.options,
  2243. i = o.length,
  2244. index = -1
  2245. while (i--) {
  2246. if (o[i].value == value) {
  2247. index = i
  2248. break
  2249. }
  2250. }
  2251. o.selectedIndex = index
  2252. } else if (el.type === 'radio') { // radio button
  2253. el.checked = value == el.value
  2254. } else if (el.type === 'checkbox') { // checkbox
  2255. el.checked = !!value
  2256. } else {
  2257. el.value = utils.toText(value)
  2258. }
  2259. },
  2260. unbind: function () {
  2261. this.el.removeEventListener(this.event, this.set)
  2262. }
  2263. }
  2264. });
  2265. require.alias("component-emitter/index.js", "seed/deps/emitter/index.js");
  2266. require.alias("component-emitter/index.js", "emitter/index.js");
  2267. require.alias("component-indexof/index.js", "component-emitter/deps/indexof/index.js");
  2268. require.alias("seed/src/main.js", "seed/index.js");