|
@@ -1,5 +1,5 @@
|
|
|
var prefix = 'sd',
|
|
var prefix = 'sd',
|
|
|
- Filters = require('./filters'),
|
|
|
|
|
|
|
+ Directive = require('./directive'),
|
|
|
Directives = require('./directives'),
|
|
Directives = require('./directives'),
|
|
|
selector = Object.keys(Directives).map(function (d) {
|
|
selector = Object.keys(Directives).map(function (d) {
|
|
|
return '[' + prefix + '-' + d + ']'
|
|
return '[' + prefix + '-' + d + ']'
|
|
@@ -11,163 +11,111 @@ function Seed (opts) {
|
|
|
root = this.el = document.getElementById(opts.id),
|
|
root = this.el = document.getElementById(opts.id),
|
|
|
els = root.querySelectorAll(selector)
|
|
els = root.querySelectorAll(selector)
|
|
|
|
|
|
|
|
- var bindings = self._bindings = {} // internal real data
|
|
|
|
|
- self.scope = {} // external interface
|
|
|
|
|
|
|
+ self.bindings = {}
|
|
|
|
|
+ self.scope = {}
|
|
|
|
|
|
|
|
// process nodes for directives
|
|
// process nodes for directives
|
|
|
- ;[].forEach.call(els, processNode)
|
|
|
|
|
- processNode(root)
|
|
|
|
|
|
|
+ ;[].forEach.call(els, this.compileNode.bind(this))
|
|
|
|
|
+ this.compileNode(root)
|
|
|
|
|
|
|
|
// initialize all variables by invoking setters
|
|
// initialize all variables by invoking setters
|
|
|
- for (var key in bindings) {
|
|
|
|
|
|
|
+ for (var key in self.bindings) {
|
|
|
self.scope[key] = opts.scope[key]
|
|
self.scope[key] = opts.scope[key]
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- function processNode (el) {
|
|
|
|
|
- cloneAttributes(el.attributes).forEach(function (attr) {
|
|
|
|
|
- var directive = parseDirective(attr)
|
|
|
|
|
- if (directive) {
|
|
|
|
|
- bindDirective(self, el, bindings, directive)
|
|
|
|
|
- }
|
|
|
|
|
- })
|
|
|
|
|
- }
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-Seed.prototype.dump = function () {
|
|
|
|
|
- var data = {}
|
|
|
|
|
- for (var key in this._bindings) {
|
|
|
|
|
- data[key] = this._bindings[key].value
|
|
|
|
|
- }
|
|
|
|
|
- return data
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-Seed.prototype.destroy = function () {
|
|
|
|
|
- for (var key in this._bindings) {
|
|
|
|
|
- this._bindings[key].directives.forEach(function (directive) {
|
|
|
|
|
- if (directive.definition.unbind) {
|
|
|
|
|
- directive.definition.unbind(
|
|
|
|
|
- directive.el,
|
|
|
|
|
- directive.argument,
|
|
|
|
|
- directive
|
|
|
|
|
- )
|
|
|
|
|
- }
|
|
|
|
|
- })
|
|
|
|
|
- }
|
|
|
|
|
- this.el.parentNode.remove(this.el)
|
|
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-// clone attributes so they don't change
|
|
|
|
|
-function cloneAttributes (attributes) {
|
|
|
|
|
- return [].map.call(attributes, function (attr) {
|
|
|
|
|
- return {
|
|
|
|
|
- name: attr.name,
|
|
|
|
|
- value: attr.value
|
|
|
|
|
|
|
+Seed.prototype.compileNode = function (node) {
|
|
|
|
|
+ var self = this
|
|
|
|
|
+ cloneAttributes(node.attributes).forEach(function (attr) {
|
|
|
|
|
+ var directive = Directive.parse(attr, prefix)
|
|
|
|
|
+ if (directive) {
|
|
|
|
|
+ self.bind(node, directive)
|
|
|
}
|
|
}
|
|
|
})
|
|
})
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-function bindDirective (seed, el, bindings, directive) {
|
|
|
|
|
- directive.el = el
|
|
|
|
|
- el.removeAttribute(directive.attr.name)
|
|
|
|
|
- var key = directive.key,
|
|
|
|
|
- binding = bindings[key]
|
|
|
|
|
- if (!binding) {
|
|
|
|
|
- bindings[key] = binding = {
|
|
|
|
|
- value: undefined,
|
|
|
|
|
- directives: []
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
|
|
+Seed.prototype.bind = function (node, directive) {
|
|
|
|
|
+
|
|
|
|
|
+ directive.el = node
|
|
|
|
|
+ node.removeAttribute(directive.attr.name)
|
|
|
|
|
+
|
|
|
|
|
+ var key = directive.key,
|
|
|
|
|
+ binding = this.bindings[key] || this.createBinding(key)
|
|
|
|
|
+
|
|
|
|
|
+ // add directive to this binding
|
|
|
binding.directives.push(directive)
|
|
binding.directives.push(directive)
|
|
|
|
|
+
|
|
|
// invoke bind hook if exists
|
|
// invoke bind hook if exists
|
|
|
if (directive.bind) {
|
|
if (directive.bind) {
|
|
|
- directive.bind(el, binding.value)
|
|
|
|
|
- }
|
|
|
|
|
- if (!seed.scope.hasOwnProperty(key)) {
|
|
|
|
|
- bindAccessors(seed, key, binding)
|
|
|
|
|
|
|
+ directive.bind(node, binding.value)
|
|
|
}
|
|
}
|
|
|
|
|
+
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-function bindAccessors (seed, key, binding) {
|
|
|
|
|
- Object.defineProperty(seed.scope, key, {
|
|
|
|
|
|
|
+Seed.prototype.createBinding = function (key) {
|
|
|
|
|
+
|
|
|
|
|
+ var binding = {
|
|
|
|
|
+ value: undefined,
|
|
|
|
|
+ directives: []
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ this.bindings[key] = binding
|
|
|
|
|
+
|
|
|
|
|
+ // bind accessor triggers to scope
|
|
|
|
|
+ Object.defineProperty(this.scope, key, {
|
|
|
get: function () {
|
|
get: function () {
|
|
|
return binding.value
|
|
return binding.value
|
|
|
},
|
|
},
|
|
|
set: function (value) {
|
|
set: function (value) {
|
|
|
binding.value = value
|
|
binding.value = value
|
|
|
binding.directives.forEach(function (directive) {
|
|
binding.directives.forEach(function (directive) {
|
|
|
- var filteredValue = value && directive.filters
|
|
|
|
|
- ? applyFilters(value, directive)
|
|
|
|
|
- : value
|
|
|
|
|
- directive.update(
|
|
|
|
|
- directive.el,
|
|
|
|
|
- filteredValue,
|
|
|
|
|
- directive.argument,
|
|
|
|
|
- directive,
|
|
|
|
|
- seed
|
|
|
|
|
- )
|
|
|
|
|
|
|
+ directive.update(value)
|
|
|
})
|
|
})
|
|
|
}
|
|
}
|
|
|
})
|
|
})
|
|
|
|
|
+
|
|
|
|
|
+ return binding
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-function parseDirective (attr) {
|
|
|
|
|
-
|
|
|
|
|
- if (attr.name.indexOf(prefix) === -1) return
|
|
|
|
|
-
|
|
|
|
|
- // parse directive name and argument
|
|
|
|
|
- var noprefix = attr.name.slice(prefix.length + 1),
|
|
|
|
|
- argIndex = noprefix.indexOf('-'),
|
|
|
|
|
- dirname = argIndex === -1
|
|
|
|
|
- ? noprefix
|
|
|
|
|
- : noprefix.slice(0, argIndex),
|
|
|
|
|
- def = Directives[dirname],
|
|
|
|
|
- arg = argIndex === -1
|
|
|
|
|
- ? null
|
|
|
|
|
- : noprefix.slice(argIndex + 1)
|
|
|
|
|
-
|
|
|
|
|
- // parse scope variable key and pipe filters
|
|
|
|
|
- var exp = attr.value,
|
|
|
|
|
- pipeIndex = exp.indexOf('|'),
|
|
|
|
|
- key = pipeIndex === -1
|
|
|
|
|
- ? exp.trim()
|
|
|
|
|
- : exp.slice(0, pipeIndex).trim(),
|
|
|
|
|
- filters = pipeIndex === -1
|
|
|
|
|
- ? null
|
|
|
|
|
- : exp.slice(pipeIndex + 1).split('|').map(function (filter) {
|
|
|
|
|
- return filter.trim()
|
|
|
|
|
- })
|
|
|
|
|
|
|
+Seed.prototype.dump = function () {
|
|
|
|
|
+ var data = {}
|
|
|
|
|
+ for (var key in this._bindings) {
|
|
|
|
|
+ data[key] = this._bindings[key].value
|
|
|
|
|
+ }
|
|
|
|
|
+ return data
|
|
|
|
|
+}
|
|
|
|
|
|
|
|
- return def
|
|
|
|
|
- ? {
|
|
|
|
|
- attr: attr,
|
|
|
|
|
- key: key,
|
|
|
|
|
- filters: filters,
|
|
|
|
|
- definition: def,
|
|
|
|
|
- argument: arg,
|
|
|
|
|
- update: typeof def === 'function'
|
|
|
|
|
- ? def
|
|
|
|
|
- : def.update
|
|
|
|
|
|
|
+Seed.prototype.destroy = function () {
|
|
|
|
|
+ for (var key in this._bindings) {
|
|
|
|
|
+ this._bindings[key].directives.forEach(unbind)
|
|
|
|
|
+ }
|
|
|
|
|
+ this.el.parentNode.remove(this.el)
|
|
|
|
|
+ function unbind (directive) {
|
|
|
|
|
+ if (directive.unbind) {
|
|
|
|
|
+ directive.unbind()
|
|
|
}
|
|
}
|
|
|
- : null
|
|
|
|
|
|
|
+ }
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-function applyFilters (value, directive) {
|
|
|
|
|
- if (directive.definition.customFilter) {
|
|
|
|
|
- return directive.definition.customFilter(value, directive.filters)
|
|
|
|
|
- } else {
|
|
|
|
|
- directive.filters.forEach(function (filter) {
|
|
|
|
|
- if (Filters[filter]) {
|
|
|
|
|
- value = Filters[filter](value)
|
|
|
|
|
- }
|
|
|
|
|
- })
|
|
|
|
|
- return value
|
|
|
|
|
- }
|
|
|
|
|
|
|
+// clone attributes so they don't change
|
|
|
|
|
+function cloneAttributes (attributes) {
|
|
|
|
|
+ return [].map.call(attributes, function (attr) {
|
|
|
|
|
+ return {
|
|
|
|
|
+ name: attr.name,
|
|
|
|
|
+ value: attr.value
|
|
|
|
|
+ }
|
|
|
|
|
+ })
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
module.exports = {
|
|
module.exports = {
|
|
|
create: function (opts) {
|
|
create: function (opts) {
|
|
|
return new Seed(opts)
|
|
return new Seed(opts)
|
|
|
},
|
|
},
|
|
|
- filters: Filters,
|
|
|
|
|
- directives: Directives
|
|
|
|
|
|
|
+ directive: function () {
|
|
|
|
|
+ // create dir
|
|
|
|
|
+ },
|
|
|
|
|
+ filter: function () {
|
|
|
|
|
+ // create filter
|
|
|
|
|
+ }
|
|
|
}
|
|
}
|