define(['jquery','underscore','./loader'],function($,_,loader){'use strict';var colonReg=/\\:/g,renderedTemplatePromises={},attributes={},elements={},globals=[],renderer,preset;renderer={render:function(tmplPath){var cachedPromise=renderedTemplatePromises[tmplPath];if(!cachedPromise){cachedPromise=renderedTemplatePromises[tmplPath]=loader.loadTemplate(tmplPath).then(renderer.parseTemplate);} return cachedPromise;},getRendered:function(tmplPath){return renderer.render(tmplPath);},parseTemplate:function(html){var fragment=document.createDocumentFragment();$(fragment).append(html);return renderer.normalize(fragment);},normalize:function(content){globals.forEach(function(handler){handler(content);});return _.toArray(content.childNodes);},addGlobal:function(handler){if(!_.contains(globals,handler)){globals.push(handler);} return this;},removeGlobal:function(handler){var index=globals.indexOf(handler);if(~index){globals.splice(index,1);} return this;},addAttribute:function(id,config){var data={name:id,binding:id,handler:renderer.handlers.attribute};if(_.isFunction(config)){data.handler=config;}else if(_.isObject(config)){_.extend(data,config);} data.id=id;attributes[id]=data;return this;},removeAttribute:function(id){delete attributes[id];return this;},addNode:function(id,config){var data={name:id,binding:id,handler:renderer.handlers.node};if(_.isFunction(config)){data.handler=config;}else if(_.isObject(config)){_.extend(data,config);} data.id=id;elements[id]=data;return this;},removeNode:function(id){delete elements[id];return this;},isCustomNode:function(node){return _.some(elements,function(elem){return elem.name.toUpperCase()===node.tagName;});},processAttributes:function(content){var repeat;repeat=_.some(attributes,function(attr){var attrName=attr.name,nodes=content.querySelectorAll('['+attrName+']'),handler=attr.handler;return _.toArray(nodes).some(function(node){var data=node.getAttribute(attrName);return handler(node,data,attr)===true;});});if(repeat){renderer.processAttributes(content);}},processNodes:function(content){var repeat;repeat=_.some(elements,function(element){var nodes=content.querySelectorAll(element.name),handler=element.handler;return _.toArray(nodes).some(function(node){var data=node.getAttribute('args');return handler(node,data,element)===true;});});if(repeat){renderer.processNodes(content);}},wrapArgs:function(args){if(~args.indexOf('\\:')){args=args.replace(colonReg,':');}else if(~args.indexOf(':')&&!~args.indexOf('}')){args='{'+args+'}';} return args;},wrapChildren:function(node,binding,data){var tag=this.createComment(binding,data),$node=$(node);$node.prepend(tag.open);$node.append(tag.close);},wrapNode:function(node,binding,data){var tag=this.createComment(binding,data),$node=$(node);$node.before(tag.open);$node.after(tag.close);},createComment:function(binding,data){return{open:document.createComment(' ko '+binding+': '+data+' '),close:document.createComment(' /ko ')};}};renderer.handlers={node:function(node,data,element){data=renderer.wrapArgs(data);renderer.wrapNode(node,element.binding,data);$(node).replaceWith(node.childNodes);return true;},attribute:function(node,data,attr){data=renderer.wrapArgs(data);renderer.bindings.add(node,attr.binding,data);node.removeAttribute(attr.name);},wrapAttribute:function(node,data,attr){data=renderer.wrapArgs(data);renderer.wrapNode(node,attr.binding,data);node.removeAttribute(attr.name);}};renderer.bindings={add:function(node,name,data){var bindings=this.get(node);if(bindings){bindings+=', ';} bindings+=name;if(data){bindings+=': '+data;} this.set(node,bindings);},get:function(node){return node.getAttribute('data-bind')||'';},set:function(node,bindings){node.setAttribute('data-bind',bindings);}};renderer.addGlobal(renderer.processAttributes).addGlobal(renderer.processNodes);preset={nodes:_.object(['if','text','with','scope','ifnot','foreach','component'],Array.prototype),attributes:_.object(['css','attr','html','with','text','click','event','submit','enable','disable','options','visible','template','hasFocus','textInput','component','uniqueName','optionsText','optionsValue','checkedValue','selectedOptions'],Array.prototype)};_.extend(preset.attributes,{if:renderer.handlers.wrapAttribute,ifnot:renderer.handlers.wrapAttribute,innerif:{binding:'if'},innerifnot:{binding:'ifnot'},outereach:{binding:'foreach',handler:renderer.handlers.wrapAttribute},foreach:{name:'each'},value:{name:'ko-value'},style:{name:'ko-style'},checked:{name:'ko-checked'},disabled:{name:'ko-disabled',binding:'disable'},focused:{name:'ko-focused',binding:'hasFocus'},render:function(node,data){data=data||'getTemplate()';data=renderer.wrapArgs(data);renderer.wrapChildren(node,'template',data);node.removeAttribute('render');}});_.extend(preset.nodes,{foreach:{name:'each'},render:function(node,data){data=data||'getTemplate()';data=renderer.wrapArgs(data);renderer.wrapNode(node,'template',data);$(node).replaceWith(node.childNodes);}});_.each(preset.attributes,function(data,id){renderer.addAttribute(id,data);});_.each(preset.nodes,function(data,id){renderer.addNode(id,data);});return renderer;});