seed.js 68 KB

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