seed.js 45 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835
  1. ;(function (undefined) {
  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.exports) {
  26. module.exports = {};
  27. module.client = module.component = true;
  28. module.call(this, module.exports, require.relative(resolved), module);
  29. }
  30. return module.exports;
  31. }
  32. /**
  33. * Registered modules.
  34. */
  35. require.modules = {};
  36. /**
  37. * Registered aliases.
  38. */
  39. require.aliases = {};
  40. /**
  41. * Resolve `path`.
  42. *
  43. * Lookup:
  44. *
  45. * - PATH/index.js
  46. * - PATH.js
  47. * - PATH
  48. *
  49. * @param {String} path
  50. * @return {String} path or null
  51. * @api private
  52. */
  53. require.resolve = function(path) {
  54. if (path.charAt(0) === '/') path = path.slice(1);
  55. var paths = [
  56. path,
  57. path + '.js',
  58. path + '.json',
  59. path + '/index.js',
  60. path + '/index.json'
  61. ];
  62. for (var i = 0; i < paths.length; i++) {
  63. var path = paths[i];
  64. if (require.modules.hasOwnProperty(path)) return path;
  65. if (require.aliases.hasOwnProperty(path)) return require.aliases[path];
  66. }
  67. };
  68. /**
  69. * Normalize `path` relative to the current path.
  70. *
  71. * @param {String} curr
  72. * @param {String} path
  73. * @return {String}
  74. * @api private
  75. */
  76. require.normalize = function(curr, path) {
  77. var segs = [];
  78. if ('.' != path.charAt(0)) return path;
  79. curr = curr.split('/');
  80. path = path.split('/');
  81. for (var i = 0; i < path.length; ++i) {
  82. if ('..' == path[i]) {
  83. curr.pop();
  84. } else if ('.' != path[i] && '' != path[i]) {
  85. segs.push(path[i]);
  86. }
  87. }
  88. return curr.concat(segs).join('/');
  89. };
  90. /**
  91. * Register module at `path` with callback `definition`.
  92. *
  93. * @param {String} path
  94. * @param {Function} definition
  95. * @api private
  96. */
  97. require.register = function(path, definition) {
  98. require.modules[path] = definition;
  99. };
  100. /**
  101. * Alias a module definition.
  102. *
  103. * @param {String} from
  104. * @param {String} to
  105. * @api private
  106. */
  107. require.alias = function(from, to) {
  108. if (!require.modules.hasOwnProperty(from)) {
  109. throw new Error('Failed to alias "' + from + '", it does not exist');
  110. }
  111. require.aliases[to] = from;
  112. };
  113. /**
  114. * Return a require function relative to the `parent` path.
  115. *
  116. * @param {String} parent
  117. * @return {Function}
  118. * @api private
  119. */
  120. require.relative = function(parent) {
  121. var p = require.normalize(parent, '..');
  122. /**
  123. * lastIndexOf helper.
  124. */
  125. function lastIndexOf(arr, obj) {
  126. var i = arr.length;
  127. while (i--) {
  128. if (arr[i] === obj) return i;
  129. }
  130. return -1;
  131. }
  132. /**
  133. * The relative require() itself.
  134. */
  135. function localRequire(path) {
  136. var resolved = localRequire.resolve(path);
  137. return require(resolved, parent, path);
  138. }
  139. /**
  140. * Resolve relative to the parent.
  141. */
  142. localRequire.resolve = function(path) {
  143. var c = path.charAt(0);
  144. if ('/' == c) return path.slice(1);
  145. if ('.' == c) return require.normalize(p, path);
  146. // resolve deps by returning
  147. // the dep in the nearest "deps"
  148. // directory
  149. var segs = parent.split('/');
  150. var i = lastIndexOf(segs, 'deps') + 1;
  151. if (!i) i = 0;
  152. path = segs.slice(0, i + 1).join('/') + '/deps/' + path;
  153. return path;
  154. };
  155. /**
  156. * Check if module is defined at `path`.
  157. */
  158. localRequire.exists = function(path) {
  159. return require.modules.hasOwnProperty(localRequire.resolve(path));
  160. };
  161. return localRequire;
  162. };
  163. require.register("component-indexof/index.js", function(exports, require, module){
  164. module.exports = function(arr, obj){
  165. if (arr.indexOf) return arr.indexOf(obj);
  166. for (var i = 0; i < arr.length; ++i) {
  167. if (arr[i] === obj) return i;
  168. }
  169. return -1;
  170. };
  171. });
  172. require.register("component-emitter/index.js", function(exports, require, module){
  173. /**
  174. * Module dependencies.
  175. */
  176. var index = require('indexof');
  177. /**
  178. * Expose `Emitter`.
  179. */
  180. module.exports = Emitter;
  181. /**
  182. * Initialize a new `Emitter`.
  183. *
  184. * @api public
  185. */
  186. function Emitter(obj) {
  187. if (obj) return mixin(obj);
  188. };
  189. /**
  190. * Mixin the emitter properties.
  191. *
  192. * @param {Object} obj
  193. * @return {Object}
  194. * @api private
  195. */
  196. function mixin(obj) {
  197. for (var key in Emitter.prototype) {
  198. obj[key] = Emitter.prototype[key];
  199. }
  200. return obj;
  201. }
  202. /**
  203. * Listen on the given `event` with `fn`.
  204. *
  205. * @param {String} event
  206. * @param {Function} fn
  207. * @return {Emitter}
  208. * @api public
  209. */
  210. Emitter.prototype.on = function(event, fn){
  211. this._callbacks = this._callbacks || {};
  212. (this._callbacks[event] = this._callbacks[event] || [])
  213. .push(fn);
  214. return this;
  215. };
  216. /**
  217. * Adds an `event` listener that will be invoked a single
  218. * time then automatically removed.
  219. *
  220. * @param {String} event
  221. * @param {Function} fn
  222. * @return {Emitter}
  223. * @api public
  224. */
  225. Emitter.prototype.once = function(event, fn){
  226. var self = this;
  227. this._callbacks = this._callbacks || {};
  228. function on() {
  229. self.off(event, on);
  230. fn.apply(this, arguments);
  231. }
  232. fn._off = on;
  233. this.on(event, on);
  234. return this;
  235. };
  236. /**
  237. * Remove the given callback for `event` or all
  238. * registered callbacks.
  239. *
  240. * @param {String} event
  241. * @param {Function} fn
  242. * @return {Emitter}
  243. * @api public
  244. */
  245. Emitter.prototype.off =
  246. Emitter.prototype.removeListener =
  247. Emitter.prototype.removeAllListeners = function(event, fn){
  248. this._callbacks = this._callbacks || {};
  249. // all
  250. if (0 == arguments.length) {
  251. this._callbacks = {};
  252. return this;
  253. }
  254. // specific event
  255. var callbacks = this._callbacks[event];
  256. if (!callbacks) return this;
  257. // remove all handlers
  258. if (1 == arguments.length) {
  259. delete this._callbacks[event];
  260. return this;
  261. }
  262. // remove specific handler
  263. var i = index(callbacks, fn._off || fn);
  264. if (~i) callbacks.splice(i, 1);
  265. return this;
  266. };
  267. /**
  268. * Emit `event` with the given args.
  269. *
  270. * @param {String} event
  271. * @param {Mixed} ...
  272. * @return {Emitter}
  273. */
  274. Emitter.prototype.emit = function(event){
  275. this._callbacks = this._callbacks || {};
  276. var args = [].slice.call(arguments, 1)
  277. , callbacks = this._callbacks[event];
  278. if (callbacks) {
  279. callbacks = callbacks.slice(0);
  280. for (var i = 0, len = callbacks.length; i < len; ++i) {
  281. callbacks[i].apply(this, args);
  282. }
  283. }
  284. return this;
  285. };
  286. /**
  287. * Return array of callbacks for `event`.
  288. *
  289. * @param {String} event
  290. * @return {Array}
  291. * @api public
  292. */
  293. Emitter.prototype.listeners = function(event){
  294. this._callbacks = this._callbacks || {};
  295. return this._callbacks[event] || [];
  296. };
  297. /**
  298. * Check if this emitter has `event` handlers.
  299. *
  300. * @param {String} event
  301. * @return {Boolean}
  302. * @api public
  303. */
  304. Emitter.prototype.hasListeners = function(event){
  305. return !! this.listeners(event).length;
  306. };
  307. });
  308. require.register("seed/src/main.js", function(exports, require, module){
  309. var config = require('./config'),
  310. Seed = require('./seed'),
  311. directives = require('./directives'),
  312. filters = require('./filters'),
  313. textParser = require('./text-parser')
  314. var controllers = config.controllers,
  315. datum = config.datum,
  316. api = {},
  317. reserved = ['datum', 'controllers'],
  318. booted = false
  319. /*
  320. * Store a piece of plain data in config.datum
  321. * so it can be consumed by sd-data
  322. */
  323. api.data = function (id, data) {
  324. if (!data) return datum[id]
  325. datum[id] = data
  326. }
  327. /*
  328. * Store a controller function in config.controllers
  329. * so it can be consumed by sd-controller
  330. */
  331. api.controller = function (id, extensions) {
  332. if (!extensions) return controllers[id]
  333. controllers[id] = extensions
  334. }
  335. /*
  336. * Allows user to create a custom directive
  337. */
  338. api.directive = function (name, fn) {
  339. if (!fn) return directives[name]
  340. directives[name] = fn
  341. }
  342. /*
  343. * Allows user to create a custom filter
  344. */
  345. api.filter = function (name, fn) {
  346. if (!fn) return filters[name]
  347. filters[name] = fn
  348. }
  349. /*
  350. * Bootstrap the whole thing
  351. * by creating a Seed instance for top level nodes
  352. * that has either sd-controller or sd-data
  353. */
  354. api.bootstrap = function (opts) {
  355. if (booted) return
  356. if (opts) {
  357. for (var key in opts) {
  358. if (reserved.indexOf(key) === -1) {
  359. config[key] = opts[key]
  360. }
  361. }
  362. }
  363. textParser.buildRegex()
  364. var el,
  365. ctrlSlt = '[' + config.prefix + '-controller]',
  366. dataSlt = '[' + config.prefix + '-data]',
  367. seeds = []
  368. /* jshint boss: true */
  369. while (el = document.querySelector(ctrlSlt) || document.querySelector(dataSlt)) {
  370. seeds.push((new Seed(el)).scope)
  371. }
  372. booted = true
  373. return seeds.length > 1 ? seeds : seeds[0]
  374. }
  375. module.exports = api
  376. });
  377. require.register("seed/src/config.js", function(exports, require, module){
  378. module.exports = {
  379. prefix : 'sd',
  380. debug : false,
  381. datum : {},
  382. controllers : {},
  383. interpolateTags : {
  384. open : '{{',
  385. close : '}}'
  386. },
  387. log: function (msg) {
  388. if (this.debug) console.log(msg)
  389. },
  390. warn: function(msg) {
  391. if (this.debug) console.warn(msg)
  392. }
  393. }
  394. });
  395. require.register("seed/src/utils.js", function(exports, require, module){
  396. var Emitter = require('emitter'),
  397. toString = Object.prototype.toString,
  398. aproto = Array.prototype,
  399. arrayMutators = ['push','pop','shift','unshift','splice','sort','reverse']
  400. var arrayAugmentations = {
  401. remove: function (index) {
  402. if (typeof index !== 'number') index = index.$index
  403. this.splice(index, 1)
  404. },
  405. replace: function (index, data) {
  406. if (typeof index !== 'number') index = index.$index
  407. this.splice(index, 1, data)
  408. }
  409. }
  410. /*
  411. * get accurate type of an object
  412. */
  413. function typeOf (obj) {
  414. return toString.call(obj).slice(8, -1)
  415. }
  416. /*
  417. * Recursively dump stuff...
  418. */
  419. function dumpValue (val) {
  420. var type = typeOf(val)
  421. if (type === 'Array') {
  422. return val.map(dumpValue)
  423. } else if (type === 'Object') {
  424. if (val.get) { // computed property
  425. return val.get()
  426. } else { // object / child scope
  427. var ret = {}
  428. for (var key in val) {
  429. if (val.hasOwnProperty(key) &&
  430. typeof val[key] !== 'function' &&
  431. key.charAt(0) !== '$')
  432. {
  433. ret[key] = dumpValue(val[key])
  434. }
  435. }
  436. return ret
  437. }
  438. } else if (type !== 'Function') {
  439. return val
  440. }
  441. }
  442. module.exports = {
  443. typeOf: typeOf,
  444. dumpValue: dumpValue,
  445. /*
  446. * Get a value from an object based on a path array
  447. */
  448. getNestedValue: function (obj, path) {
  449. if (path.length === 1) return obj[path[0]]
  450. var i = 0
  451. /* jshint boss: true */
  452. while (obj[path[i]]) {
  453. obj = obj[path[i]]
  454. i++
  455. }
  456. return i === path.length ? obj : undefined
  457. },
  458. /*
  459. * augment an Array so that it emit events when mutated
  460. */
  461. watchArray: function (collection) {
  462. Emitter(collection)
  463. arrayMutators.forEach(function (method) {
  464. collection[method] = function () {
  465. var result = aproto[method].apply(this, arguments)
  466. collection.emit('mutate', {
  467. method: method,
  468. args: aproto.slice.call(arguments),
  469. result: result
  470. })
  471. }
  472. })
  473. for (var method in arrayAugmentations) {
  474. collection[method] = arrayAugmentations[method]
  475. }
  476. }
  477. }
  478. });
  479. require.register("seed/src/seed.js", function(exports, require, module){
  480. var config = require('./config'),
  481. Scope = require('./scope'),
  482. Binding = require('./binding'),
  483. DirectiveParser = require('./directive-parser'),
  484. TextParser = require('./text-parser'),
  485. depsParser = require('./deps-parser')
  486. var slice = Array.prototype.slice,
  487. ctrlAttr = config.prefix + '-controller',
  488. eachAttr = config.prefix + '-each'
  489. /*
  490. * The main ViewModel class
  491. * scans a node and parse it to populate data bindings
  492. */
  493. function Seed (el, options) {
  494. config.log('\ncreated new Seed instance.\n')
  495. if (typeof el === 'string') {
  496. el = document.querySelector(el)
  497. }
  498. this.el = el
  499. el.seed = this
  500. this._bindings = {}
  501. // list of computed properties that need to parse dependencies for
  502. this._computed = []
  503. // list of bindings that has dynamic context dependencies
  504. this._contextBindings = []
  505. // copy options
  506. options = options || {}
  507. for (var op in options) {
  508. this[op] = options[op]
  509. }
  510. // check if there's passed in data
  511. var dataAttr = config.prefix + '-data',
  512. dataId = el.getAttribute(dataAttr),
  513. data = (options && options.data) || config.datum[dataId]
  514. if (dataId && !data) {
  515. config.warn('data "' + dataId + '" is not defined.')
  516. }
  517. data = data || {}
  518. el.removeAttribute(dataAttr)
  519. // if the passed in data is the scope of a Seed instance,
  520. // make a copy from it
  521. if (data.$seed instanceof Seed) {
  522. data = data.$dump()
  523. }
  524. // initialize the scope object
  525. var key,
  526. scope = this.scope = new Scope(this, options)
  527. // copy data
  528. for (key in data) {
  529. scope[key] = data[key]
  530. }
  531. // if has controller function, apply it so we have all the user definitions
  532. var ctrlID = el.getAttribute(ctrlAttr)
  533. if (ctrlID) {
  534. el.removeAttribute(ctrlAttr)
  535. var factory = config.controllers[ctrlID]
  536. if (factory) {
  537. factory(this.scope)
  538. } else {
  539. config.warn('controller "' + ctrlID + '" is not defined.')
  540. }
  541. }
  542. // now parse the DOM
  543. this._compileNode(el, true)
  544. // for anything in scope but not binded in DOM, create bindings for them
  545. for (key in scope) {
  546. if (key.charAt(0) !== '$' && !this._bindings[key]) {
  547. this._createBinding(key)
  548. }
  549. }
  550. // extract dependencies for computed properties
  551. if (this._computed.length) depsParser.parse(this._computed)
  552. delete this._computed
  553. if (this._contextBindings.length) this._bindContexts(this._contextBindings)
  554. delete this._contextBindings
  555. }
  556. // for better compression
  557. var SeedProto = Seed.prototype
  558. /*
  559. * Compile a DOM node (recursive)
  560. */
  561. SeedProto._compileNode = function (node, root) {
  562. var seed = this
  563. if (node.nodeType === 3) { // text node
  564. seed._compileTextNode(node)
  565. } else if (node.nodeType === 1) {
  566. var eachExp = node.getAttribute(eachAttr),
  567. ctrlExp = node.getAttribute(ctrlAttr),
  568. directive
  569. if (eachExp) { // each block
  570. directive = DirectiveParser.parse(eachAttr, eachExp)
  571. if (directive) {
  572. directive.el = node
  573. seed._bind(directive)
  574. }
  575. } else if (ctrlExp && !root) { // nested controllers
  576. new Seed(node, {
  577. child: true,
  578. parentSeed: seed
  579. })
  580. } else { // normal node
  581. // parse if has attributes
  582. if (node.attributes && node.attributes.length) {
  583. var attrs = slice.call(node.attributes),
  584. i = attrs.length, attr, j, valid, exps, exp
  585. while (i--) {
  586. attr = attrs[i]
  587. if (attr.name === ctrlAttr) continue
  588. valid = false
  589. exps = attr.value.split(',')
  590. j = exps.length
  591. while (j--) {
  592. exp = exps[j]
  593. directive = DirectiveParser.parse(attr.name, exp)
  594. if (directive) {
  595. valid = true
  596. directive.el = node
  597. seed._bind(directive)
  598. }
  599. }
  600. if (valid) node.removeAttribute(attr.name)
  601. }
  602. }
  603. // recursively compile childNodes
  604. if (node.childNodes.length) {
  605. slice.call(node.childNodes).forEach(seed._compileNode, seed)
  606. }
  607. }
  608. }
  609. }
  610. /*
  611. * Compile a text node
  612. */
  613. SeedProto._compileTextNode = function (node) {
  614. var tokens = TextParser.parse(node)
  615. if (!tokens) return
  616. var seed = this,
  617. dirname = config.prefix + '-text',
  618. el, token, directive
  619. for (var i = 0, l = tokens.length; i < l; i++) {
  620. token = tokens[i]
  621. el = document.createTextNode()
  622. if (token.key) {
  623. directive = DirectiveParser.parse(dirname, token.key)
  624. if (directive) {
  625. directive.el = el
  626. seed._bind(directive)
  627. }
  628. } else {
  629. el.nodeValue = token
  630. }
  631. node.parentNode.insertBefore(el, node)
  632. }
  633. node.parentNode.removeChild(node)
  634. }
  635. /*
  636. * Add a directive instance to the correct binding & scope
  637. */
  638. SeedProto._bind = function (directive) {
  639. var key = directive.key,
  640. seed = directive.seed = this
  641. // deal with each block
  642. if (this.each) {
  643. if (key.indexOf(this.eachPrefix) === 0) {
  644. key = directive.key = key.replace(this.eachPrefix, '')
  645. } else {
  646. seed = this.parentSeed
  647. }
  648. }
  649. // deal with nesting
  650. seed = traceOwnerSeed(directive, seed)
  651. var binding = seed._bindings[key] || seed._createBinding(key)
  652. binding.instances.push(directive)
  653. directive.binding = binding
  654. // invoke bind hook if exists
  655. if (directive.bind) {
  656. directive.bind(binding.value)
  657. }
  658. // set initial value
  659. directive.update(binding.value)
  660. if (binding.isComputed) {
  661. directive.refresh()
  662. }
  663. }
  664. /*
  665. * Create binding and attach getter/setter for a key to the scope object
  666. */
  667. SeedProto._createBinding = function (key) {
  668. config.log(' created binding: ' + key)
  669. var binding = new Binding(this, key)
  670. this._bindings[key] = binding
  671. if (binding.isComputed) this._computed.push(binding)
  672. return binding
  673. }
  674. /*
  675. * Process subscriptions for computed properties that has
  676. * dynamic context dependencies
  677. */
  678. SeedProto._bindContexts = function (bindings) {
  679. var i = bindings.length, j, binding, depKey, dep
  680. while (i--) {
  681. binding = bindings[i]
  682. j = binding.contextDeps.length
  683. while (j--) {
  684. depKey = binding.contextDeps[j]
  685. dep = this._bindings[depKey]
  686. dep.subs.push(binding)
  687. }
  688. }
  689. }
  690. /*
  691. * Call unbind() of all directive instances
  692. * to remove event listeners, destroy child seeds, etc.
  693. */
  694. SeedProto._unbind = function () {
  695. var i, ins
  696. for (var key in this._bindings) {
  697. ins = this._bindings[key].instances
  698. i = ins.length
  699. while (i--) {
  700. if (ins[i].unbind) ins[i].unbind()
  701. }
  702. }
  703. }
  704. /*
  705. * Unbind and remove element
  706. */
  707. SeedProto._destroy = function () {
  708. this._unbind()
  709. this.el.parentNode.removeChild(this.el)
  710. }
  711. // Helpers --------------------------------------------------------------------
  712. /*
  713. * determine which scope a key belongs to based on nesting symbols
  714. */
  715. function traceOwnerSeed (key, seed) {
  716. if (key.nesting) {
  717. var levels = key.nesting
  718. while (seed.parentSeed && levels--) {
  719. seed = seed.parentSeed
  720. }
  721. } else if (key.root) {
  722. while (seed.parentSeed) {
  723. seed = seed.parentSeed
  724. }
  725. }
  726. return seed
  727. }
  728. module.exports = Seed
  729. });
  730. require.register("seed/src/scope.js", function(exports, require, module){
  731. var utils = require('./utils')
  732. function Scope (seed, options) {
  733. this.$seed = seed
  734. this.$el = seed.el
  735. this.$index = options.index
  736. this.$parent = options.parentSeed && options.parentSeed.scope
  737. this.$watchers = {}
  738. }
  739. var ScopeProto = Scope.prototype
  740. /*
  741. * watch a key on the scope for changes
  742. * fire callback with new value
  743. */
  744. ScopeProto.$watch = function (key, callback) {
  745. var self = this
  746. // yield and wait for seed to finish compiling
  747. setTimeout(function () {
  748. var scope = self.$seed.scope,
  749. binding = self.$seed._bindings[key],
  750. i = binding.deps.length,
  751. watcher = self.$watchers[key] = {
  752. refresh: function () {
  753. callback(scope[key])
  754. },
  755. deps: binding.deps
  756. }
  757. while (i--) {
  758. binding.deps[i].subs.push(watcher)
  759. }
  760. }, 0)
  761. }
  762. /*
  763. * remove watcher
  764. */
  765. ScopeProto.$unwatch = function (key) {
  766. var self = this
  767. setTimeout(function () {
  768. var watcher = self.$watchers[key]
  769. if (!watcher) return
  770. var i = watcher.deps.length, subs
  771. while (i--) {
  772. subs = watcher.deps[i].subs
  773. subs.splice(subs.indexOf(watcher))
  774. }
  775. delete self.$watchers[key]
  776. }, 0)
  777. }
  778. /*
  779. * Dump a copy of current scope data, excluding seed-exposed properties.
  780. * @param key (optional): key for the value to dump
  781. */
  782. ScopeProto.$dump = function (key) {
  783. var bindings = this.$seed._bindings
  784. return utils.dumpValue(key ? bindings[key].value : this)
  785. }
  786. /*
  787. * stringify the result from $dump
  788. */
  789. ScopeProto.$serialize = function (key) {
  790. return JSON.stringify(this.$dump(key))
  791. }
  792. /*
  793. * unbind everything, remove everything
  794. */
  795. ScopeProto.$destroy = function () {
  796. this.$seed._destroy()
  797. }
  798. module.exports = Scope
  799. });
  800. require.register("seed/src/binding.js", function(exports, require, module){
  801. var utils = require('./utils'),
  802. observer = require('./deps-parser').observer,
  803. def = Object.defineProperty
  804. /*
  805. * Binding class.
  806. *
  807. * each property on the scope has one corresponding Binding object
  808. * which has multiple directive instances on the DOM
  809. * and multiple computed property dependents
  810. */
  811. function Binding (seed, key) {
  812. this.seed = seed
  813. this.scope = seed.scope
  814. this.key = key
  815. var path = key.split('.')
  816. this.inspect(utils.getNestedValue(seed.scope, path))
  817. this.def(seed.scope, path)
  818. this.instances = []
  819. this.subs = []
  820. this.deps = []
  821. }
  822. var BindingProto = Binding.prototype
  823. /*
  824. * Pre-process a passed in value based on its type
  825. */
  826. BindingProto.inspect = function (value) {
  827. var type = utils.typeOf(value),
  828. self = this
  829. // preprocess the value depending on its type
  830. if (type === 'Object') {
  831. if (value.get || value.set) { // computed property
  832. self.isComputed = true
  833. }
  834. } else if (type === 'Array') {
  835. utils.watchArray(value)
  836. value.on('mutate', function () {
  837. self.pub()
  838. })
  839. }
  840. self.value = value
  841. }
  842. /*
  843. * Define getter/setter for this binding on scope
  844. * recursive for nested objects
  845. */
  846. BindingProto.def = function (scope, path) {
  847. var self = this,
  848. key = path[0]
  849. if (path.length === 1) {
  850. // here we are! at the end of the path!
  851. // define the real value accessors.
  852. def(scope, key, {
  853. get: function () {
  854. if (observer.isObserving) {
  855. observer.emit('get', self)
  856. }
  857. return self.isComputed
  858. ? self.value.get({
  859. el: self.seed.el,
  860. scope: self.seed.scope
  861. })
  862. : self.value
  863. },
  864. set: function (value) {
  865. if (self.isComputed) {
  866. // computed properties cannot be redefined
  867. // no need to call binding.update() here,
  868. // as dependency extraction has taken care of that
  869. if (self.value.set) {
  870. self.value.set(value)
  871. }
  872. } else if (value !== self.value) {
  873. self.update(value)
  874. }
  875. }
  876. })
  877. } else {
  878. // we are not there yet!!!
  879. // create an intermediate subscope
  880. // which also has its own getter/setters
  881. var subScope = scope[key]
  882. if (!subScope) {
  883. subScope = {}
  884. def(scope, key, {
  885. get: function () {
  886. return subScope
  887. },
  888. set: function (value) {
  889. // when the subScope is given a new value,
  890. // copy everything over to trigger the setters
  891. for (var prop in value) {
  892. subScope[prop] = value[prop]
  893. }
  894. }
  895. })
  896. }
  897. // recurse
  898. this.def(subScope, path.slice(1))
  899. }
  900. }
  901. /*
  902. * Process the value, then trigger updates on all dependents
  903. */
  904. BindingProto.update = function (value) {
  905. this.inspect(value)
  906. var i = this.instances.length
  907. while (i--) {
  908. this.instances[i].update(value)
  909. }
  910. this.pub()
  911. }
  912. BindingProto.refresh = function () {
  913. var i = this.instances.length
  914. while (i--) {
  915. this.instances[i].refresh()
  916. }
  917. }
  918. /*
  919. * Notify computed properties that depend on this binding
  920. * to update themselves
  921. */
  922. BindingProto.pub = function () {
  923. var i = this.subs.length
  924. while (i--) {
  925. this.subs[i].refresh()
  926. }
  927. }
  928. module.exports = Binding
  929. });
  930. require.register("seed/src/directive-parser.js", function(exports, require, module){
  931. var config = require('./config'),
  932. directives = require('./directives'),
  933. filters = require('./filters')
  934. var KEY_RE = /^[^\|<]+/,
  935. ARG_RE = /([^:]+):(.+)$/,
  936. FILTERS_RE = /\|[^\|<]+/g,
  937. FILTER_TOKEN_RE = /[^\s']+|'[^']+'/g,
  938. INVERSE_RE = /^!/,
  939. NESTING_RE = /^\^+/,
  940. ONEWAY_RE = /-oneway$/
  941. /*
  942. * Directive class
  943. * represents a single directive instance in the DOM
  944. */
  945. function Directive (directiveName, expression, oneway) {
  946. var prop,
  947. definition = directives[directiveName]
  948. // mix in properties from the directive definition
  949. if (typeof definition === 'function') {
  950. this._update = definition
  951. } else {
  952. this._update = definition.update
  953. for (prop in definition) {
  954. if (prop !== 'update') {
  955. this[prop] = definition[prop]
  956. }
  957. }
  958. }
  959. this.oneway = !!oneway
  960. this.directiveName = directiveName
  961. this.expression = expression.trim()
  962. this.rawKey = expression.match(KEY_RE)[0].trim()
  963. this.parseKey(this.rawKey)
  964. var filterExps = expression.match(FILTERS_RE)
  965. this.filters = filterExps
  966. ? filterExps.map(parseFilter)
  967. : null
  968. }
  969. var DirProto = Directive.prototype
  970. /*
  971. * called when a new value is set
  972. * for computed properties, this will only be called once
  973. * during initialization.
  974. */
  975. DirProto.update = function (value) {
  976. if (value && (value === this.value)) return
  977. this.value = value
  978. this.apply(value)
  979. }
  980. /*
  981. * called when a dependency has changed
  982. * computed properties only
  983. */
  984. DirProto.refresh = function () {
  985. // pass element and scope info to the getter
  986. // enables powerful context-aware bindings
  987. var value = this.value.get({
  988. el: this.el,
  989. scope: this.seed.scope
  990. })
  991. if (value === this.computedValue) return
  992. this.computedValue = value
  993. this.apply(value)
  994. this.binding.pub()
  995. }
  996. /*
  997. * Actually invoking the _update from the directive's definition
  998. */
  999. DirProto.apply = function (value) {
  1000. if (this.inverse) value = !value
  1001. this._update(
  1002. this.filters
  1003. ? this.applyFilters(value)
  1004. : value
  1005. )
  1006. }
  1007. /*
  1008. * pipe the value through filters
  1009. */
  1010. DirProto.applyFilters = function (value) {
  1011. var filtered = value, filter
  1012. for (var i = 0, l = this.filters.length; i < l; i++) {
  1013. filter = this.filters[i]
  1014. if (!filter.apply) throw new Error('Unknown filter: ' + filter.name)
  1015. filtered = filter.apply(filtered, filter.args)
  1016. }
  1017. return filtered
  1018. }
  1019. /*
  1020. * parse a key, extract argument and nesting/root info
  1021. */
  1022. DirProto.parseKey = function (rawKey) {
  1023. var argMatch = rawKey.match(ARG_RE)
  1024. var key = argMatch
  1025. ? argMatch[2].trim()
  1026. : rawKey.trim()
  1027. this.arg = argMatch
  1028. ? argMatch[1].trim()
  1029. : null
  1030. this.inverse = INVERSE_RE.test(key)
  1031. if (this.inverse) {
  1032. key = key.slice(1)
  1033. }
  1034. var nesting = key.match(NESTING_RE)
  1035. this.nesting = nesting
  1036. ? nesting[0].length
  1037. : false
  1038. this.root = key.charAt(0) === '$'
  1039. if (this.nesting) {
  1040. key = key.replace(NESTING_RE, '')
  1041. } else if (this.root) {
  1042. key = key.slice(1)
  1043. }
  1044. this.key = key
  1045. }
  1046. /*
  1047. * parse a filter expression
  1048. */
  1049. function parseFilter (filter) {
  1050. var tokens = filter.slice(1)
  1051. .match(FILTER_TOKEN_RE)
  1052. .map(function (token) {
  1053. return token.replace(/'/g, '').trim()
  1054. })
  1055. return {
  1056. name : tokens[0],
  1057. apply : filters[tokens[0]],
  1058. args : tokens.length > 1
  1059. ? tokens.slice(1)
  1060. : null
  1061. }
  1062. }
  1063. module.exports = {
  1064. /*
  1065. * make sure the directive and expression is valid
  1066. * before we create an instance
  1067. */
  1068. parse: function (dirname, expression) {
  1069. var prefix = config.prefix
  1070. if (dirname.indexOf(prefix) === -1) return null
  1071. dirname = dirname.slice(prefix.length + 1)
  1072. var oneway = ONEWAY_RE.test(dirname)
  1073. if (oneway) {
  1074. dirname = dirname.slice(0, -7)
  1075. }
  1076. var dir = directives[dirname],
  1077. valid = KEY_RE.test(expression)
  1078. if (!dir) config.warn('unknown directive: ' + dirname)
  1079. if (!valid) config.warn('invalid directive expression: ' + expression)
  1080. return dir && valid
  1081. ? new Directive(dirname, expression, oneway)
  1082. : null
  1083. }
  1084. }
  1085. });
  1086. require.register("seed/src/text-parser.js", function(exports, require, module){
  1087. var config = require('./config'),
  1088. ESCAPE_RE = /[-.*+?^${}()|[\]\/\\]/g,
  1089. BINDING_RE
  1090. /*
  1091. * Escapes a string so that it can be used to construct RegExp
  1092. */
  1093. function escapeRegex (val) {
  1094. return val.replace(ESCAPE_RE, '\\$&')
  1095. }
  1096. module.exports = {
  1097. /*
  1098. * Parse a piece of text, return an array of tokens
  1099. */
  1100. parse: function (node) {
  1101. var text = node.nodeValue
  1102. if (!BINDING_RE.test(text)) return null
  1103. var m, i, tokens = []
  1104. do {
  1105. m = text.match(BINDING_RE)
  1106. if (!m) break
  1107. i = m.index
  1108. if (i > 0) tokens.push(text.slice(0, i))
  1109. tokens.push({ key: m[1] })
  1110. text = text.slice(i + m[0].length)
  1111. } while (true)
  1112. if (text.length) tokens.push(text)
  1113. return tokens
  1114. },
  1115. /*
  1116. * Build interpolate tag regex from config settings
  1117. */
  1118. buildRegex: function () {
  1119. var open = escapeRegex(config.interpolateTags.open),
  1120. close = escapeRegex(config.interpolateTags.close)
  1121. BINDING_RE = new RegExp(open + '(.+?)' + close)
  1122. }
  1123. }
  1124. });
  1125. require.register("seed/src/deps-parser.js", function(exports, require, module){
  1126. var Emitter = require('emitter'),
  1127. config = require('./config'),
  1128. observer = new Emitter()
  1129. var dummyEl = document.createElement('div'),
  1130. ARGS_RE = /^function\s*?\((.+?)\)/,
  1131. SCOPE_RE_STR = '\\.scope\\.[\\.A-Za-z0-9_][\\.A-Za-z0-9_$]*',
  1132. noop = function () {}
  1133. /*
  1134. * Auto-extract the dependencies of a computed property
  1135. * by recording the getters triggered when evaluating it.
  1136. *
  1137. * However, the first pass will contain duplicate dependencies
  1138. * for computed properties. It is therefore necessary to do a
  1139. * second pass in injectDeps()
  1140. */
  1141. function catchDeps (binding) {
  1142. observer.on('get', function (dep) {
  1143. binding.deps.push(dep)
  1144. })
  1145. parseContextDependency(binding)
  1146. binding.value.get({
  1147. scope: createDummyScope(binding),
  1148. el: dummyEl
  1149. })
  1150. observer.off('get')
  1151. }
  1152. /*
  1153. * The second pass of dependency extraction.
  1154. * Only include dependencies that don't have dependencies themselves.
  1155. */
  1156. function filterDeps (binding) {
  1157. var i = binding.deps.length, dep
  1158. config.log('\n─ ' + binding.key)
  1159. while (i--) {
  1160. dep = binding.deps[i]
  1161. if (!dep.deps.length) {
  1162. config.log(' └─' + dep.key)
  1163. dep.subs.push(binding)
  1164. } else {
  1165. binding.deps.splice(i, 1)
  1166. }
  1167. }
  1168. }
  1169. /*
  1170. * We need to invoke each binding's getter for dependency parsing,
  1171. * but we don't know what sub-scope properties the user might try
  1172. * to access in that getter. To avoid thowing an error or forcing
  1173. * the user to guard against an undefined argument, we staticly
  1174. * analyze the function to extract any possible nested properties
  1175. * the user expects the target scope to possess. They are all assigned
  1176. * a noop function so they can be invoked with no real harm.
  1177. */
  1178. function createDummyScope (binding) {
  1179. var scope = {},
  1180. deps = binding.contextDeps
  1181. if (!deps) return scope
  1182. var i = binding.contextDeps.length,
  1183. j, level, key, path
  1184. while (i--) {
  1185. level = scope
  1186. path = deps[i].split('.')
  1187. j = 0
  1188. while (j < path.length) {
  1189. key = path[j]
  1190. if (!level[key]) level[key] = noop
  1191. level = level[key]
  1192. j++
  1193. }
  1194. }
  1195. return scope
  1196. }
  1197. /*
  1198. * Extract context dependency paths
  1199. */
  1200. function parseContextDependency (binding) {
  1201. var fn = binding.value.get,
  1202. str = fn.toString(),
  1203. args = str.match(ARGS_RE)
  1204. if (!args) return null
  1205. var argRE = new RegExp(args[1] + SCOPE_RE_STR, 'g'),
  1206. matches = str.match(argRE),
  1207. base = args[1].length + 7
  1208. if (!matches) return null
  1209. var i = matches.length,
  1210. deps = [], dep
  1211. while (i--) {
  1212. dep = matches[i].slice(base)
  1213. if (deps.indexOf(dep) === -1) {
  1214. deps.push(dep)
  1215. }
  1216. }
  1217. binding.contextDeps = deps
  1218. binding.seed._contextBindings.push(binding)
  1219. }
  1220. module.exports = {
  1221. /*
  1222. * the observer that catches events triggered by getters
  1223. */
  1224. observer: observer,
  1225. /*
  1226. * parse a list of computed property bindings
  1227. */
  1228. parse: function (bindings) {
  1229. config.log('\nparsing dependencies...')
  1230. observer.isObserving = true
  1231. bindings.forEach(catchDeps)
  1232. bindings.forEach(filterDeps)
  1233. observer.isObserving = false
  1234. config.log('\ndone.')
  1235. }
  1236. }
  1237. });
  1238. require.register("seed/src/filters.js", function(exports, require, module){
  1239. var keyCodes = {
  1240. enter : 13,
  1241. tab : 9,
  1242. 'delete' : 46,
  1243. up : 38,
  1244. left : 37,
  1245. right : 39,
  1246. down : 40,
  1247. esc : 27
  1248. }
  1249. module.exports = {
  1250. trim: function (value) {
  1251. return value ? value.toString().trim() : ''
  1252. },
  1253. capitalize: function (value) {
  1254. if (!value) return ''
  1255. value = value.toString()
  1256. return value.charAt(0).toUpperCase() + value.slice(1)
  1257. },
  1258. uppercase: function (value) {
  1259. return value ? value.toString().toUpperCase() : ''
  1260. },
  1261. lowercase: function (value) {
  1262. return value ? value.toString().toLowerCase() : ''
  1263. },
  1264. currency: function (value, args) {
  1265. if (!value) return ''
  1266. var sign = (args && args[0]) || '$',
  1267. i = value % 3,
  1268. f = '.' + value.toFixed(2).slice(-2),
  1269. s = Math.floor(value).toString()
  1270. return sign + s.slice(0, i) + s.slice(i).replace(/(\d{3})(?=\d)/g, '$1,') + f
  1271. },
  1272. key: function (handler, args) {
  1273. if (!handler) return
  1274. var code = keyCodes[args[0]]
  1275. if (!code) {
  1276. code = parseInt(args[0], 10)
  1277. }
  1278. return function (e) {
  1279. if (e.keyCode === code) {
  1280. handler.call(this, e)
  1281. }
  1282. }
  1283. }
  1284. }
  1285. });
  1286. require.register("seed/src/directives/index.js", function(exports, require, module){
  1287. module.exports = {
  1288. on : require('./on'),
  1289. each : require('./each'),
  1290. attr: function (value) {
  1291. this.el.setAttribute(this.arg, value)
  1292. },
  1293. text: function (value) {
  1294. this.el.textContent =
  1295. (typeof value === 'string' || typeof value === 'number')
  1296. ? value : ''
  1297. },
  1298. html: function (value) {
  1299. this.el.innerHTML =
  1300. (typeof value === 'string' || typeof value === 'number')
  1301. ? value : ''
  1302. },
  1303. show: function (value) {
  1304. this.el.style.display = value ? '' : 'none'
  1305. },
  1306. visible: function (value) {
  1307. this.el.style.visibility = value ? '' : 'hidden'
  1308. },
  1309. focus: function (value) {
  1310. var el = this.el
  1311. setTimeout(function () {
  1312. el[value ? 'focus' : 'blur']()
  1313. }, 0)
  1314. },
  1315. class: function (value) {
  1316. if (this.arg) {
  1317. this.el.classList[value ? 'add' : 'remove'](this.arg)
  1318. } else {
  1319. if (this.lastVal) {
  1320. this.el.classList.remove(this.lastVal)
  1321. }
  1322. this.el.classList.add(value)
  1323. this.lastVal = value
  1324. }
  1325. },
  1326. value: {
  1327. bind: function () {
  1328. if (this.oneway) return
  1329. var el = this.el, self = this
  1330. this.change = function () {
  1331. self.seed.scope[self.key] = el.value
  1332. }
  1333. el.addEventListener('change', this.change)
  1334. },
  1335. update: function (value) {
  1336. this.el.value = value ? value : ''
  1337. },
  1338. unbind: function () {
  1339. if (this.oneway) return
  1340. this.el.removeEventListener('change', this.change)
  1341. }
  1342. },
  1343. checked: {
  1344. bind: function () {
  1345. if (this.oneway) return
  1346. var el = this.el, self = this
  1347. this.change = function () {
  1348. self.seed.scope[self.key] = el.checked
  1349. }
  1350. el.addEventListener('change', this.change)
  1351. },
  1352. update: function (value) {
  1353. this.el.checked = !!value
  1354. },
  1355. unbind: function () {
  1356. if (this.oneway) return
  1357. this.el.removeEventListener('change', this.change)
  1358. }
  1359. },
  1360. 'if': {
  1361. bind: function () {
  1362. this.parent = this.el.parentNode
  1363. this.ref = document.createComment('sd-if-' + this.key)
  1364. var next = this.el.nextSibling
  1365. if (next) {
  1366. this.parent.insertBefore(this.ref, next)
  1367. } else {
  1368. this.parent.appendChild(this.ref)
  1369. }
  1370. },
  1371. update: function (value) {
  1372. if (!value) {
  1373. if (this.el.parentNode) {
  1374. this.parent.removeChild(this.el)
  1375. }
  1376. } else {
  1377. if (!this.el.parentNode) {
  1378. this.parent.insertBefore(this.el, this.ref)
  1379. }
  1380. }
  1381. }
  1382. },
  1383. style: {
  1384. bind: function () {
  1385. this.arg = convertCSSProperty(this.arg)
  1386. },
  1387. update: function (value) {
  1388. this.el.style[this.arg] = value
  1389. }
  1390. }
  1391. }
  1392. /*
  1393. * convert hyphen style CSS property to Camel style
  1394. */
  1395. var CONVERT_RE = /-(.)/g
  1396. function convertCSSProperty (prop) {
  1397. if (prop.charAt(0) === '-') prop = prop.slice(1)
  1398. return prop.replace(CONVERT_RE, function (m, char) {
  1399. return char.toUpperCase()
  1400. })
  1401. }
  1402. });
  1403. require.register("seed/src/directives/each.js", function(exports, require, module){
  1404. var config = require('../config')
  1405. /*
  1406. * Mathods that perform precise DOM manipulation
  1407. * based on mutator method triggered
  1408. */
  1409. var mutationHandlers = {
  1410. push: function (m) {
  1411. var i, l = m.args.length,
  1412. baseIndex = this.collection.length - l
  1413. for (i = 0; i < l; i++) {
  1414. this.buildItem(this.ref, m.args[i], baseIndex + i)
  1415. }
  1416. },
  1417. pop: function (m) {
  1418. m.result.$destroy()
  1419. },
  1420. unshift: function (m) {
  1421. var i, l = m.args.length, ref
  1422. for (i = 0; i < l; i++) {
  1423. ref = this.collection.length > l
  1424. ? this.collection[l].$el
  1425. : this.ref
  1426. this.buildItem(ref, m.args[i], i)
  1427. }
  1428. this.updateIndexes()
  1429. },
  1430. shift: function (m) {
  1431. m.result.$destroy()
  1432. this.updateIndexes()
  1433. },
  1434. splice: function (m) {
  1435. var i, pos, ref,
  1436. l = m.args.length,
  1437. k = m.result.length,
  1438. index = m.args[0],
  1439. removed = m.args[1],
  1440. added = l - 2
  1441. for (i = 0; i < k; i++) {
  1442. m.result[i].$destroy()
  1443. }
  1444. if (added > 0) {
  1445. for (i = 2; i < l; i++) {
  1446. pos = index - removed + added + 1
  1447. ref = this.collection[pos]
  1448. ? this.collection[pos].$el
  1449. : this.ref
  1450. this.buildItem(ref, m.args[i], index + i)
  1451. }
  1452. }
  1453. if (removed !== added) {
  1454. this.updateIndexes()
  1455. }
  1456. },
  1457. sort: function () {
  1458. var i, l = this.collection.length, scope
  1459. for (i = 0; i < l; i++) {
  1460. scope = this.collection[i]
  1461. scope.$index = i
  1462. this.container.insertBefore(scope.$el, this.ref)
  1463. }
  1464. }
  1465. }
  1466. mutationHandlers.reverse = mutationHandlers.sort
  1467. module.exports = {
  1468. bind: function () {
  1469. this.el.removeAttribute(config.prefix + '-each')
  1470. var ctn = this.container = this.el.parentNode
  1471. // create a comment node as a reference node for DOM insertions
  1472. this.ref = document.createComment('sd-each-' + this.arg)
  1473. ctn.insertBefore(this.ref, this.el)
  1474. ctn.removeChild(this.el)
  1475. },
  1476. update: function (collection) {
  1477. this.unbind(true)
  1478. if (!Array.isArray(collection)) return
  1479. this.collection = collection
  1480. // attach an object to container to hold handlers
  1481. this.container.sd_dHandlers = {}
  1482. // listen for collection mutation events
  1483. // the collection has been augmented during Binding.set()
  1484. var self = this
  1485. collection.on('mutate', function (mutation) {
  1486. mutationHandlers[mutation.method].call(self, mutation)
  1487. })
  1488. // create child-seeds and append to DOM
  1489. for (var i = 0, l = collection.length; i < l; i++) {
  1490. this.buildItem(this.ref, collection[i], i)
  1491. }
  1492. },
  1493. buildItem: function (ref, data, index) {
  1494. var node = this.el.cloneNode(true)
  1495. this.container.insertBefore(node, ref)
  1496. var Seed = require('../seed'),
  1497. spore = new Seed(node, {
  1498. each: true,
  1499. eachPrefix: this.arg + '.',
  1500. parentSeed: this.seed,
  1501. index: index,
  1502. data: data,
  1503. delegator: this.container
  1504. })
  1505. this.collection[index] = spore.scope
  1506. },
  1507. updateIndexes: function () {
  1508. var i = this.collection.length
  1509. while (i--) {
  1510. this.collection[i].$index = i
  1511. }
  1512. },
  1513. unbind: function (reset) {
  1514. if (this.collection && this.collection.length) {
  1515. var i = this.collection.length,
  1516. fn = reset ? '_destroy' : '_unbind'
  1517. while (i--) {
  1518. this.collection[i].$seed[fn]()
  1519. }
  1520. this.collection = null
  1521. }
  1522. var ctn = this.container,
  1523. handlers = ctn.sd_dHandlers
  1524. for (var key in handlers) {
  1525. ctn.removeEventListener(handlers[key].event, handlers[key])
  1526. }
  1527. delete ctn.sd_dHandlers
  1528. }
  1529. }
  1530. });
  1531. require.register("seed/src/directives/on.js", function(exports, require, module){
  1532. function delegateCheck (current, top, identifier) {
  1533. if (current[identifier]) {
  1534. return current
  1535. } else if (current === top) {
  1536. return false
  1537. } else {
  1538. return delegateCheck(current.parentNode, top, identifier)
  1539. }
  1540. }
  1541. module.exports = {
  1542. expectFunction : true,
  1543. bind: function () {
  1544. if (this.seed.each) {
  1545. // attach an identifier to the el
  1546. // so it can be matched during event delegation
  1547. this.el[this.expression] = true
  1548. // attach the owner scope of this directive
  1549. this.el.sd_scope = this.seed.scope
  1550. }
  1551. },
  1552. update: function (handler) {
  1553. this.unbind()
  1554. if (!handler) return
  1555. var seed = this.seed,
  1556. event = this.arg
  1557. if (seed.each && event !== 'blur' && event !== 'blur') {
  1558. // for each blocks, delegate for better performance
  1559. // focus and blur events dont bubble so exclude them
  1560. var delegator = seed.delegator,
  1561. identifier = this.expression,
  1562. dHandler = delegator.sd_dHandlers[identifier]
  1563. if (dHandler) return
  1564. // the following only gets run once for the entire each block
  1565. dHandler = delegator.sd_dHandlers[identifier] = function (e) {
  1566. var target = delegateCheck(e.target, delegator, identifier)
  1567. if (target) {
  1568. e.el = target
  1569. e.scope = target.sd_scope
  1570. handler.call(seed.scope, e)
  1571. }
  1572. }
  1573. dHandler.event = event
  1574. delegator.addEventListener(event, dHandler)
  1575. } else {
  1576. // a normal, single element handler
  1577. this.handler = function (e) {
  1578. e.el = e.currentTarget
  1579. e.scope = seed.scope
  1580. handler.call(seed.scope, e)
  1581. }
  1582. this.el.addEventListener(event, this.handler)
  1583. }
  1584. },
  1585. unbind: function () {
  1586. this.el.removeEventListener(this.arg, this.handler)
  1587. }
  1588. }
  1589. });
  1590. require.alias("component-emitter/index.js", "seed/deps/emitter/index.js");
  1591. require.alias("component-emitter/index.js", "emitter/index.js");
  1592. require.alias("component-indexof/index.js", "component-emitter/deps/indexof/index.js");
  1593. require.alias("seed/src/main.js", "seed/index.js");
  1594. window.Seed = window.Seed || require('seed')
  1595. Seed.version = '0.1.4'
  1596. })();