| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547 |
- ;(function(){
- /**
- * 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._resolving && !module.exports) {
- var mod = {};
- mod.exports = {};
- mod.client = mod.component = true;
- module._resolving = true;
- module.call(this, mod.exports, require.relative(resolved), mod);
- delete module._resolving;
- module.exports = mod.exports;
- }
- 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){
- var indexOf = [].indexOf;
- module.exports = function(arr, obj){
- if (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'),
- ViewModel = require('./viewmodel'),
- directives = require('./directives'),
- filters = require('./filters'),
- utils = require('./utils')
- /*
- * Set config options
- */
- ViewModel.config = function (opts) {
- if (opts) {
- utils.extend(config, opts)
- }
- }
- /*
- * Allows user to register/retrieve a directive definition
- */
- ViewModel.directive = function (id, fn) {
- if (!fn) return directives[id]
- directives[id] = fn
- }
- /*
- * Allows user to register/retrieve a filter function
- */
- ViewModel.filter = function (id, fn) {
- if (!fn) return filters[id]
- filters[id] = fn
- }
- /*
- * Allows user to register/retrieve a ViewModel constructor
- */
- ViewModel.vm = function (id, Ctor) {
- if (!Ctor) return utils.vms[id]
- utils.vms[id] = Ctor
- }
- /*
- * Allows user to register/retrieve a template partial
- */
- ViewModel.partial = function (id, partial) {
- if (!partial) return utils.partials[id]
- utils.partials[id] = templateToFragment(partial)
- }
- /*
- * Allows user to register/retrieve a transition definition object
- */
- ViewModel.transition = function (id, transition) {
- if (!transition) return utils.transitions[id]
- utils.transitions[id] = transition
- }
- ViewModel.extend = extend
- /*
- * Expose the main ViewModel class
- * and add extend method
- */
- function extend (options) {
- var ParentVM = this
- // inherit options
- options = inheritOptions(options, ParentVM.options, true)
- var ExtendedVM = function (opts) {
- opts = inheritOptions(opts, options, true)
- ParentVM.call(this, opts)
- }
- // inherit prototype props
- var proto = ExtendedVM.prototype = Object.create(ParentVM.prototype)
- utils.defProtected(proto, 'constructor', ExtendedVM)
- // copy prototype props
- var protoMixins = options.proto
- if (protoMixins) {
- for (var key in protoMixins) {
- if (!(key in ViewModel.prototype)) {
- proto[key] = protoMixins[key]
- }
- }
- }
- // convert template to documentFragment
- if (options.template) {
- options.templateFragment = templateToFragment(options.template)
- }
- // allow extended VM to be further extended
- ExtendedVM.extend = extend
- ExtendedVM.super = ParentVM
- ExtendedVM.options = options
- return ExtendedVM
- }
- /*
- * Inherit options
- *
- * For options such as `scope`, `vms`, `directives`, 'partials',
- * they should be further extended. However extending should only
- * be done at top level.
- *
- * `proto` is an exception because it's handled directly on the
- * prototype.
- *
- * `el` is an exception because it's not allowed as an
- * extension option, but only as an instance option.
- */
- function inheritOptions (child, parent, topLevel) {
- child = child || {}
- convertPartials(child.partials)
- if (!parent) return child
- for (var key in parent) {
- if (key === 'el' || key === 'proto') continue
- if (!child[key]) { // child has priority
- child[key] = parent[key]
- } else if (topLevel && utils.typeOf(child[key]) === 'Object') {
- inheritOptions(child[key], parent[key], false)
- }
- }
- return child
- }
- /*
- * Convert an object of partials to dom fragments
- */
- function convertPartials (partials) {
- if (!partials) return
- for (var key in partials) {
- if (typeof partials[key] === 'string') {
- partials[key] = templateToFragment(partials[key])
- }
- }
- }
- /*
- * Convert a string template to a dom fragment
- */
- function templateToFragment (template) {
- if (template.charAt(0) === '#') {
- var templateNode = document.querySelector(template)
- if (!templateNode) return
- template = templateNode.innerHTML
- }
- var node = document.createElement('div'),
- frag = document.createDocumentFragment(),
- child
- node.innerHTML = template.trim()
- /* jshint boss: true */
- while (child = node.firstChild) {
- frag.appendChild(child)
- }
- return frag
- }
- module.exports = ViewModel
- });
- require.register("seed/src/emitter.js", function(exports, require, module){
- // shiv to make this work for Component, Browserify and Node at the same time.
- var Emitter,
- componentEmitter = 'emitter'
- try {
- // Requiring without a string literal will make browserify
- // unable to parse the dependency, thus preventing it from
- // stopping the compilation after a failed lookup.
- Emitter = require(componentEmitter)
- } catch (e) {}
- module.exports = Emitter || require('events').EventEmitter
- });
- require.register("seed/src/config.js", function(exports, require, module){
- module.exports = {
- prefix : 'sd',
- debug : false
-
- }
- });
- require.register("seed/src/utils.js", function(exports, require, module){
- var config = require('./config'),
- toString = Object.prototype.toString,
- join = Array.prototype.join,
- console = window.console
- module.exports = {
- // global storage for user-registered
- // vms, partials and transitions
- vms : {},
- partials : {},
- transitions : {},
- /*
- * Define an ienumerable property
- * This avoids it being included in JSON.stringify
- * or for...in loops.
- */
- defProtected: function (obj, key, val, enumerable) {
- if (obj.hasOwnProperty(key)) return
- Object.defineProperty(obj, key, {
- enumerable: !!enumerable,
- configurable: false,
- value: val
- })
- },
- /*
- * Accurate type check
- */
- typeOf: function (obj) {
- return toString.call(obj).slice(8, -1)
- },
- /*
- * Make sure only strings and numbers are output to html
- * output empty string is value is not string or number
- */
- toText: function (value) {
- /* jshint eqeqeq: false */
- return (typeof value === 'string' ||
- (typeof value === 'number' && value == value)) // deal with NaN
- ? value
- : ''
- },
- /*
- * simple extend
- */
- extend: function (obj, ext, protective) {
- if (!ext) return
- for (var key in ext) {
- if (protective && obj[key]) continue
- obj[key] = ext[key]
- }
- },
- /*
- * log for debugging
- */
- log: function () {
- if (config.debug && console) {
- console.log(join.call(arguments, ' '))
- }
- },
-
- /*
- * warn for debugging
- */
- warn: function() {
- if (config.debug && console) {
- console.warn(join.call(arguments, ' '))
- }
- }
- }
- });
- require.register("seed/src/compiler.js", function(exports, require, module){
- var Emitter = require('./emitter'),
- Observer = require('./observer'),
- config = require('./config'),
- utils = require('./utils'),
- Binding = require('./binding'),
- Directive = require('./directive'),
- TextParser = require('./text-parser'),
- DepsParser = require('./deps-parser'),
- ExpParser = require('./exp-parser'),
- slice = Array.prototype.slice,
- log = utils.log,
- vmAttr,
- repeatAttr,
- partialAttr,
- transitionAttr,
- preAttr
- /*
- * The DOM compiler
- * scans a DOM node and compile bindings for a ViewModel
- */
- function Compiler (vm, options) {
- refreshPrefix()
- var compiler = this
- // extend options
- options = compiler.options = options || {}
- utils.extend(compiler, options.compilerOptions)
- // initialize element
- compiler.setupElement(options)
- log('\nnew VM instance:', compiler.el.tagName, '\n')
- // copy scope properties to vm
- var scope = options.scope
- if (scope) utils.extend(vm, scope, true)
- compiler.vm = vm
- vm.$compiler = compiler
- vm.$el = compiler.el
- // keep track of directives and expressions
- // so they can be unbound during destroy()
- compiler.dirs = []
- compiler.exps = []
- compiler.childCompilers = [] // keep track of child compilers
- compiler.emitter = new Emitter() // the emitter used for nested VM communication
- // Store things during parsing to be processed afterwards,
- // because we want to have created all bindings before
- // observing values / parsing dependencies.
- var observables = compiler.observables = [],
- computed = compiler.computed = []
- // prototypal inheritance of bindings
- var parent = compiler.parentCompiler
- compiler.bindings = parent
- ? Object.create(parent.bindings)
- : {}
- compiler.rootCompiler = parent
- ? getRoot(parent)
- : compiler
- // setup observer
- compiler.setupObserver()
- // call user init. this will capture some initial values.
- if (options.init) {
- options.init.apply(vm, options.args || [])
- }
- // create bindings for keys set on the vm by the user
- var key, keyPrefix
- for (key in vm) {
- keyPrefix = key.charAt(0)
- if (keyPrefix !== '$' && keyPrefix !== '_') {
- compiler.createBinding(key)
- }
- }
- // for repeated items, create an index binding
- if (compiler.repeat) {
- vm[compiler.repeatPrefix].$index = compiler.repeatIndex
- }
- // now parse the DOM, during which we will create necessary bindings
- // and bind the parsed directives
- compiler.compile(compiler.el, true)
- // observe root values so that they emit events when
- // their nested values change (for an Object)
- // or when they mutate (for an Array)
- var i = observables.length, binding
- while (i--) {
- binding = observables[i]
- Observer.observe(binding.value, binding.key, compiler.observer)
- }
- // extract dependencies for computed properties
- if (computed.length) DepsParser.parse(computed)
- // unset these no longer needed stuff
- compiler.observables = compiler.computed = compiler.arrays = null
- }
- var CompilerProto = Compiler.prototype
- /*
- * Initialize the VM/Compiler's element.
- * Fill it in with the template if necessary.
- */
- CompilerProto.setupElement = function (options) {
- // create the node first
- var el = this.el = typeof options.el === 'string'
- ? document.querySelector(options.el)
- : options.el || document.createElement(options.tagName || 'div')
- // apply element options
- if (options.id) el.id = options.id
- if (options.className) el.className = options.className
- var attrs = options.attributes
- if (attrs) {
- for (var attr in attrs) {
- el.setAttribute(attr, attrs[attr])
- }
- }
- // initialize template
- var template = options.template
- if (typeof template === 'string') {
- if (template.charAt(0) === '#') {
- var templateNode = document.querySelector(template)
- if (templateNode) {
- el.innerHTML = templateNode.innerHTML
- }
- } else {
- el.innerHTML = template
- }
- } else if (options.templateFragment) {
- el.innerHTML = ''
- el.appendChild(options.templateFragment.cloneNode(true))
- }
- }
- /*
- * Setup observer.
- * The observer listens for get/set/mutate events on all VM
- * values/objects and trigger corresponding binding updates.
- */
- CompilerProto.setupObserver = function () {
- var bindings = this.bindings,
- observer = this.observer = new Emitter(),
- depsOb = DepsParser.observer
- // a hash to hold event proxies for each root level key
- // so they can be referenced and removed later
- observer.proxies = {}
- // add own listeners which trigger binding updates
- observer
- .on('get', function (key) {
- if (bindings[key] && depsOb.isObserving) {
- depsOb.emit('get', bindings[key])
- }
- })
- .on('set', function (key, val) {
- observer.emit('change:' + key, val)
- if (bindings[key]) bindings[key].update(val)
- })
- .on('mutate', function (key, val, mutation) {
- observer.emit('change:' + key, val, mutation)
- if (bindings[key]) bindings[key].pub()
- })
- }
- /*
- * Compile a DOM node (recursive)
- */
- CompilerProto.compile = function (node, root) {
- var compiler = this
- if (node.nodeType === 1) {
- // a normal node
- if (node.hasAttribute(preAttr)) return
- var repeatExp = node.getAttribute(repeatAttr),
- vmId = node.getAttribute(vmAttr),
- partialId = node.getAttribute(partialAttr)
- // we need to check for any possbile special directives
- // e.g. sd-repeat, sd-viewmodel & sd-partial
- if (repeatExp) { // repeat block
- var directive = Directive.parse(repeatAttr, repeatExp, compiler, node)
- if (directive) {
- compiler.bindDirective(directive)
- }
- } else if (vmId && !root) { // child ViewModels
- node.removeAttribute(vmAttr)
- var ChildVM = compiler.getOption('vms', vmId)
- if (ChildVM) {
- var child = new ChildVM({
- el: node,
- child: true,
- compilerOptions: {
- parentCompiler: compiler
- }
- })
- compiler.childCompilers.push(child.$compiler)
- }
- } else {
- if (partialId) { // replace innerHTML with partial
- node.removeAttribute(partialAttr)
- var partial = compiler.getOption('partials', partialId)
- if (partial) {
- node.innerHTML = ''
- node.appendChild(partial.cloneNode(true))
- }
- }
- // finally, only normal directives left!
- compiler.compileNode(node)
- }
- } else if (node.nodeType === 3) { // text node
- compiler.compileTextNode(node)
- }
- }
- /*
- * Compile a normal node
- */
- CompilerProto.compileNode = function (node) {
- var i, j
- // parse if has attributes
- if (node.attributes && node.attributes.length) {
- var attrs = slice.call(node.attributes),
- attr, valid, exps, exp
- // loop through all attributes
- i = attrs.length
- while (i--) {
- attr = attrs[i]
- valid = false
- exps = attr.value.split(',')
- // loop through clauses (separated by ",")
- // inside each attribute
- j = exps.length
- while (j--) {
- exp = exps[j]
- var directive = Directive.parse(attr.name, exp, this, node)
- if (directive) {
- valid = true
- this.bindDirective(directive)
- }
- }
- if (valid) node.removeAttribute(attr.name)
- }
- }
- // recursively compile childNodes
- if (node.childNodes.length) {
- var nodes = slice.call(node.childNodes)
- for (i = 0, j = nodes.length; i < j; i++) {
- this.compile(nodes[i])
- }
- }
- }
- /*
- * Compile a text node
- */
- CompilerProto.compileTextNode = function (node) {
- var tokens = TextParser.parse(node.nodeValue)
- if (!tokens) return
- var dirname = config.prefix + '-text',
- el, token, directive
- for (var i = 0, l = tokens.length; i < l; i++) {
- token = tokens[i]
- if (token.key) { // a binding
- if (token.key.charAt(0) === '>') { // a partial
- var partialId = token.key.slice(1).trim(),
- partial = this.getOption('partials', partialId)
- if (partial) {
- el = partial.cloneNode(true)
- this.compileNode(el)
- }
- } else { // a binding
- el = document.createTextNode('')
- directive = Directive.parse(dirname, token.key, this, el)
- if (directive) {
- this.bindDirective(directive)
- }
- }
- } else { // a plain string
- el = document.createTextNode(token)
- }
- node.parentNode.insertBefore(el, node)
- }
- node.parentNode.removeChild(node)
- }
- /*
- * Add a directive instance to the correct binding & viewmodel
- */
- CompilerProto.bindDirective = function (directive) {
- var binding,
- compiler = this,
- key = directive.key,
- baseKey = key.split('.')[0],
- ownerCompiler = traceOwnerCompiler(directive, compiler)
- compiler.dirs.push(directive)
- if (directive.isExp) {
- binding = compiler.createBinding(key, true)
- } else if (ownerCompiler.vm.hasOwnProperty(baseKey)) {
- // if the value is present in the target VM, we create the binding on its compiler
- binding = ownerCompiler.bindings.hasOwnProperty(key)
- ? ownerCompiler.bindings[key]
- : ownerCompiler.createBinding(key)
- } else {
- // due to prototypal inheritance of bindings, if a key doesn't exist here,
- // it doesn't exist in the whole prototype chain. Therefore in that case
- // we create the new binding at the root level.
- binding = ownerCompiler.bindings[key] || compiler.rootCompiler.createBinding(key)
- }
- binding.instances.push(directive)
- directive.binding = binding
- // for newly inserted sub-VMs (repeat items), need to bind deps
- // because they didn't get processed when the parent compiler
- // was binding dependencies.
- var i, dep, deps = binding.contextDeps
- if (deps) {
- i = deps.length
- while (i--) {
- dep = compiler.bindings[deps[i]]
- dep.subs.push(directive)
- }
- }
- var value = binding.value
- // invoke bind hook if exists
- if (directive.bind) {
- directive.bind(value)
- }
- // set initial value
- if (binding.isComputed) {
- directive.refresh(value)
- } else {
- directive.update(value, true)
- }
- }
- /*
- * Create binding and attach getter/setter for a key to the viewmodel object
- */
- CompilerProto.createBinding = function (key, isExp) {
- var compiler = this,
- bindings = compiler.bindings,
- binding = new Binding(compiler, key, isExp)
- if (isExp) {
- // a complex expression binding
- // we need to generate an anonymous computed property for it
- var result = ExpParser.parse(key)
- if (result) {
- log(' created anonymous binding: ' + key)
- binding.value = { get: result.getter }
- compiler.markComputed(binding)
- compiler.exps.push(binding)
- // need to create the bindings for keys
- // that do not exist yet
- var i = result.vars.length, v
- while (i--) {
- v = result.vars[i]
- if (!bindings[v]) {
- compiler.rootCompiler.createBinding(v)
- }
- }
- } else {
- utils.warn(' invalid expression: ' + key)
- }
- } else {
- log(' created binding: ' + key)
- bindings[key] = binding
- // make sure the key exists in the object so it can be observed
- // by the Observer!
- compiler.ensurePath(key)
- if (binding.root) {
- // this is a root level binding. we need to define getter/setters for it.
- compiler.define(key, binding)
- } else {
- var parentKey = key.slice(0, key.lastIndexOf('.'))
- if (!bindings.hasOwnProperty(parentKey)) {
- // this is a nested value binding, but the binding for its parent
- // has not been created yet. We better create that one too.
- compiler.createBinding(parentKey)
- }
- }
- }
- return binding
- }
- /*
- * Sometimes when a binding is found in the template, the value might
- * have not been set on the VM yet. To ensure computed properties and
- * dependency extraction can work, we have to create a dummy value for
- * any given path.
- */
- CompilerProto.ensurePath = function (key) {
- var path = key.split('.'), sec, obj = this.vm
- for (var i = 0, d = path.length - 1; i < d; i++) {
- sec = path[i]
- if (!obj[sec]) obj[sec] = {}
- obj = obj[sec]
- }
- if (utils.typeOf(obj) === 'Object') {
- sec = path[i]
- if (!(sec in obj)) obj[sec] = undefined
- }
- }
- /*
- * Defines the getter/setter for a root-level binding on the VM
- * and observe the initial value
- */
- CompilerProto.define = function (key, binding) {
- log(' defined root binding: ' + key)
- var compiler = this,
- vm = compiler.vm,
- ob = compiler.observer,
- value = binding.value = vm[key], // save the value before redefinening it
- type = utils.typeOf(value)
- if (type === 'Object' && value.get) {
- // computed property
- compiler.markComputed(binding)
- } else if (type === 'Object' || type === 'Array') {
- // observe objects later, becase there might be more keys
- // to be added to it. we also want to emit all the set events
- // after all values are available.
- compiler.observables.push(binding)
- }
- Object.defineProperty(vm, key, {
- enumerable: true,
- get: function () {
- var value = binding.value
- if ((!binding.isComputed && (!value || !value.__observer__)) ||
- Array.isArray(value)) {
- // only emit non-computed, non-observed (primitive) values, or Arrays.
- // because these are the cleanest dependencies
- ob.emit('get', key)
- }
- return binding.isComputed
- ? value.get()
- : value
- },
- set: function (newVal) {
- var value = binding.value
- if (binding.isComputed) {
- if (value.set) {
- value.set(newVal)
- }
- } else if (newVal !== value) {
- // unwatch the old value
- Observer.unobserve(value, key, ob)
- // set new value
- binding.value = newVal
- ob.emit('set', key, newVal)
- // now watch the new value, which in turn emits 'set'
- // for all its nested values
- Observer.observe(newVal, key, ob)
- }
- }
- })
- }
- /*
- * Process a computed property binding
- */
- CompilerProto.markComputed = function (binding) {
- var value = binding.value,
- vm = this.vm
- binding.isComputed = true
- // bind the accessors to the vm
- value.get = value.get.bind(vm)
- if (value.set) value.set = value.set.bind(vm)
- // keep track for dep parsing later
- this.computed.push(binding)
- }
- /*
- * Process subscriptions for computed properties that has
- * dynamic context dependencies
- */
- CompilerProto.bindContexts = function (bindings) {
- var i = bindings.length, j, k, binding, depKey, dep, ins
- while (i--) {
- binding = bindings[i]
- j = binding.contextDeps.length
- while (j--) {
- depKey = binding.contextDeps[j]
- k = binding.instances.length
- while (k--) {
- ins = binding.instances[k]
- dep = ins.compiler.bindings[depKey]
- dep.subs.push(ins)
- }
- }
- }
- }
- /*
- * Retrive an option from the compiler
- */
- CompilerProto.getOption = function (type, id) {
- var opts = this.options
- return (opts[type] && opts[type][id]) || (utils[type] && utils[type][id])
- }
- /*
- * Unbind and remove element
- */
- CompilerProto.destroy = function () {
- var compiler = this
- log('compiler destroyed: ', compiler.vm.$el)
- // unwatch
- compiler.observer.off()
- compiler.emitter.off()
- var i, key, dir, inss, binding,
- el = compiler.el,
- directives = compiler.dirs,
- exps = compiler.exps,
- bindings = compiler.bindings
- // remove all directives that are instances of external bindings
- i = directives.length
- while (i--) {
- dir = directives[i]
- if (dir.binding.compiler !== compiler) {
- inss = dir.binding.instances
- if (inss) inss.splice(inss.indexOf(dir), 1)
- }
- dir.unbind()
- }
- // unbind all expressions (anonymous bindings)
- i = exps.length
- while (i--) {
- exps[i].unbind()
- }
- // unbind/unobserve all own bindings
- for (key in bindings) {
- if (bindings.hasOwnProperty(key)) {
- binding = bindings[key]
- if (binding.root) {
- Observer.unobserve(binding.value, binding.key, compiler.observer)
- }
- binding.unbind()
- }
- }
- // remove self from parentCompiler
- var parent = compiler.parentCompiler
- if (parent) {
- parent.childCompilers.splice(parent.childCompilers.indexOf(compiler), 1)
- }
- // remove el
- if (el === document.body) {
- el.innerHTML = ''
- } else if (el.parentNode) {
- el.parentNode.removeChild(el)
- }
- }
- // Helpers --------------------------------------------------------------------
- /*
- * Refresh prefix in case it has been changed
- * during compilations
- */
- function refreshPrefix () {
- var prefix = config.prefix
- repeatAttr = prefix + '-repeat'
- vmAttr = prefix + '-viewmodel'
- partialAttr = prefix + '-partial'
- transitionAttr = prefix + '-transition'
- preAttr = prefix + '-pre'
- }
- /*
- * determine which viewmodel a key belongs to based on nesting symbols
- */
- function traceOwnerCompiler (key, compiler) {
- if (key.nesting) {
- var levels = key.nesting
- while (compiler.parentCompiler && levels--) {
- compiler = compiler.parentCompiler
- }
- } else if (key.root) {
- while (compiler.parentCompiler) {
- compiler = compiler.parentCompiler
- }
- }
- return compiler
- }
- /*
- * shorthand for getting root compiler
- */
- function getRoot (compiler) {
- return traceOwnerCompiler({ root: true }, compiler)
- }
- module.exports = Compiler
- });
- require.register("seed/src/viewmodel.js", function(exports, require, module){
- var Compiler = require('./compiler')
- /*
- * ViewModel exposed to the user that holds data,
- * computed properties, event handlers
- * and a few reserved methods
- */
- function ViewModel (options) {
- // just compile. options are passed directly to compiler
- new Compiler(this, options)
- }
- var VMProto = ViewModel.prototype
- /*
- * Convenience function to set an actual nested value
- * from a flat key string. Used in directives.
- */
- VMProto.$set = function (key, value) {
- var path = key.split('.'),
- obj = getTargetVM(this, path)
- if (!obj) return
- for (var d = 0, l = path.length - 1; d < l; d++) {
- obj = obj[path[d]]
- }
- obj[path[d]] = value
- }
- /*
- * The function for getting a key
- * which will go up along the prototype chain of the bindings
- * Used in exp-parser.
- */
- VMProto.$get = function (key) {
- var path = key.split('.'),
- obj = getTargetVM(this, path),
- vm = obj
- if (!obj) return
- for (var d = 0, l = path.length; d < l; d++) {
- obj = obj[path[d]]
- }
- if (typeof obj === 'function') obj = obj.bind(vm)
- return obj
- }
- /*
- * watch a key on the viewmodel for changes
- * fire callback with new value
- */
- VMProto.$watch = function (key, callback) {
- this.$compiler.observer.on('change:' + key, callback)
- }
- /*
- * unwatch a key
- */
- VMProto.$unwatch = function (key, callback) {
- // workaround here
- // since the emitter module checks callback existence
- // by checking the length of arguments
- var args = ['change:' + key],
- ob = this.$compiler.observer
- if (callback) args.push(callback)
- ob.off.apply(ob, args)
- }
- /*
- * unbind everything, remove everything
- */
- VMProto.$destroy = function () {
- this.$compiler.destroy()
- this.$compiler = null
- }
- /*
- * broadcast an event to all child VMs recursively.
- */
- VMProto.$broadcast = function () {
- var children = this.$compiler.childCompilers,
- i = children.length,
- child
- while (i--) {
- child = children[i]
- child.emitter.emit.apply(child.emitter, arguments)
- child.vm.$broadcast.apply(child.vm, arguments)
- }
- }
- /*
- * emit an event that propagates all the way up to parent VMs.
- */
- VMProto.$emit = function () {
- var parent = this.$compiler.parentCompiler
- if (parent) {
- parent.emitter.emit.apply(parent.emitter, arguments)
- parent.vm.$emit.apply(parent.vm, arguments)
- }
- }
- /*
- * delegate on/off/once to the compiler's emitter
- */
- ;['on', 'off', 'once'].forEach(function (method) {
- VMProto['$' + method] = function () {
- var emitter = this.$compiler.emitter
- emitter[method].apply(emitter, arguments)
- }
- })
- /*
- * If a VM doesn't contain a path, go up the prototype chain
- * to locate the ancestor that has it.
- */
- function getTargetVM (vm, path) {
- var baseKey = path[0],
- binding = vm.$compiler.bindings[baseKey]
- return binding
- ? binding.compiler.vm
- : null
- }
- module.exports = ViewModel
- });
- require.register("seed/src/binding.js", function(exports, require, module){
- /*
- * Binding class.
- *
- * each property on the viewmodel has one corresponding Binding object
- * which has multiple directive instances on the DOM
- * and multiple computed property dependents
- */
- function Binding (compiler, key, isExp) {
- this.value = undefined
- this.isExp = !!isExp
- this.root = !this.isExp && key.indexOf('.') === -1
- this.compiler = compiler
- this.key = key
- this.instances = []
- this.subs = []
- this.deps = []
- }
- var BindingProto = Binding.prototype
- /*
- * Process the value, then trigger updates on all dependents
- */
- BindingProto.update = function (value) {
- this.value = value
- var i = this.instances.length
- while (i--) {
- this.instances[i].update(value)
- }
- this.pub()
- }
- /*
- * -- computed property only --
- * Force all instances to re-evaluate themselves
- */
- BindingProto.refresh = function () {
- var i = this.instances.length
- while (i--) {
- this.instances[i].refresh()
- }
- 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()
- }
- }
- /*
- * Unbind the binding, remove itself from all of its dependencies
- */
- BindingProto.unbind = function () {
- var i = this.instances.length
- while (i--) {
- this.instances[i].unbind()
- }
- i = this.deps.length
- var subs
- while (i--) {
- subs = this.deps[i].subs
- subs.splice(subs.indexOf(this), 1)
- }
- this.compiler = this.pubs = this.subs = this.instances = this.deps = null
- }
- module.exports = Binding
- });
- require.register("seed/src/observer.js", function(exports, require, module){
- /* jshint proto:true */
- var Emitter = require('./emitter'),
- utils = require('./utils'),
- typeOf = utils.typeOf,
- def = utils.defProtected,
- slice = Array.prototype.slice,
- methods = ['push','pop','shift','unshift','splice','sort','reverse'],
- hasProto = ({}).__proto__ // fix for IE9
- // The proxy prototype to replace the __proto__ of
- // an observed array
- var ArrayProxy = Object.create(Array.prototype)
- // Define mutation interceptors so we can emit the mutation info
- methods.forEach(function (method) {
- def(ArrayProxy, method, function () {
- var result = Array.prototype[method].apply(this, arguments)
- this.__observer__.emit('mutate', this.__observer__.path, this, {
- method: method,
- args: slice.call(arguments),
- result: result
- })
- return result
- }, !hasProto)
- })
- // Augment it with several convenience methods
- var extensions = {
- remove: function (index) {
- if (typeof index !== 'number') index = this.indexOf(index)
- return this.splice(index, 1)[0]
- },
- replace: function (index, data) {
- if (typeof index !== 'number') index = this.indexOf(index)
- if (this[index] !== undefined) return this.splice(index, 1, data)[0]
- },
- mutateFilter: function (fn) {
- var i = this.length
- while (i--) {
- if (!fn(this[i])) this.splice(i, 1)
- }
- return this
- }
- }
- for (var method in extensions) {
- def(ArrayProxy, method, extensions[method], !hasProto)
- }
- /*
- * Watch an object based on type
- */
- function watch (obj, path, observer) {
- var type = typeOf(obj)
- if (type === 'Object') {
- watchObject(obj, path, observer)
- } else if (type === 'Array') {
- watchArray(obj, path, observer)
- }
- }
- /*
- * Watch an Object, recursive.
- */
- function watchObject (obj, path, observer) {
- for (var key in obj) {
- bind(obj, key, path, observer)
- }
- }
- /*
- * Watch an Array, overload mutation methods
- * and add augmentations by intercepting the prototype chain
- */
- function watchArray (arr, path, observer) {
- def(arr, '__observer__', observer)
- observer.path = path
- if (hasProto) {
- arr.__proto__ = ArrayProxy
- } else {
- for (var key in ArrayProxy) {
- def(arr, key, ArrayProxy[key])
- }
- }
- }
- /*
- * Define accessors for a property on an Object
- * so it emits get/set events.
- * Then watch the value itself.
- */
- function bind (obj, key, path, observer) {
- var val = obj[key],
- watchable = isWatchable(val),
- values = observer.values,
- fullKey = (path ? path + '.' : '') + key
- values[fullKey] = val
- // emit set on bind
- // this means when an object is observed it will emit
- // a first batch of set events.
- observer.emit('set', fullKey, val)
- Object.defineProperty(obj, key, {
- enumerable: true,
- get: function () {
- // only emit get on tip values
- if (!watchable) observer.emit('get', fullKey)
- return values[fullKey]
- },
- set: function (newVal) {
- values[fullKey] = newVal
- observer.emit('set', fullKey, newVal)
- watch(newVal, fullKey, observer)
- }
- })
- watch(val, fullKey, observer)
- }
- /*
- * Check if a value is watchable
- */
- function isWatchable (obj) {
- var type = typeOf(obj)
- return type === 'Object' || type === 'Array'
- }
- /*
- * When a value that is already converted is
- * observed again by another observer, we can skip
- * the watch conversion and simply emit set event for
- * all of its properties.
- */
- function emitSet (obj, observer) {
- if (typeOf(obj) === 'Array') {
- observer.emit('set', 'length', obj.length)
- } else {
- var key, val, values = observer.values
- for (key in observer.values) {
- val = values[key]
- observer.emit('set', key, val)
- }
- }
- }
- module.exports = {
- // used in sd-repeat
- watchArray: watchArray,
- /*
- * Observe an object with a given path,
- * and proxy get/set/mutate events to the provided observer.
- */
- observe: function (obj, rawPath, observer) {
- if (isWatchable(obj)) {
- var path = rawPath + '.',
- ob, alreadyConverted = !!obj.__observer__
- if (!alreadyConverted) {
- def(obj, '__observer__', new Emitter())
- }
- ob = obj.__observer__
- ob.values = ob.values || {}
- var proxies = observer.proxies[path] = {
- get: function (key) {
- observer.emit('get', path + key)
- },
- set: function (key, val) {
- observer.emit('set', path + key, val)
- },
- mutate: function (key, val, mutation) {
- // if the Array is a root value
- // the key will be null
- var fixedPath = key ? path + key : rawPath
- observer.emit('mutate', fixedPath, val, mutation)
- // also emit set for Array's length when it mutates
- var m = mutation.method
- if (m !== 'sort' && m !== 'reverse') {
- observer.emit('set', fixedPath + '.length', val.length)
- }
- }
- }
- ob
- .on('get', proxies.get)
- .on('set', proxies.set)
- .on('mutate', proxies.mutate)
- if (alreadyConverted) {
- emitSet(obj, ob, rawPath)
- } else {
- watch(obj, null, ob)
- }
- }
- },
- /*
- * Cancel observation, turn off the listeners.
- */
- unobserve: function (obj, path, observer) {
- if (!obj || !obj.__observer__) return
- path = path + '.'
- var proxies = observer.proxies[path]
- obj.__observer__
- .off('get', proxies.get)
- .off('set', proxies.set)
- .off('mutate', proxies.mutate)
- observer.proxies[path] = null
- }
- }
- });
- require.register("seed/src/directive.js", function(exports, require, module){
- var config = require('./config'),
- utils = require('./utils'),
- directives = require('./directives'),
- filters = require('./filters')
- var KEY_RE = /^[^\|]+/,
- ARG_RE = /([^:]+):(.+)$/,
- FILTERS_RE = /\|[^\|]+/g,
- FILTER_TOKEN_RE = /[^\s']+|'[^']+'/g,
- NESTING_RE = /^\^+/,
- SINGLE_VAR_RE = /^[\w\.\$]+$/
- /*
- * Directive class
- * represents a single directive instance in the DOM
- */
- function Directive (definition, directiveName, expression, rawKey, compiler, node) {
- this.compiler = compiler
- this.vm = compiler.vm
- this.el = node
- // mix in properties from the directive definition
- if (typeof definition === 'function') {
- this._update = definition
- } else {
- for (var prop in definition) {
- if (prop === 'unbind' || prop === 'update') {
- this['_' + prop] = definition[prop]
- } else {
- this[prop] = definition[prop]
- }
- }
- }
- this.name = directiveName
- this.expression = expression.trim()
- this.rawKey = rawKey
-
- parseKey(this, rawKey)
- this.isExp = !SINGLE_VAR_RE.test(this.key)
-
- var filterExps = expression.match(FILTERS_RE)
- if (filterExps) {
- this.filters = []
- var i = 0, l = filterExps.length, filter
- for (; i < l; i++) {
- filter = parseFilter(filterExps[i], this.compiler)
- if (filter) this.filters.push(filter)
- }
- if (!this.filters.length) this.filters = null
- } else {
- this.filters = null
- }
- }
- var DirProto = Directive.prototype
- /*
- * parse a key, extract argument and nesting/root info
- */
- function parseKey (dir, rawKey) {
- var argMatch = rawKey.match(ARG_RE)
- var key = argMatch
- ? argMatch[2].trim()
- : rawKey.trim()
- dir.arg = argMatch
- ? argMatch[1].trim()
- : null
- var nesting = key.match(NESTING_RE)
- dir.nesting = nesting
- ? nesting[0].length
- : false
- dir.root = key.charAt(0) === '$'
- if (dir.nesting) {
- key = key.replace(NESTING_RE, '')
- } else if (dir.root) {
- key = key.slice(1)
- }
- dir.key = key
- }
- /*
- * parse a filter expression
- */
- function parseFilter (filter, compiler) {
- var tokens = filter.slice(1).match(FILTER_TOKEN_RE)
- if (!tokens) return
- tokens = tokens.map(function (token) {
- return token.replace(/'/g, '').trim()
- })
- var name = tokens[0],
- apply = compiler.getOption('filters', name) || filters[name]
- if (!apply) {
- utils.warn('Unknown filter: ' + name)
- return
- }
- return {
- name : name,
- apply : apply,
- args : tokens.length > 1
- ? tokens.slice(1)
- : null
- }
- }
- /*
- * called when a new value is set
- * for computed properties, this will only be called once
- * during initialization.
- */
- DirProto.update = function (value, init) {
- if (!init && value === this.value) return
- this.value = value
- this.apply(value)
- }
- /*
- * -- computed property only --
- * called when a dependency has changed
- */
- DirProto.refresh = function (value) {
- // pass element and viewmodel info to the getter
- // enables context-aware bindings
- if (value) this.value = value
- value = this.value.get({
- el: this.el,
- vm: this.vm
- })
- if (value && value === this.computedValue) return
- this.computedValue = value
- this.apply(value)
- }
- /*
- * Actually invoking the _update from the directive's definition
- */
- DirProto.apply = function (value) {
- this._update(
- this.filters
- ? this.applyFilters(value)
- : value
- )
- }
- /*
- * pipe the value through filters
- */
- DirProto.applyFilters = function (value) {
- var filtered = value, filter
- for (var i = 0, l = this.filters.length; i < l; i++) {
- filter = this.filters[i]
- filtered = filter.apply(filtered, filter.args)
- }
- return filtered
- }
- /*
- * Unbind diretive
- * @ param {Boolean} update
- * Sometimes we call unbind before an update (i.e. not destroy)
- * just to teardown previousstuff, in that case we do not want
- * to null everything.
- */
- DirProto.unbind = function (update) {
- // this can be called before the el is even assigned...
- if (!this.el) return
- if (this._unbind) this._unbind(update)
- if (!update) this.vm = this.el = this.binding = this.compiler = null
- }
- /*
- * make sure the directive and expression is valid
- * before we create an instance
- */
- Directive.parse = function (dirname, expression, compiler, node) {
- var prefix = config.prefix
- if (dirname.indexOf(prefix) === -1) return null
- dirname = dirname.slice(prefix.length + 1)
- var dir = compiler.getOption('directives', dirname) || directives[dirname],
- keyMatch = expression.match(KEY_RE),
- rawKey = keyMatch && keyMatch[0].trim()
- if (!dir) utils.warn('unknown directive: ' + dirname)
- if (!rawKey) utils.warn('invalid directive expression: ' + expression)
- return dir && rawKey
- ? new Directive(dir, dirname, expression, rawKey, compiler, node)
- : null
- }
- module.exports = Directive
- });
- require.register("seed/src/exp-parser.js", function(exports, require, module){
- // Variable extraction scooped from https://github.com/RubyLouvre/avalon
- var KEYWORDS =
- // keywords
- 'break,case,catch,continue,debugger,default,delete,do,else,false'
- + ',finally,for,function,if,in,instanceof,new,null,return,switch,this'
- + ',throw,true,try,typeof,var,void,while,with'
- // reserved
- + ',abstract,boolean,byte,char,class,const,double,enum,export,extends'
- + ',final,float,goto,implements,import,int,interface,long,native'
- + ',package,private,protected,public,short,static,super,synchronized'
- + ',throws,transient,volatile'
- // ECMA 5 - use strict
- + ',arguments,let,yield'
- + ',undefined',
- KEYWORDS_RE = new RegExp(["\\b" + KEYWORDS.replace(/,/g, '\\b|\\b') + "\\b"].join('|'), 'g'),
- REMOVE_RE = /\/\*(?:.|\n)*?\*\/|\/\/[^\n]*\n|\/\/[^\n]*$|'[^']*'|"[^"]*"|[\s\t\n]*\.[\s\t\n]*[$\w\.]+/g,
- SPLIT_RE = /[^\w$]+/g,
- NUMBER_RE = /\b\d[^,]*/g,
- BOUNDARY_RE = /^,+|,+$/g
- function getVariables (code) {
- code = code
- .replace(REMOVE_RE, '')
- .replace(SPLIT_RE, ',')
- .replace(KEYWORDS_RE, '')
- .replace(NUMBER_RE, '')
- .replace(BOUNDARY_RE, '')
- return code
- ? code.split(/,+/)
- : []
- }
- module.exports = {
- /*
- * Parse and create an anonymous computed property getter function
- * from an arbitrary expression.
- */
- parse: function (exp) {
- // extract variable names
- var vars = getVariables(exp)
- if (!vars.length) return null
- var args = [],
- v, i, keyPrefix,
- l = vars.length,
- hash = {}
- for (i = 0; i < l; i++) {
- v = vars[i]
- // avoid duplicate keys
- if (hash[v]) continue
- hash[v] = v
- // push assignment
- keyPrefix = v.charAt(0)
- args.push(v + (
- (keyPrefix === '$' || keyPrefix === '_')
- ? '=this.' + v
- : '=this.$get("' + v + '")'
- ))
- }
- args = 'var ' + args.join(',') + ';return ' + exp
- /* jshint evil: true */
- return {
- getter: new Function(args),
- vars: Object.keys(hash)
- }
- }
- }
- });
- require.register("seed/src/text-parser.js", function(exports, require, module){
- var BINDING_RE = /\{\{(.+?)\}\}/
- module.exports = {
- /*
- * Parse a piece of text, return an array of tokens
- */
- parse: function (text) {
- 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].trim() })
- text = text.slice(i + m[0].length)
- } while (true)
- if (text.length) tokens.push(text)
- return tokens
- }
-
- }
- });
- require.register("seed/src/deps-parser.js", function(exports, require, module){
- var Emitter = require('./emitter'),
- utils = require('./utils'),
- observer = new Emitter()
- /*
- * Auto-extract the dependencies of a computed property
- * by recording the getters triggered when evaluating it.
- */
- function catchDeps (binding) {
- utils.log('\n─ ' + binding.key)
- var depsHash = {}
- observer.on('get', function (dep) {
- if (depsHash[dep.key]) return
- depsHash[dep.key] = 1
- utils.log(' └─ ' + dep.key)
- binding.deps.push(dep)
- dep.subs.push(binding)
- })
- binding.value.get()
- observer.off('get')
- }
- module.exports = {
- /*
- * the observer that catches events triggered by getters
- */
- observer: observer,
- /*
- * parse a list of computed property bindings
- */
- parse: function (bindings) {
- utils.log('\nparsing dependencies...')
- observer.isObserving = true
- bindings.forEach(catchDeps)
- observer.isObserving = false
- utils.log('\ndone.')
- }
-
- }
- });
- 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,
- esc : 27
- }
- module.exports = {
- capitalize: function (value) {
- if (!value && value !== 0) return ''
- value = value.toString()
- return value.charAt(0).toUpperCase() + value.slice(1)
- },
- uppercase: function (value) {
- return (value || value === 0)
- ? value.toString().toUpperCase()
- : ''
- },
- lowercase: function (value) {
- return (value || value === 0)
- ? value.toString().toLowerCase()
- : ''
- },
- /*
- * args: an array of strings corresponding to
- * the single, double, triple ... forms of the word to
- * be pluralized. When the number to be pluralized
- * exceeds the length of the args, it will use the last
- * entry in the array.
- *
- * e.g. ['single', 'double', 'triple', 'multiple']
- */
- pluralize: function (value, args) {
- return args.length > 1
- ? (args[value - 1] || args[args.length - 1])
- : (args[value - 1] || args[0] + 's')
- },
- currency: function (value, args) {
- if (!value && value !== 0) return ''
- var sign = (args && args[0]) || '$',
- s = Math.floor(value).toString(),
- i = s.length % 3,
- h = i > 0 ? (s.slice(0, i) + (s.length > 3 ? ',' : '')) : '',
- f = '.' + value.toFixed(2).slice(-2)
- return sign + h + s.slice(i).replace(/(\d{3})(?=\d)/g, '$1,') + f
- },
- key: function (handler, args) {
- if (!handler) return
- var code = keyCodes[args[0]]
- if (!code) {
- code = parseInt(args[0], 10)
- }
- return function (e) {
- if (e.keyCode === code) {
- handler.call(this, e)
- }
- }
- }
- }
- });
- require.register("seed/src/directives/index.js", function(exports, require, module){
- var utils = require('../utils')
- module.exports = {
- on : require('./on'),
- repeat : require('./repeat'),
- model : require('./model'),
- attr: function (value) {
- this.el.setAttribute(this.arg, value)
- },
- text: function (value) {
- this.el.textContent = utils.toText(value)
- },
- html: function (value) {
- this.el.innerHTML = utils.toText(value)
- },
- style: {
- bind: function () {
- this.arg = convertCSSProperty(this.arg)
- },
- update: function (value) {
- this.el.style[this.arg] = value
- }
- },
- show: function (value) {
- this.el.style.display = value ? '' : 'none'
- },
- visible: function (value) {
- this.el.style.visibility = value ? '' : 'hidden'
- },
- 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
- }
- },
- 'if': {
- bind: function () {
- this.parent = this.el.parentNode
- this.ref = document.createComment('sd-if-' + this.key)
- },
- update: function (value) {
- var attached = !!this.el.parentNode
- if (!this.parent) { // the node was detached when bound
- if (!attached) {
- return
- } else {
- this.parent = this.el.parentNode
- }
- }
- // should always have this.parent if we reach here
- if (!value) {
- if (attached) {
- // insert the reference node
- var next = this.el.nextSibling
- if (next) {
- this.parent.insertBefore(this.ref, next)
- } else {
- this.parent.appendChild(this.ref)
- }
- this.parent.removeChild(this.el)
- }
- } else if (!attached) {
- this.parent.insertBefore(this.el, this.ref)
- this.parent.removeChild(this.ref)
- }
- }
- }
- }
- /*
- * 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/repeat.js", function(exports, require, module){
- var config = require('../config'),
- Observer = require('../observer'),
- Emitter = require('../emitter'),
- ViewModel // lazy def to avoid circular dependency
- /*
- * Mathods that perform precise DOM manipulation
- * based on mutator method triggered
- */
- var mutationHandlers = {
- push: function (m) {
- var i, l = m.args.length,
- base = this.collection.length - l
- for (i = 0; i < l; i++) {
- this.buildItem(m.args[i], base + i)
- }
- },
- pop: function () {
- var vm = this.vms.pop()
- if (vm) vm.$destroy()
- },
- unshift: function (m) {
- var i, l = m.args.length
- for (i = 0; i < l; i++) {
- this.buildItem(m.args[i], i)
- }
- },
- shift: function () {
- var vm = this.vms.shift()
- if (vm) vm.$destroy()
- },
- splice: function (m) {
- var i, l,
- index = m.args[0],
- removed = m.args[1],
- added = m.args.length - 2,
- removedVMs = this.vms.splice(index, removed)
- for (i = 0, l = removedVMs.length; i < l; i++) {
- removedVMs[i].$destroy()
- }
- for (i = 0; i < added; i++) {
- this.buildItem(m.args[i + 2], index + i)
- }
- },
- sort: function () {
- var key = this.arg,
- vms = this.vms,
- col = this.collection,
- l = col.length,
- sorted = new Array(l),
- i, j, vm, data
- for (i = 0; i < l; i++) {
- data = col[i]
- for (j = 0; j < l; j++) {
- vm = vms[j]
- if (vm[key] === data) {
- sorted[i] = vm
- break
- }
- }
- }
- for (i = 0; i < l; i++) {
- this.container.insertBefore(sorted[i].$el, this.ref)
- }
- this.vms = sorted
- },
- reverse: function () {
- var vms = this.vms
- vms.reverse()
- for (var i = 0, l = vms.length; i < l; i++) {
- this.container.insertBefore(vms[i].$el, this.ref)
- }
- }
- }
- module.exports = {
- bind: function () {
- this.el.removeAttribute(config.prefix + '-repeat')
- var ctn = this.container = this.el.parentNode
- // create a comment node as a reference node for DOM insertions
- this.ref = document.createComment('sd-repeat-' + this.arg)
- ctn.insertBefore(this.ref, this.el)
- ctn.removeChild(this.el)
- this.collection = null
- this.vms = null
- var self = this
- this.mutationListener = function (path, arr, mutation) {
- self.detach()
- var method = mutation.method
- mutationHandlers[method].call(self, mutation)
- if (method !== 'push' && method !== 'pop') {
- self.updateIndexes()
- }
- self.retach()
- }
- },
- update: function (collection) {
- this.unbind(true)
- // attach an object to container to hold handlers
- this.container.sd_dHandlers = {}
- // if initiating with an empty collection, we need to
- // force a compile so that we get all the bindings for
- // dependency extraction.
- if (!this.collection && !collection.length) {
- this.buildItem()
- }
- this.collection = collection
- this.vms = []
- // listen for collection mutation events
- // the collection has been augmented during Binding.set()
- if (!collection.__observer__) Observer.watchArray(collection, null, new Emitter())
- collection.__observer__.on('mutate', this.mutationListener)
- // create child-seeds and append to DOM
- this.detach()
- for (var i = 0, l = collection.length; i < l; i++) {
- this.buildItem(collection[i], i)
- }
- this.retach()
- },
- /*
- * Create a new child VM from a data object
- * passing along compiler options indicating this
- * is a sd-repeat item.
- */
- buildItem: function (data, index) {
- ViewModel = ViewModel || require('../viewmodel')
- var node = this.el.cloneNode(true),
- ctn = this.container,
- vmID = node.getAttribute(config.prefix + '-viewmodel'),
- ChildVM = this.compiler.getOption('vms', vmID) || ViewModel,
- scope = {}
- scope[this.arg] = data || {}
- var item = new ChildVM({
- el: node,
- scope: scope,
- compilerOptions: {
- repeat: true,
- repeatIndex: index,
- repeatPrefix: this.arg,
- parentCompiler: this.compiler,
- delegator: ctn
- }
- })
- if (!data) {
- item.$destroy()
- } else {
- var ref = this.vms.length > index
- ? this.vms[index].$el
- : this.ref
- ctn.insertBefore(node, ref)
- this.vms.splice(index, 0, item)
- }
- },
- /*
- * Update index of each item after a mutation
- */
- updateIndexes: function () {
- var i = this.vms.length
- while (i--) {
- this.vms[i][this.arg].$index = i
- }
- },
- /*
- * Detach/ the container from the DOM before mutation
- * so that batch DOM updates are done in-memory and faster
- */
- detach: function () {
- var c = this.container,
- p = this.parent = c.parentNode
- this.next = c.nextSibling
- if (p) p.removeChild(c)
- },
- retach: function () {
- var n = this.next,
- p = this.parent,
- c = this.container
- if (!p) return
- if (n) {
- p.insertBefore(c, n)
- } else {
- p.appendChild(c)
- }
- },
- unbind: function () {
- if (this.collection) {
- this.collection.__observer__.off('mutate', this.mutationListener)
- var i = this.vms.length
- while (i--) {
- this.vms[i].$destroy()
- }
- }
- var ctn = this.container,
- handlers = ctn.sd_dHandlers
- for (var key in handlers) {
- ctn.removeEventListener(handlers[key].event, handlers[key])
- }
- ctn.sd_dHandlers = null
- }
- }
- });
- require.register("seed/src/directives/on.js", function(exports, require, module){
- var utils = require('../utils')
- 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 = {
- bind: function () {
- if (this.compiler.repeat) {
- // attach an identifier to the el
- // so it can be matched during event delegation
- this.el[this.expression] = true
- // attach the owner viewmodel of this directive
- this.el.sd_viewmodel = this.vm
- }
- },
- update: function (handler) {
- this.unbind(true)
- if (typeof handler !== 'function') {
- return utils.warn('Directive "on" expects a function value.')
- }
- var compiler = this.compiler,
- event = this.arg,
- ownerVM = this.binding.compiler.vm
- if (compiler.repeat && event !== 'blur' && event !== 'focus') {
- // for each blocks, delegate for better performance
- // focus and blur events dont bubble so exclude them
- var delegator = compiler.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) {
- e.el = target
- e.vm = target.sd_viewmodel
- e.item = e.vm[compiler.repeatPrefix]
- handler.call(ownerVM, e)
- }
- }
- dHandler.event = event
- delegator.addEventListener(event, dHandler)
- } else {
- // a normal, single element handler
- var vm = this.vm
- this.handler = function (e) {
- e.el = e.currentTarget
- e.vm = vm
- if (compiler.repeat) {
- e.item = vm[compiler.repeatPrefix]
- }
- handler.call(ownerVM, e)
- }
- this.el.addEventListener(event, this.handler)
- }
- },
- unbind: function (update) {
- this.el.removeEventListener(this.arg, this.handler)
- this.handler = null
- if (!update) this.el.sd_viewmodel = null
- }
- }
- });
- require.register("seed/src/directives/model.js", function(exports, require, module){
- var utils = require('../utils')
- module.exports = {
- bind: function () {
- var self = this,
- el = self.el,
- type = el.type
- self.lock = false
- // determine what event to listen to
- self.event =
- (self.compiler.options.lazy ||
- el.tagName === 'SELECT' ||
- type === 'checkbox' ||
- type === 'radio')
- ? 'change'
- : 'keyup'
- // determin the attribute to change when updating
- var attr = type === 'checkbox'
- ? 'checked'
- : 'value'
- // attach listener
- self.set = function () {
- self.lock = true
- self.vm.$set(self.key, el[attr])
- self.lock = false
- }
- el.addEventListener(self.event, self.set)
- },
- update: function (value) {
- /* jshint eqeqeq: false */
- var self = this,
- el = self.el
- if (self.lock) return
- if (el.tagName === 'SELECT') { // select dropdown
- // setting <select>'s value in IE9 doesn't work
- var o = el.options,
- i = o.length,
- index = -1
- while (i--) {
- if (o[i].value == value) {
- index = i
- break
- }
- }
- o.selectedIndex = index
- } else if (el.type === 'radio') { // radio button
- el.checked = value == el.value
- } else if (el.type === 'checkbox') { // checkbox
- el.checked = !!value
- } else {
- el.value = utils.toText(value)
- }
- },
- unbind: function () {
- this.el.removeEventListener(this.event, this.set)
- }
- }
- });
- 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");if (typeof exports == "object") {
- module.exports = require("seed");
- } else if (typeof define == "function" && define.amd) {
- define(function(){ return require("seed"); });
- } else {
- this["Seed"] = require("seed");
- }})();
|