seed.js 46 KB

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