| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701 |
- ;(function (undefined) {
- /**
- * Require the given path.
- *
- * @param {String} path
- * @return {Object} exports
- * @api public
- */
- function require(path, parent, orig) {
- var resolved = require.resolve(path);
- // lookup failed
- if (null == resolved) {
- orig = orig || path;
- parent = parent || 'root';
- var err = new Error('Failed to require "' + orig + '" from "' + parent + '"');
- err.path = orig;
- err.parent = parent;
- err.require = true;
- throw err;
- }
- var module = require.modules[resolved];
- // perform real require()
- // by invoking the module's
- // registered function
- if (!module.exports) {
- module.exports = {};
- module.client = module.component = true;
- module.call(this, module.exports, require.relative(resolved), module);
- }
- return module.exports;
- }
- /**
- * Registered modules.
- */
- require.modules = {};
- /**
- * Registered aliases.
- */
- require.aliases = {};
- /**
- * Resolve `path`.
- *
- * Lookup:
- *
- * - PATH/index.js
- * - PATH.js
- * - PATH
- *
- * @param {String} path
- * @return {String} path or null
- * @api private
- */
- require.resolve = function(path) {
- if (path.charAt(0) === '/') path = path.slice(1);
- var paths = [
- path,
- path + '.js',
- path + '.json',
- path + '/index.js',
- path + '/index.json'
- ];
- for (var i = 0; i < paths.length; i++) {
- var path = paths[i];
- if (require.modules.hasOwnProperty(path)) return path;
- if (require.aliases.hasOwnProperty(path)) return require.aliases[path];
- }
- };
- /**
- * Normalize `path` relative to the current path.
- *
- * @param {String} curr
- * @param {String} path
- * @return {String}
- * @api private
- */
- require.normalize = function(curr, path) {
- var segs = [];
- if ('.' != path.charAt(0)) return path;
- curr = curr.split('/');
- path = path.split('/');
- for (var i = 0; i < path.length; ++i) {
- if ('..' == path[i]) {
- curr.pop();
- } else if ('.' != path[i] && '' != path[i]) {
- segs.push(path[i]);
- }
- }
- return curr.concat(segs).join('/');
- };
- /**
- * Register module at `path` with callback `definition`.
- *
- * @param {String} path
- * @param {Function} definition
- * @api private
- */
- require.register = function(path, definition) {
- require.modules[path] = definition;
- };
- /**
- * Alias a module definition.
- *
- * @param {String} from
- * @param {String} to
- * @api private
- */
- require.alias = function(from, to) {
- if (!require.modules.hasOwnProperty(from)) {
- throw new Error('Failed to alias "' + from + '", it does not exist');
- }
- require.aliases[to] = from;
- };
- /**
- * Return a require function relative to the `parent` path.
- *
- * @param {String} parent
- * @return {Function}
- * @api private
- */
- require.relative = function(parent) {
- var p = require.normalize(parent, '..');
- /**
- * lastIndexOf helper.
- */
- function lastIndexOf(arr, obj) {
- var i = arr.length;
- while (i--) {
- if (arr[i] === obj) return i;
- }
- return -1;
- }
- /**
- * The relative require() itself.
- */
- function localRequire(path) {
- var resolved = localRequire.resolve(path);
- return require(resolved, parent, path);
- }
- /**
- * Resolve relative to the parent.
- */
- localRequire.resolve = function(path) {
- var c = path.charAt(0);
- if ('/' == c) return path.slice(1);
- if ('.' == c) return require.normalize(p, path);
- // resolve deps by returning
- // the dep in the nearest "deps"
- // directory
- var segs = parent.split('/');
- var i = lastIndexOf(segs, 'deps') + 1;
- if (!i) i = 0;
- path = segs.slice(0, i + 1).join('/') + '/deps/' + path;
- return path;
- };
- /**
- * Check if module is defined at `path`.
- */
- localRequire.exists = function(path) {
- return require.modules.hasOwnProperty(localRequire.resolve(path));
- };
- return localRequire;
- };
- require.register("component-indexof/index.js", function(exports, require, module){
- module.exports = function(arr, obj){
- if (arr.indexOf) return arr.indexOf(obj);
- for (var i = 0; i < arr.length; ++i) {
- if (arr[i] === obj) return i;
- }
- return -1;
- };
- });
- require.register("component-emitter/index.js", function(exports, require, module){
- /**
- * Module dependencies.
- */
- var index = require('indexof');
- /**
- * Expose `Emitter`.
- */
- module.exports = Emitter;
- /**
- * Initialize a new `Emitter`.
- *
- * @api public
- */
- function Emitter(obj) {
- if (obj) return mixin(obj);
- };
- /**
- * Mixin the emitter properties.
- *
- * @param {Object} obj
- * @return {Object}
- * @api private
- */
- function mixin(obj) {
- for (var key in Emitter.prototype) {
- obj[key] = Emitter.prototype[key];
- }
- return obj;
- }
- /**
- * Listen on the given `event` with `fn`.
- *
- * @param {String} event
- * @param {Function} fn
- * @return {Emitter}
- * @api public
- */
- Emitter.prototype.on = function(event, fn){
- this._callbacks = this._callbacks || {};
- (this._callbacks[event] = this._callbacks[event] || [])
- .push(fn);
- return this;
- };
- /**
- * Adds an `event` listener that will be invoked a single
- * time then automatically removed.
- *
- * @param {String} event
- * @param {Function} fn
- * @return {Emitter}
- * @api public
- */
- Emitter.prototype.once = function(event, fn){
- var self = this;
- this._callbacks = this._callbacks || {};
- function on() {
- self.off(event, on);
- fn.apply(this, arguments);
- }
- fn._off = on;
- this.on(event, on);
- return this;
- };
- /**
- * Remove the given callback for `event` or all
- * registered callbacks.
- *
- * @param {String} event
- * @param {Function} fn
- * @return {Emitter}
- * @api public
- */
- Emitter.prototype.off =
- Emitter.prototype.removeListener =
- Emitter.prototype.removeAllListeners = function(event, fn){
- this._callbacks = this._callbacks || {};
- // all
- if (0 == arguments.length) {
- this._callbacks = {};
- return this;
- }
- // specific event
- var callbacks = this._callbacks[event];
- if (!callbacks) return this;
- // remove all handlers
- if (1 == arguments.length) {
- delete this._callbacks[event];
- return this;
- }
- // remove specific handler
- var i = index(callbacks, fn._off || fn);
- if (~i) callbacks.splice(i, 1);
- return this;
- };
- /**
- * Emit `event` with the given args.
- *
- * @param {String} event
- * @param {Mixed} ...
- * @return {Emitter}
- */
- Emitter.prototype.emit = function(event){
- this._callbacks = this._callbacks || {};
- var args = [].slice.call(arguments, 1)
- , callbacks = this._callbacks[event];
- if (callbacks) {
- callbacks = callbacks.slice(0);
- for (var i = 0, len = callbacks.length; i < len; ++i) {
- callbacks[i].apply(this, args);
- }
- }
- return this;
- };
- /**
- * Return array of callbacks for `event`.
- *
- * @param {String} event
- * @return {Array}
- * @api public
- */
- Emitter.prototype.listeners = function(event){
- this._callbacks = this._callbacks || {};
- return this._callbacks[event] || [];
- };
- /**
- * Check if this emitter has `event` handlers.
- *
- * @param {String} event
- * @return {Boolean}
- * @api public
- */
- Emitter.prototype.hasListeners = function(event){
- return !! this.listeners(event).length;
- };
- });
- require.register("seed/src/main.js", function(exports, require, module){
- var config = require('./config'),
- Seed = require('./seed'),
- directives = require('./directives'),
- filters = require('./filters'),
- textParser = require('./text-parser')
- var controllers = config.controllers,
- datum = config.datum,
- api = {},
- reserved = ['datum', 'controllers'],
- booted = false
- /*
- * Store a piece of plain data in config.datum
- * so it can be consumed by sd-data
- */
- api.data = function (id, data) {
- if (!data) return datum[id]
- datum[id] = data
- }
- /*
- * Store a controller function in config.controllers
- * so it can be consumed by sd-controller
- */
- api.controller = function (id, extensions) {
- if (!extensions) return controllers[id]
- controllers[id] = extensions
- }
- /*
- * Allows user to create a custom directive
- */
- api.directive = function (name, fn) {
- if (!fn) return directives[name]
- directives[name] = fn
- }
- /*
- * Allows user to create a custom filter
- */
- api.filter = function (name, fn) {
- if (!fn) return filters[name]
- filters[name] = fn
- }
- /*
- * Bootstrap the whole thing
- * by creating a Seed instance for top level nodes
- * that has either sd-controller or sd-data
- */
- api.bootstrap = function (opts) {
- if (booted) return
- if (opts) {
- for (var key in opts) {
- if (reserved.indexOf(key) === -1) {
- config[key] = opts[key]
- }
- }
- }
- textParser.buildRegex()
- var el,
- ctrlSlt = '[' + config.prefix + '-controller]',
- dataSlt = '[' + config.prefix + '-data]',
- seeds = []
- /* jshint boss: true */
- while (el = document.querySelector(ctrlSlt) || document.querySelector(dataSlt)) {
- seeds.push((new Seed(el)).scope)
- }
- booted = true
- return seeds.length > 1 ? seeds : seeds[0]
- }
- module.exports = api
- });
- require.register("seed/src/config.js", function(exports, require, module){
- module.exports = {
- prefix : 'sd',
- debug : false,
- datum : {},
- controllers : {},
- interpolateTags : {
- open : '{{',
- close : '}}'
- }
- }
- });
- require.register("seed/src/utils.js", function(exports, require, module){
- var Emitter = require('emitter'),
- toString = Object.prototype.toString,
- aproto = Array.prototype,
- arrayMutators = ['push','pop','shift','unshift','splice','sort','reverse']
- var arrayAugmentations = {
- remove: function (index) {
- if (typeof index !== 'number') index = index.$index
- this.splice(index, 1)
- },
- replace: function (index, data) {
- if (typeof index !== 'number') index = index.$index
- this.splice(index, 1, data)
- }
- }
- /*
- * get accurate type of an object
- */
- function typeOf (obj) {
- return toString.call(obj).slice(8, -1)
- }
- /*
- * Recursively dump stuff...
- */
- function dumpValue (val) {
- var type = typeOf(val)
- if (type === 'Array') {
- return val.map(dumpValue)
- } else if (type === 'Object') {
- if (val.get) { // computed property
- return val.get()
- } else { // object / child scope
- var ret = {}
- for (var key in val) {
- if (val.hasOwnProperty(key) &&
- typeof val[key] !== 'function' &&
- key.charAt(0) !== '$')
- {
- ret[key] = dumpValue(val[key])
- }
- }
- return ret
- }
- } else if (type !== 'Function') {
- return val
- }
- }
- module.exports = {
- typeOf: typeOf,
- dumpValue: dumpValue,
- /*
- * Get a value from an object based on a path array
- */
- getNestedValue: function (obj, path) {
- if (path.length === 1) return obj[path[0]]
- var i = 0
- /* jshint boss: true */
- while (obj[path[i]]) {
- obj = obj[path[i]]
- i++
- }
- return i === path.length ? obj : undefined
- },
- /*
- * augment an Array so that it emit events when mutated
- */
- watchArray: function (collection) {
- Emitter(collection)
- arrayMutators.forEach(function (method) {
- collection[method] = function () {
- var result = aproto[method].apply(this, arguments)
- collection.emit('mutate', {
- method: method,
- args: aproto.slice.call(arguments),
- result: result
- })
- }
- })
- for (var method in arrayAugmentations) {
- collection[method] = arrayAugmentations[method]
- }
- }
- }
- });
- require.register("seed/src/seed.js", function(exports, require, module){
- var config = require('./config'),
- Scope = require('./scope'),
- Binding = require('./binding'),
- DirectiveParser = require('./directive-parser'),
- TextParser = require('./text-parser'),
- depsParser = require('./deps-parser')
- var slice = Array.prototype.slice,
- ctrlAttr = config.prefix + '-controller',
- eachAttr = config.prefix + '-each'
- /*
- * The main ViewModel class
- * scans a node and parse it to populate data bindings
- */
- function Seed (el, options) {
- if (typeof el === 'string') {
- el = document.querySelector(el)
- }
- this.el = el
- el.seed = this
- this._bindings = {}
- this._computed = []
- // copy options
- options = options || {}
- for (var op in options) {
- this[op] = options[op]
- }
- // check if there's passed in data
- var dataAttr = config.prefix + '-data',
- dataId = el.getAttribute(dataAttr),
- data = (options && options.data) || config.datum[dataId]
- if (config.debug && dataId && !data) {
- console.warn('data "' + dataId + '" is not defined.')
- }
- data = data || {}
- el.removeAttribute(dataAttr)
- // if the passed in data is the scope of a Seed instance,
- // make a copy from it
- if (data.$seed instanceof Seed) {
- data = data.$dump()
- }
- // initialize the scope object
- var scope = this.scope = new Scope(this, options)
- // copy data
- for (var key in data) {
- scope[key] = data[key]
- }
- // if has controller function, apply it so we have all the user definitions
- var ctrlID = el.getAttribute(ctrlAttr)
- if (ctrlID) {
- el.removeAttribute(ctrlAttr)
- var factory = config.controllers[ctrlID]
- if (factory) {
- factory(this.scope)
- } else if (config.debug) {
- console.warn('controller "' + ctrlID + '" is not defined.')
- }
- }
- // now parse the DOM
- this._compileNode(el, true)
- // extract dependencies for computed properties
- depsParser.parse(this._computed)
- delete this._computed
- }
- // for better compression
- var SeedProto = Seed.prototype
- /*
- * Compile a DOM node (recursive)
- */
- SeedProto._compileNode = function (node, root) {
- var seed = this
- if (node.nodeType === 3) { // text node
- seed._compileTextNode(node)
- } else if (node.nodeType === 1) {
- var eachExp = node.getAttribute(eachAttr),
- ctrlExp = node.getAttribute(ctrlAttr)
- if (eachExp) { // each block
- var directive = DirectiveParser.parse(eachAttr, eachExp)
- if (directive) {
- directive.el = node
- seed._bind(directive)
- }
- } else if (ctrlExp && !root) { // nested controllers
- new Seed(node, {
- child: true,
- parentSeed: seed
- })
- } else { // normal node
- // parse if has attributes
- if (node.attributes && node.attributes.length) {
- // forEach vs for loop perf comparison: http://jsperf.com/for-vs-foreach-case
- // takeaway: not worth it to wrtie manual loops.
- slice.call(node.attributes).forEach(function (attr) {
- if (attr.name === ctrlAttr) return
- var valid = false
- attr.value.split(',').forEach(function (exp) {
- var directive = DirectiveParser.parse(attr.name, exp)
- if (directive) {
- valid = true
- directive.el = node
- seed._bind(directive)
- }
- })
- if (valid) node.removeAttribute(attr.name)
- })
- }
- // recursively compile childNodes
- if (node.childNodes.length) {
- slice.call(node.childNodes).forEach(seed._compileNode, seed)
- }
- }
- }
- }
- /*
- * Compile a text node
- */
- SeedProto._compileTextNode = function (node) {
- var tokens = TextParser.parse(node)
- if (!tokens) return
- var seed = this,
- dirname = config.prefix + '-text',
- el, token, directive
- for (var i = 0, l = tokens.length; i < l; i++) {
- token = tokens[i]
- el = document.createTextNode()
- if (token.key) {
- directive = DirectiveParser.parse(dirname, token.key)
- if (directive) {
- directive.el = el
- seed._bind(directive)
- }
- } else {
- el.nodeValue = token
- }
- node.parentNode.insertBefore(el, node)
- }
- node.parentNode.removeChild(node)
- }
- /*
- * Add a directive instance to the correct binding & scope
- */
- SeedProto._bind = function (directive) {
- var key = directive.key,
- seed = directive.seed = this
- // deal with each block
- if (this.each) {
- if (key.indexOf(this.eachPrefix) === 0) {
- key = directive.key = key.replace(this.eachPrefix, '')
- } else {
- seed = this.parentSeed
- }
- }
- // deal with nesting
- seed = traceOwnerSeed(directive, seed)
- var binding = seed._bindings[key] || seed._createBinding(key)
- // add directive to this binding
- binding.instances.push(directive)
- directive.binding = binding
- // invoke bind hook if exists
- if (directive.bind) {
- directive.bind(binding.value)
- }
- // set initial value
- directive.update(binding.value)
- if (binding.isComputed) {
- directive.refresh()
- }
- }
- /*
- * Create binding and attach getter/setter for a key to the scope object
- */
- SeedProto._createBinding = function (key) {
- var binding = new Binding(this, key)
- this._bindings[key] = binding
- if (binding.isComputed) this._computed.push(binding)
- return binding
- }
- /*
- * Call unbind() of all directive instances
- * to remove event listeners, destroy child seeds, etc.
- */
- SeedProto._unbind = function () {
- var i, ins
- for (var key in this._bindings) {
- ins = this._bindings[key].instances
- i = ins.length
- while (i--) {
- if (ins[i].unbind) ins[i].unbind()
- }
- }
- }
- /*
- * Unbind and remove element
- */
- SeedProto._destroy = function () {
- this._unbind()
- this.el.parentNode.removeChild(this.el)
- }
- // Helpers --------------------------------------------------------------------
- /*
- * determine which scope a key belongs to based on nesting symbols
- */
- function traceOwnerSeed (key, seed) {
- if (key.nesting) {
- var levels = key.nesting
- while (seed.parentSeed && levels--) {
- seed = seed.parentSeed
- }
- } else if (key.root) {
- while (seed.parentSeed) {
- seed = seed.parentSeed
- }
- }
- return seed
- }
- module.exports = Seed
- });
- require.register("seed/src/scope.js", function(exports, require, module){
- var utils = require('./utils')
- function Scope (seed, options) {
- this.$seed = seed
- this.$el = seed.el
- this.$index = options.index
- this.$parent = options.parentSeed && options.parentSeed.scope
- this.$watchers = {}
- }
- var ScopeProto = Scope.prototype
- /*
- * watch a key on the scope for changes
- * fire callback with new value
- */
- ScopeProto.$watch = function (key, callback) {
- var self = this
- // yield and wait for seed to finish compiling
- setTimeout(function () {
- var scope = self.$seed.scope,
- binding = self.$seed._bindings[key],
- watcher = self.$watchers[key] = {
- refresh: function () {
- callback(scope[key])
- },
- deps: binding.deps
- }
- binding.deps.forEach(function (dep) {
- dep.subs.push(watcher)
- })
- }, 0)
- }
- /*
- * remove watcher
- */
- ScopeProto.$unwatch = function (key) {
- var self = this
- setTimeout(function () {
- var watcher = self.$watchers[key]
- if (!watcher) return
- watcher.deps.forEach(function (dep) {
- dep.subs.splice(dep.subs.indexOf(watcher))
- })
- delete self.$watchers[key]
- }, 0)
- }
- /*
- * Dump a copy of current scope data, excluding seed-exposed properties.
- * @param key (optional): key for the value to dump
- */
- ScopeProto.$dump = function (key) {
- var bindings = this.$seed._bindings
- return utils.dumpValue(key ? bindings[key].value : this)
- }
- /*
- * stringify the result from $dump
- */
- ScopeProto.$serialize = function (key) {
- return JSON.stringify(this.$dump(key))
- }
- /*
- * unbind everything, remove everything
- */
- ScopeProto.$destroy = function () {
- this.$seed._destroy()
- }
- module.exports = Scope
- });
- require.register("seed/src/binding.js", function(exports, require, module){
- var utils = require('./utils'),
- observer = require('./deps-parser').observer,
- def = Object.defineProperty
- /*
- * Binding class.
- *
- * each property on the scope has one corresponding Binding object
- * which has multiple directive instances on the DOM
- * and multiple computed property dependents
- */
- function Binding (seed, key) {
- this.seed = seed
- this.key = key
- var path = key.split('.')
- this.inspect(utils.getNestedValue(seed.scope, path))
- this.def(seed.scope, path)
- this.instances = []
- this.subs = []
- this.deps = []
- }
- var BindingProto = Binding.prototype
- /*
- * Pre-process a passed in value based on its type
- */
- BindingProto.inspect = function (value) {
- var type = utils.typeOf(value),
- self = this
- // preprocess the value depending on its type
- if (type === 'Object') {
- if (value.get || value.set) { // computed property
- self.isComputed = true
- }
- } else if (type === 'Array') {
- utils.watchArray(value)
- value.on('mutate', function () {
- self.pub()
- })
- }
- self.value = value
- }
- /*
- * Define getter/setter for this binding on scope
- * recursive for nested objects
- */
- BindingProto.def = function (scope, path) {
- var self = this,
- key = path[0]
- if (path.length === 1) {
- // here we are! at the end of the path!
- // define the real value accessors.
- def(scope, key, {
- get: function () {
- if (observer.isObserving) {
- observer.emit('get', self)
- }
- return self.isComputed
- ? self.value.get()
- : self.value
- },
- set: function (value) {
- if (self.isComputed) {
- // computed properties cannot be redefined
- // no need to call binding.update() here,
- // as dependency extraction has taken care of that
- if (self.value.set) {
- self.value.set(value)
- }
- } else if (value !== self.value) {
- self.update(value)
- }
- }
- })
- } else {
- // we are not there yet!!!
- // create an intermediate subscope
- // which also has its own getter/setters
- var subScope = scope[key]
- if (!subScope) {
- subScope = {}
- def(scope, key, {
- get: function () {
- return subScope
- },
- set: function (value) {
- // when the subScope is given a new value,
- // copy everything over to trigger the setters
- for (var prop in value) {
- subScope[prop] = value[prop]
- }
- }
- })
- }
- // recurse
- this.def(subScope, path.slice(1))
- }
- }
- /*
- * Process the value, then trigger updates on all dependents
- */
- BindingProto.update = function (value) {
- this.inspect(value)
- var i = this.instances.length
- while (i--) {
- this.instances[i].update(value)
- }
- this.pub()
- }
- /*
- * Notify computed properties that depend on this binding
- * to update themselves
- */
- BindingProto.pub = function () {
- var i = this.subs.length
- while (i--) {
- this.subs[i].refresh()
- }
- }
- module.exports = Binding
- });
- require.register("seed/src/directive-parser.js", function(exports, require, module){
- var config = require('./config'),
- directives = require('./directives'),
- filters = require('./filters')
- var KEY_RE = /^[^\|<]+/,
- ARG_RE = /([^:]+):(.+)$/,
- FILTERS_RE = /\|[^\|<]+/g,
- FILTER_TOKEN_RE = /[^\s']+|'[^']+'/g,
- INVERSE_RE = /^!/,
- NESTING_RE = /^\^+/,
- ONEWAY_RE = /-oneway$/
- /*
- * Directive class
- * represents a single directive instance in the DOM
- */
- function Directive (directiveName, expression, oneway) {
- var prop,
- definition = directives[directiveName]
- // mix in properties from the directive definition
- if (typeof definition === 'function') {
- this._update = definition
- } else {
- this._update = definition.update
- for (prop in definition) {
- if (prop !== 'update') {
- this[prop] = definition[prop]
- }
- }
- }
- this.oneway = !!oneway
- this.directiveName = directiveName
- this.expression = expression.trim()
- this.rawKey = expression.match(KEY_RE)[0].trim()
-
- this.parseKey(this.rawKey)
-
- var filterExps = expression.match(FILTERS_RE)
- this.filters = filterExps
- ? filterExps.map(parseFilter)
- : null
- }
- var DirProto = Directive.prototype
- /*
- * called when a new value is set
- * for computed properties, this will only be called once
- * during initialization.
- */
- DirProto.update = function (value) {
- if (value && (value === this.value)) return
- this.value = value
- this.apply(value)
- }
- /*
- * called when a dependency has changed
- * computed properties only
- */
- DirProto.refresh = function () {
- var value = this.value.get()
- if (value === this.computedValue) return
- this.computedValue = value
- this.apply(value)
- this.binding.pub()
- }
- /*
- * Actually invoking the _update from the directive's definition
- */
- DirProto.apply = function (value) {
- if (this.inverse) value = !value
- this._update(
- this.filters
- ? this.applyFilters(value)
- : value
- )
- }
- /*
- * pipe the value through filters
- */
- DirProto.applyFilters = function (value) {
- var filtered = value
- this.filters.forEach(function (filter) {
- if (!filter.apply) throw new Error('Unknown filter: ' + filter.name)
- filtered = filter.apply(filtered, filter.args)
- })
- return filtered
- }
- /*
- * parse a key, extract argument and nesting/root info
- */
- DirProto.parseKey = function (rawKey) {
- var argMatch = rawKey.match(ARG_RE)
- var key = argMatch
- ? argMatch[2].trim()
- : rawKey.trim()
- this.arg = argMatch
- ? argMatch[1].trim()
- : null
- this.inverse = INVERSE_RE.test(key)
- if (this.inverse) {
- key = key.slice(1)
- }
- var nesting = key.match(NESTING_RE)
- this.nesting = nesting
- ? nesting[0].length
- : false
- this.root = key.charAt(0) === '$'
- if (this.nesting) {
- key = key.replace(NESTING_RE, '')
- } else if (this.root) {
- key = key.slice(1)
- }
- this.key = key
- }
- /*
- * parse a filter expression
- */
- function parseFilter (filter) {
- var tokens = filter.slice(1)
- .match(FILTER_TOKEN_RE)
- .map(function (token) {
- return token.replace(/'/g, '').trim()
- })
- return {
- name : tokens[0],
- apply : filters[tokens[0]],
- args : tokens.length > 1
- ? tokens.slice(1)
- : null
- }
- }
- module.exports = {
- /*
- * make sure the directive and expression is valid
- * before we create an instance
- */
- parse: function (dirname, expression) {
- var prefix = config.prefix
- if (dirname.indexOf(prefix) === -1) return null
- dirname = dirname.slice(prefix.length + 1)
- var oneway = ONEWAY_RE.test(dirname)
- if (oneway) {
- dirname = dirname.slice(0, -7)
- }
- var dir = directives[dirname],
- valid = KEY_RE.test(expression)
- if (config.debug) {
- if (!dir) console.warn('unknown directive: ' + dirname)
- if (!valid) console.warn('invalid directive expression: ' + expression)
- }
- return dir && valid
- ? new Directive(dirname, expression, oneway)
- : null
- }
- }
- });
- require.register("seed/src/text-parser.js", function(exports, require, module){
- var config = require('./config'),
- ESCAPE_RE = /[-.*+?^${}()|[\]\/\\]/g,
- BINDING_RE
- /*
- * Escapes a string so that it can be used to construct RegExp
- */
- function escapeRegex (val) {
- return val.replace(ESCAPE_RE, '\\$&')
- }
- module.exports = {
- /*
- * Parse a piece of text, return an array of tokens
- */
- parse: function (node) {
- var text = node.nodeValue
- if (!BINDING_RE.test(text)) return null
- var m, i, tokens = []
- do {
- m = text.match(BINDING_RE)
- if (!m) break
- i = m.index
- if (i > 0) tokens.push(text.slice(0, i))
- tokens.push({ key: m[1] })
- text = text.slice(i + m[0].length)
- } while (true)
- if (text.length) tokens.push(text)
- return tokens
- },
- /*
- * Build interpolate tag regex from config settings
- */
- buildRegex: function () {
- var open = escapeRegex(config.interpolateTags.open),
- close = escapeRegex(config.interpolateTags.close)
- BINDING_RE = new RegExp(open + '(.+?)' + close)
- }
- }
- });
- require.register("seed/src/deps-parser.js", function(exports, require, module){
- var Emitter = require('emitter'),
- observer = new Emitter()
- /*
- * Auto-extract the dependencies of a computed property
- * by recording the getters triggered when evaluating it.
- *
- * However, the first pass will contain duplicate dependencies
- * for computed properties. It is therefore necessary to do a
- * second pass in injectDeps()
- */
- function catchDeps (binding) {
- observer.on('get', function (dep) {
- binding.deps.push(dep)
- })
- binding.value.get()
- observer.off('get')
- }
- /*
- * The second pass of dependency extraction.
- * Only include dependencies that don't have dependencies themselves.
- */
- function filterDeps (binding) {
- var i = binding.deps.length, dep
- while (i--) {
- dep = binding.deps[i]
- if (!dep.deps.length) {
- dep.subs.push.apply(dep.subs, binding.instances)
- } else {
- binding.deps.splice(i, 1)
- }
- }
- }
- module.exports = {
- /*
- * the observer that catches events triggered by getters
- */
- observer: observer,
- /*
- * parse a list of computed property bindings
- */
- parse: function (bindings) {
- observer.isObserving = true
- bindings.forEach(catchDeps)
- bindings.forEach(filterDeps)
- observer.isObserving = false
- }
- }
- });
- require.register("seed/src/filters.js", function(exports, require, module){
- var keyCodes = {
- enter: 13,
- tab: 9,
- 'delete': 46,
- up: 38,
- left: 37,
- right: 39,
- down: 40
- }
- module.exports = {
- capitalize: function (value) {
- value = value.toString()
- return value.charAt(0).toUpperCase() + value.slice(1)
- },
- uppercase: function (value) {
- return value.toString().toUpperCase()
- },
- lowercase: function (value) {
- return value.toString().toLowerCase()
- },
- currency: function (value, args) {
- if (!value) return value
- var sign = (args && args[0]) || '$',
- i = value % 3,
- f = '.' + value.toFixed(2).slice(-2),
- s = Math.floor(value).toString()
- return sign + s.slice(0, i) + s.slice(i).replace(/(\d{3})(?=\d)/g, '$1,') + f
- },
- key: function (handler, args) {
- var code = keyCodes[args[0]]
- if (!code) {
- code = parseInt(args[0], 10)
- }
- return function (e) {
- if (e.originalEvent.keyCode === code) {
- handler.call(this, e)
- }
- }
- }
- }
- });
- require.register("seed/src/directives/index.js", function(exports, require, module){
- module.exports = {
- on : require('./on'),
- each : require('./each'),
- attr: function (value) {
- this.el.setAttribute(this.arg, value)
- },
- text: function (value) {
- this.el.textContent =
- (typeof value === 'string' || typeof value === 'number')
- ? value : ''
- },
- html: function (value) {
- this.el.innerHTML =
- (typeof value === 'string' || typeof value === 'number')
- ? value : ''
- },
- show: function (value) {
- this.el.style.display = value ? '' : 'none'
- },
- visible: function (value) {
- this.el.style.visibility = value ? '' : 'hidden'
- },
-
- focus: function (value) {
- // yield so it work when toggling visibility
- var el = this.el
- setTimeout(function () {
- el[value ? 'focus' : 'blur']()
- }, 0)
- },
- class: function (value) {
- if (this.arg) {
- this.el.classList[value ? 'add' : 'remove'](this.arg)
- } else {
- if (this.lastVal) {
- this.el.classList.remove(this.lastVal)
- }
- this.el.classList.add(value)
- this.lastVal = value
- }
- },
- value: {
- bind: function () {
- if (this.oneway) return
- var el = this.el, self = this
- this.change = function () {
- self.seed.scope[self.key] = el.value
- }
- el.addEventListener('change', this.change)
- },
- update: function (value) {
- this.el.value = value
- },
- unbind: function () {
- if (this.oneway) return
- this.el.removeEventListener('change', this.change)
- }
- },
- checked: {
- bind: function () {
- if (this.oneway) return
- var el = this.el, self = this
- this.change = function () {
- self.seed.scope[self.key] = el.checked
- }
- el.addEventListener('change', this.change)
- },
- update: function (value) {
- this.el.checked = !!value
- },
- unbind: function () {
- if (this.oneway) return
- this.el.removeEventListener('change', this.change)
- }
- },
- 'if': {
- bind: function () {
- this.parent = this.el.parentNode
- this.ref = document.createComment('sd-if-' + this.key)
- var next = this.el.nextSibling
- if (next) {
- this.parent.insertBefore(this.ref, next)
- } else {
- this.parent.appendChild(this.ref)
- }
- },
- update: function (value) {
- if (!value) {
- if (this.el.parentNode) {
- this.parent.removeChild(this.el)
- }
- } else {
- if (!this.el.parentNode) {
- this.parent.insertBefore(this.el, this.ref)
- }
- }
- }
- },
- style: {
- bind: function () {
- this.arg = convertCSSProperty(this.arg)
- },
- update: function (value) {
- this.el.style[this.arg] = value
- }
- }
- }
- /*
- * convert hyphen style CSS property to Camel style
- */
- var CONVERT_RE = /-(.)/g
- function convertCSSProperty (prop) {
- if (prop.charAt(0) === '-') prop = prop.slice(1)
- return prop.replace(CONVERT_RE, function (m, char) {
- return char.toUpperCase()
- })
- }
- });
- require.register("seed/src/directives/each.js", function(exports, require, module){
- var config = require('../config')
- /*
- * Mathods that perform precise DOM manipulation
- * based on mutator method triggered
- */
- var mutationHandlers = {
- push: function (m) {
- var self = this
- m.args.forEach(function (data, i) {
- var seed = self.buildItem(data, self.collection.length + i)
- self.container.insertBefore(seed.el, self.ref)
- })
- },
- pop: function (m) {
- m.result.$destroy()
- },
- unshift: function (m) {
- var self = this
- m.args.forEach(function (data, i) {
- var seed = self.buildItem(data, i),
- ref = self.collection.length > m.args.length
- ? self.collection[m.args.length].$el
- : self.ref
- self.container.insertBefore(seed.el, ref)
- })
- self.updateIndexes()
- },
- shift: function (m) {
- m.result.$destroy()
- var self = this
- self.updateIndexes()
- },
- splice: function (m) {
- var self = this,
- index = m.args[0],
- removed = m.args[1],
- added = m.args.length - 2
- m.result.forEach(function (scope) {
- scope.$destroy()
- })
- if (added > 0) {
- m.args.slice(2).forEach(function (data, i) {
- var seed = self.buildItem(data, index + i),
- pos = index - removed + added + 1,
- ref = self.collection[pos]
- ? self.collection[pos].$el
- : self.ref
- self.container.insertBefore(seed.el, ref)
- })
- }
- if (removed !== added) {
- self.updateIndexes()
- }
- },
- sort: function () {
- var self = this
- self.collection.forEach(function (scope, i) {
- scope.$index = i
- self.container.insertBefore(scope.$el, self.ref)
- })
- }
- }
- mutationHandlers.reverse = mutationHandlers.sort
- module.exports = {
- bind: function () {
- this.el.removeAttribute(config.prefix + '-each')
- var ctn = this.container = this.el.parentNode
- // create a comment node as a reference node for DOM insertions
- this.ref = document.createComment('sd-each-' + this.arg)
- ctn.insertBefore(this.ref, this.el)
- ctn.removeChild(this.el)
- },
- update: function (collection) {
- this.unbind(true)
- if (!Array.isArray(collection)) return
- this.collection = collection
- // attach an object to container to hold handlers
- this.container.sd_dHandlers = {}
- // listen for collection mutation events
- // the collection has been augmented during Binding.set()
- var self = this
- collection.on('mutate', function (mutation) {
- mutationHandlers[mutation.method].call(self, mutation)
- })
- // create child-seeds and append to DOM
- collection.forEach(function (data, i) {
- var seed = self.buildItem(data, i)
- self.container.insertBefore(seed.el, self.ref)
- })
- },
- buildItem: function (data, index) {
- var Seed = require('../seed'),
- node = this.el.cloneNode(true)
- var spore = new Seed(node, {
- each: true,
- eachPrefix: this.arg + '.',
- parentSeed: this.seed,
- index: index,
- data: data,
- delegator: this.container
- })
- this.collection[index] = spore.scope
- return spore
- },
- updateIndexes: function () {
- this.collection.forEach(function (scope, i) {
- scope.$index = i
- })
- },
- unbind: function (reset) {
- if (this.collection && this.collection.length) {
- var fn = reset ? '_destroy' : '_unbind'
- this.collection.forEach(function (scope) {
- scope.$seed[fn]()
- })
- this.collection = null
- }
- var ctn = this.container,
- handlers = ctn.sd_dHandlers
- for (var key in handlers) {
- ctn.removeEventListener(handlers[key].event, handlers[key])
- }
- delete ctn.sd_dHandlers
- }
- }
- });
- require.register("seed/src/directives/on.js", function(exports, require, module){
- function delegateCheck (current, top, identifier) {
- if (current[identifier]) {
- return current
- } else if (current === top) {
- return false
- } else {
- return delegateCheck(current.parentNode, top, identifier)
- }
- }
- module.exports = {
- expectFunction : true,
- bind: function () {
- if (this.seed.each) {
- // attach an identifier to the el
- // so it can be matched during event delegation
- this.el[this.expression] = true
- // attach the owner scope of this directive
- this.el.sd_scope = this.seed.scope
- }
- },
- update: function (handler) {
- this.unbind()
- if (!handler) return
- var seed = this.seed,
- event = this.arg
- if (seed.each && event !== 'blur' && event !== 'blur') {
- // for each blocks, delegate for better performance
- // focus and blur events dont bubble so exclude them
- var delegator = seed.delegator,
- identifier = this.expression,
- dHandler = delegator.sd_dHandlers[identifier]
- if (dHandler) return
- // the following only gets run once for the entire each block
- dHandler = delegator.sd_dHandlers[identifier] = function (e) {
- var target = delegateCheck(e.target, delegator, identifier)
- if (target) {
- handler.call(seed.scope, {
- el: target,
- scope: target.sd_scope,
- originalEvent: e
- })
- }
- }
- dHandler.event = event
- delegator.addEventListener(event, dHandler)
- } else {
- // a normal, single element handler
- this.handler = function (e) {
- handler.call(seed.scope, {
- el: e.currentTarget,
- scope: seed.scope,
- originalEvent: e
- })
- }
- this.el.addEventListener(event, this.handler)
- }
- },
- unbind: function () {
- this.el.removeEventListener(this.arg, this.handler)
- }
- }
- });
- require.alias("component-emitter/index.js", "seed/deps/emitter/index.js");
- require.alias("component-emitter/index.js", "emitter/index.js");
- require.alias("component-indexof/index.js", "component-emitter/deps/indexof/index.js");
- require.alias("seed/src/main.js", "seed/index.js");
- window.Seed = window.Seed || require('seed')
- Seed.version = '0.1.1'
- })();
|