UNPKG

driven

Version:

Model Driven Things

124 lines (100 loc) 3.08 kB
/* jshint node: true */ /* global window: false */ 'use strict'; 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]); } } };