driven
Version:
Model Driven Things
124 lines (100 loc) • 3.08 kB
JavaScript
/* jshint node: true */
/* global window: false */
;
var paths = require('gedi-paths');
var scope = require('../scope');
var tagMappings = {
div: 'container',
ul: 'container'
};
// require all the supported element types
// without these requires, the browserification process will not work
require('./container');
require('./element');
require('./input');
function HtmlDriver(data, opts) {
var autoAttach;
var driver = this;
if (! (this instanceof HtmlDriver)) {
return new HtmlDriver(data, opts);
}
// attach to the driver
this.data = data;
// TODO: check data valid (looks and smells like Gedi)
// auto attach (if not specified otherwise)
autoAttach = (opts || {}).autoAttach;
if (typeof autoAttach == 'undefined' || autoAttach) {
window.addEventListener('load', function() {
driver.attach(
(opts || {}).target || document.body,
(opts || {}).basePath
);
});
}
}
module.exports = HtmlDriver;
HtmlDriver.prototype.attach = function(target, basePath) {
var elementPath;
var binding;
var handlerType;
var handler;
var ii = 0;
var count;
var path;
var data = this.data;
var checkChildNodes = true;
// if the node is text, or a comment abort
if ((target instanceof Text) || (target instanceof Comment)) return;
// if the target is already bound, then abort
if (target._activeBinding) return;
// initialise the basepath if not already provided
basePath = paths.create(basePath);
// check to see if we have a path on the element
binding = target.getAttribute('data-binding');
count = target.childNodes.length;
// path relative to the current element
path = paths.append(
basePath,
target.getAttribute('data-scope') || target.getAttribute('data-path') || ''
);
// bind if we have a binding
if (binding) {
// get the handler type
handlerType = target.tagName.toLowerCase();
// check if we should use another handler for the current tag
handlerType = tagMappings[handlerType] || handlerType;
try {
handler = require('./' + handlerType);
}
catch (e) {
handler = require('./element');
}
// run the handler
checkChildNodes = handler.call(this, target, data, binding, path);
// flag as bound
target._activeBinding = binding; // path.append(binding);
}
// iterate through the child nodes of the element
for (; (checkChildNodes || typeof checkChildNodes == 'undefined') && ii < count; ii++) {
if (target.childNodes[ii]) {
this.attach(target.childNodes[ii], path);
}
}
};
/**
#### remove(target)
Debind listening on the node
**/
HtmlDriver.prototype.remove = function(target) {
// TODO: needs to be more specific
if (target._activeBinding) {
this.data.debind(target._activeBinding);
}
if (! target.childNodes) return;
// iterate through the child nodes
for (var ii = target.childNodes.length; ii--; ) {
if (target.childNodes[ii] && (! (target.childNodes[ii] instanceof Text))) {
this.remove(target.childNodes[ii]);
}
}
};