diff options
Diffstat (limited to 'src/Compiler.js')
| -rw-r--r-- | src/Compiler.js | 259 |
1 files changed, 41 insertions, 218 deletions
diff --git a/src/Compiler.js b/src/Compiler.js index ca94c893..ba598a43 100644 --- a/src/Compiler.js +++ b/src/Compiler.js @@ -48,224 +48,41 @@ Template.prototype = { }; /////////////////////////////////// -//JQLite +//Compiler ////////////////////////////////// - -var jqCache = {}; -var jqName = 'ng-' + new Date().getTime(); -var jqId = 1; -function jqNextId() { return jqId++; } - -var addEventListener = window.document.attachEvent ? - function(element, type, fn) { - element.attachEvent('on' + type, fn); - } : function(element, type, fn) { - element.addEventListener(type, fn, false); - }; - -var removeEventListener = window.document.detachEvent ? - function(element, type, fn) { - element.detachEvent('on' + type, fn); - } : function(element, type, fn) { - element.removeEventListener(type, fn, false); - }; - -function jqClearData(element) { - var cacheId = element[jqName], - cache = jqCache[cacheId]; - if (cache) { - foreach(cache.bind || {}, function(fn, type){ - removeEventListener(element, type, fn); - }); - delete jqCache[cacheId]; - delete element[jqName]; - } -}; - -function JQLite(element) { - this[0] = element; +function isTextNode(node) { + return node.nodeType == Node.TEXT_NODE; } -function jqLite(element) { - if (typeof element == 'string') { - var div = document.createElement('div'); - div.innerHTML = element; - element = div.childNodes[0]; +function eachTextNode(element, fn){ + var i, chldNodes = element[0].childNodes || [], size = chldNodes.length, chld; + for (i = 0; i < size; i++) { + if(isTextNode(chld = chldNodes[i])) { + fn(jqLite(chld), i); + } } - return element instanceof JQLite ? element : new JQLite(element); } -JQLite.prototype = { - data: function(key, value) { - var element = this[0], - cacheId = element[jqName], - cache = jqCache[cacheId || -1]; - if (isDefined(value)) { - if (!cache) { - element[jqName] = cacheId = jqNextId(); - cache = jqCache[cacheId] = {}; - } - cache[key] = value; - } else { - return cache ? cache[key] : null; +function eachNode(element, fn){ + var i, chldNodes = element[0].childNodes || [], size = chldNodes.length, chld; + for (i = 0; i < size; i++) { + if(!isTextNode(chld = chldNodes[i])) { + fn(jqLite(chld), i); } - }, - - removeData: function(){ - jqClearData(this[0]); - }, - - dealoc: function(){ - (function dealoc(element){ - jqClearData(element); - for ( var i = 0, children = element.childNodes; i < children.length; i++) { - dealoc(children[0]); - } - })(this[0]); - }, - - bind: function(type, fn){ - var element = this[0], - bind = this.data('bind'), - eventHandler; - if (!bind) this.data('bind', bind = {}); - eventHandler = bind[type]; - if (!eventHandler) { - bind[type] = eventHandler = function() { - var self = this; - foreach(eventHandler.fns, function(fn){ - fn.apply(self, arguments); - }); - }; - eventHandler.fns = []; - addEventListener(element, type, eventHandler); - } - eventHandler.fns.push(fn); - }, - - trigger: function(type) { - var cache = this.data('bind'); - if (cache) { - (cache[type] || noop)(); - } - }, - - click: function(fn) { - if (fn) - this.bind('click', fn); - else - this.trigger('click'); - }, - - eachTextNode: function(fn){ - var i, chldNodes = this[0].childNodes || [], size = chldNodes.length, chld; - for (i = 0; i < size; i++) { - if((chld = new JQLite(chldNodes[i])).isText()) { - fn(chld, i); - } - } - }, - - - eachNode: function(fn){ - var i, chldNodes = this[0].childNodes || [], size = chldNodes.length, chld; - for (i = 0; i < size; i++) { - if(!(chld = new JQLite(chldNodes[i])).isText()) { - fn(chld, i); - } - } - }, - - eachAttribute: function(fn){ - var i, attrs = this[0].attributes || [], size = attrs.length, chld, attr; - for (i = 0; i < size; i++) { - var attr = attrs[i]; - fn(attr.name, attr.value); - } - }, - - replaceWith: function(replaceNode) { - this[0].parentNode.replaceChild(jqLite(replaceNode)[0], this[0]); - }, - - remove: function() { - this.dealoc(); - this[0].parentNode.removeChild(this[0]); - }, - - removeAttr: function(name) { - this[0].removeAttribute(name); - }, - - after: function(element) { - this[0].parentNode.insertBefore(jqLite(element)[0], this[0].nextSibling); - }, - - hasClass: function(selector) { - var className = " " + selector + " "; - if ( (" " + this[0].className + " ").replace(/[\n\t]/g, " ").indexOf( className ) > -1 ) { - return true; - } - return false; - }, - - addClass: function( selector ) { - if (!this.hasClass(selector)) { - this[0].className += ' ' + selector; - } - }, - - css: function(name, value) { - var style = this[0].style; - if (isString(name)) { - if (isDefined(value)) { - style[name] = value; - } else { - return style[name]; - } - } else { - extend(style, name); - } - }, - - attr: function(name, value){ - var e = this[0]; - if (isObject(name)) { - foreach(name, function(value, name){ - e.setAttribute(name, value); - }); - } else if (isDefined(value)) { - e.setAttribute(name, value); - } else { - return e.getAttribute(name); - } - }, - - text: function(value) { - if (isDefined(value)) { - this[0].textContent = value; - } - return this[0].textContent; - }, - - html: function(value) { - if (isDefined(value)) { - this[0].innerHTML = value; - } - return this[0].innerHTML; - }, - - parent: function() { return jqLite(this[0].parentNode);}, - isText: function() { return this[0].nodeType == Node.TEXT_NODE; }, - clone: function() { return jqLite(this[0].cloneNode(true)); } -}; + } +} -/////////////////////////////////// -//Compiler -////////////////////////////////// +function eachAttribute(element, fn){ + var i, attrs = element[0].attributes || [], size = attrs.length, chld, attr; + for (i = 0; i < size; i++) { + var attr = attrs[i]; + fn(attr.name, attr.value); + } +} -function Compiler(markup, directives, widgets){ - this.markup = markup; +function Compiler(textMarkup, attrMarkup, directives, widgets){ + this.textMarkup = textMarkup; + this.attrMarkup = attrMarkup; this.directives = directives; this.widgets = widgets; } @@ -291,8 +108,6 @@ Compiler.prototype = { elementName = element[0].nodeName, widgets = self.widgets, widget = widgets[elementName], - markup = self.markup, - markupSize = markup.length, directives = self.directives, descend = true, exclusive = false, @@ -300,7 +115,9 @@ Compiler.prototype = { template = new Template(), selfApi = { compile: bind(self, self.compile), - reference:function(name) {return jqLite(document.createComment(name));}, + comment:function(text) {return jqLite(document.createComment(text));}, + element:function(type) {return jqLite(document.createElement(type));}, + text:function(text) {return jqLite(document.createTextNode(text));}, descend: function(value){ if(isDefined(value)) descend = value; return descend;} }; @@ -308,14 +125,20 @@ Compiler.prototype = { template.addInit(widget.call(selfApi, element)); } else { // process markup for text nodes only - element.eachTextNode(function(textNode){ - for (var i = 0, text = textNode.text(); i < markupSize; i++) { - markup[i].call(selfApi, text, textNode, element); - } + eachTextNode(element, function(textNode){ + var text = textNode.text(); + foreach(self.textMarkup, function(markup){ + markup.call(selfApi, text, textNode, element); + }); }); // Process attributes/directives - element.eachAttribute(function(name, value){ + eachAttribute(element, function(name, value){ + foreach(self.attrMarkup, function(markup){ + markup.call(selfApi, value, name, element); + }); + }); + eachAttribute(element, function(name, value){ var directive = directives[name]; if (!exclusive && directive) { if (directive.exclusive) { @@ -333,7 +156,7 @@ Compiler.prototype = { // Process non text child nodes if (descend) { - element.eachNode(function(child, i){ + eachNode(element, function(child, i){ template.addChild(i, self.templatize(child)); }); } |
