From 8b487551cacc04b185baa670ec0afb7b02c24d7e Mon Sep 17 00:00:00 2001 From: StefansArya Date: Sun, 18 Nov 2018 15:50:23 +0700 Subject: [PATCH] Update to version 0.8.1 --- dist/scarletsframe.min.js | 2 +- dist/scarletsframe.min.js.map | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/dist/scarletsframe.min.js b/dist/scarletsframe.min.js index e638a66..17f9d18 100644 --- a/dist/scarletsframe.min.js +++ b/dist/scarletsframe.min.js @@ -6,5 +6,5 @@ https://github.com/ScarletsFiction/ScarletsFrame */ -sf=function(e){function t(){return e.apply(this,arguments)}return t.toString=function(){return e.toString()},t}(function(){if(arguments[0].constructor===Function)return sf.loader.onFinish.apply(null,arguments)}),sf.regex={avoidQuotes:"(?=(?:[^\"']*(?:'|\")[^\"']*(?:'|\"))*[^\"']*$)",strictVar:"(?=\\b[^.]|^|\\n| +|\\t|\\W )"},"undefined"!=typeof $&&$.fn||setTimeout(function(){console.clear(),console.error("Please load jQuery before ScarletsFrame")},1e3),$.fn.extend||($.fn.extend=function(e){for(var t in e)$.fn[t]=e[t]}),$.fn.extend({animateCSS:function(e,t,r){var n=this,o={animation:"animationend",OAnimation:"oAnimationEnd",MozAnimation:"mozAnimationEnd",WebkitAnimation:"webkitAnimationEnd"};for(var i in o)if(void 0!==n[0].style[i]){o=o[i];break}return r&&n.css("-webkit-animation-duration",r+"s").css("animation-duration",r+"s"),n.addClass("animated "+e).one(o,function(){setTimeout(function(){$(n).removeClass("animated "+e)},1),r&&$(n).css("-webkit-animation-duration","").css("animation-duration",""),"function"==typeof t&&t()}),n}}),sf.controller=new function(){var self=this;self.pending={},self.active={},self.for=function(e,t){self.pending[e]=t},self.modelScope=function(e,t){var r=$(e),n=sf.controller.modelName(e);if(!n)throw"model or controller was not found";var o=r.attr("[sf-bind-list]");if(o||(o=r.parents("[sf-bind-list]").attr("sf-bind-list")),!o)return t?t(sf.model.root[n],-1):sf.model.root[n];var i=0;return o&&(i=r.parents("[sf-bind-list]").prevAll("[sf-bind-list]").length),t?t(sf.model.root[n][o],i):sf.model.root[n][o][i]},self.modelName=function(e){var t=void 0;return void 0===(t=e.attributes["sf-controller"]?e.attributes["sf-controller"].value:$(e).parents("[sf-controller]").attr("sf-controller"))||self.active[t]||self.run(t),t};var listenSFClick=function listenSFClick(e){var element=$(e.target),script=element.attr("sf-click");script||(element=element.parents("[sf-click]").eq(0),script=element.attr("sf-click"));var model=element.parents("[sf-controller]").attr("sf-controller");if(!sf.model.root[model])throw"Couldn't find model for "+model+" that was called from sf-click";var _modelScope=sf.model.root[model],modelKeys=sf.model.modelKeys(_modelScope),scopeMask=RegExp(sf.regex.strictVar+"("+modelKeys+")"+sf.regex.avoidQuotes+"\\b","g");script=script.replace(scopeMask,function(e,t){return"_modelScope."+t}),script=script.split("(");var method=script[0],method_=method;try{method=eval(method)}catch(e){method=!1}if(method){script.shift(),script=script.join("("),script=script.split(")"),script.pop(),script=script.join("("),0!==script.length&&(script=eval("["+script+"]")),script||(script=[]);try{method.apply(element[0],script)}catch(e){console.error("Error on sf-click for model: "+model+"\n",e.target,"\n",e)}}else console.error("Error on sf-click for model: "+model+" [Cannot find "+method_+"]\n",e.target)},root_=function(e){return sf.model.root[e]||(sf.model.root[e]={}),sf.model.root[e]||sf.controller.run(e),sf.model.root[e]};self.run=function(e,t){if(!sf.loader.DOMWasLoaded)return sf(function(){self.run(e,t)});self.pending[e]&&(sf.model.root[e]||(sf.model.root[e]={}),self.pending[e](sf.model.root[e],root_),self.active[e]=!0,delete self.pending[e]),t&&t(sf.model.root[e],root_)},self.init=function(e){if(!sf.loader.DOMWasLoaded)return sf(function(){self.init(name)});$("[sf-controller]",e?$(e)[0]:document.body).each(function(){self.run(this.attributes["sf-controller"].value)})},$(function(){$("body").on("click","[sf-controller] [sf-click]",listenSFClick)})},sf.loader=new function(){var e=this;e.loadedContent=0,e.totalContent=0,e.DOMWasLoaded=!1;var t=[],r=[];e.onFinish=function(r){if(e.DOMWasLoaded)return r();-1===t.indexOf(r)&&t.push(r)},e.onProgress=function(t){if(e.DOMWasLoaded)return t(e.loadedContent,e.totalContent);-1===r.indexOf(t)&&r.push(t)},e.f=function(t){e.loadedContent++;for(var n=0;n=0;r--)0!==$('link[href*="'+t[r]+'"]').length&&t.splice(r,1);if(0===t.length)return}e.totalContent=e.totalContent+t.length;var n="";for(r=0;r';$(function(){document.getElementsByTagName("body")[0].innerHTML+=n})},e.js=function(t){if(e.DOMWasLoaded){for(var r=t.length-1;r>=0;r--)0!==$('script[src*="'+t[r]+'"]').length&&t.splice(r,1);if(0===t.length)return}e.totalContent=e.totalContent+t.length;for(r=0;r=0;r--)-1!==t[r].indexOf("$")&&t.splice(r,1);return t.join("|")};var clearElementData=function(e){$&&$.cleanData&&$.cleanData(e.getElementsByTagName("*")),e.innerHTML="";for(var t=0;t\&]/gim,function(e){return"&#"+e.charCodeAt(0)+";"})})},uniqueDataParser=function(e,t,r,n){var o={length:0,take:function(e,o){if(!e)return dataParser(this[o],t,r,n);var i='"use strict";var ',a=!0;for(var l in e)"string"==typeof e[l]?e[l]='"'+e[l].split('"').join('\\"')+'"':"object"==typeof e[l]&&(e[l]=JSON.stringify(e[l])),a||(i+=","),i+=l+" = "+e[l],a=!1;return i=i.split("(").join("").split(")").join(""),dataParser(this[o],t,r,n,i+";")}};e=e.replace(/{\[([\s\S]*?)\]}/g,function(e,t){return o[o.length]=t,o.length++,"_result_ += _content_.take(&VarPass&, "+(o.length-1)+");"});var i=self.root[n],a=RegExp(sf.regex.strictVar+"("+self.modelKeys(i)+")"+sf.regex.avoidQuotes+"\\b","g");if(r)var l=RegExp(sf.regex.strictVar+r+"\\."+sf.regex.avoidQuotes+"\\b","g");return e.replace(/{{(@[\s\S]*?)}}/g,function(e,n){n=n.split('\\"').join("\\$%*").split("\\'").join("\\%$*"),r&&(n=n.replace(l,function(e){return"_model_."+e[0].slice(1)}));var s=!1;if(1!=(s=(n=(n=n.replace(a,function(e,t){return"_modelScope."+t})).split("\\$%*").join('\\"').split("\\%$*").join("\\'")).split("@if ")).length&&(s=s[1].split(":"),localEval.apply(self.root,[s[0],t,i,o])))return s.shift(),s.join(":");for(var f=/(var|let)([\w,\s]+)(?=\s(?==|in|of))/g,c=[],d=null;null!==(d=f.exec(n));)c.push(d[2]);if(c.length){for(var u=[],p=0;p").split("&").join("&"),n=localEval.apply(self.root,[s,t,i,o])):""})},bindArray=function(e,t,r,n,o,i){for(var a=t.slice(0),l=["pop","push","splice","shift","unshift","softRefresh","hardRefresh"],s=function(t,a,l,s){var f=$("[sf-controller='"+n+"']",i);if(0!==f.length){f=f.find("[sf-bind-list='"+o+"']");var c=!1;if(self.root[n]["on$"+o]&&(c=self.root[n]["on$"+o]),-1===t){for(var d=self.root[n][o],u="",p=0;p=3)arguments[0]=!1,t="softRefresh";else{var n=arguments[0];n<0&&(n=r+n);var o=arguments[1];o||(o=a.length);for(var i=o-1;i>=0;i--)s(n+i)}else"unshift"===t&&s(0,!0,!0);if("softRefresh"===t)if(arguments[0]||0===arguments[0])s(arguments[0],!!a[arguments[0]]);else{var l=!1;if(a.length>this.length)for(i=a.length-1;i>=this.length;i--)-1===this.indexOf(a[i])&&(l=!0,s(i));if(a.lengthe.length&&l.splice(e.length),l}}),bindArray(t,l,a,e,i[1],n)}return o},bindInput=function(e){$("input[sf-bound]",e).each(function(){var e=$(this),t=e.parents("[sf-controller]").attr("sf-controller");if(t){var r=e.attr("sf-bound");void 0!==typeof self.root[t][r]?(e.attr("sf-bounded",r),e.removeAttr("sf-bound"),e.keyup(function(n){self.root[t][r]=e.val()}),e.attr("value","{{"+r+"}}"),bindObject(e,self.root[t],r,"attr")):console.error('Cannot get reference for self.root["'+t+'"]["'+r+'"]')}})},alreadyInitialized=!1;function DOMNodeRemoved(e){var t=sf.controller.modelName(e);$("[sf-bind-id], [sf-bind-list], [sf-bounded], [sf-repeat-this]",e).each(function(){removeBinding(this,t)}),removeBinding(e)}self.init=function(e){alreadyInitialized||(alreadyInitialized=!0,setTimeout(function(){alreadyInitialized=!1},50),e=e?$(e)[0]:document.body,self.parsePreprocess(self.queuePreprocess(e)),bindInput(e),$("[sf-repeat-this]",e).each(function(){var t=$(this),r=t.parent(),n=t.next();n.length&&t[0]!==n[0]||(n=!1);var o=t.before();o.length&&t[0]!==o[0]||(o=!1);var i=t.attr("sf-repeat-this");t.removeAttr("sf-repeat-this");var a=sf.controller.modelName(this),l=this.outerHTML;if(/sf-bind-id|sf-bind-list/.test(l))throw"Can't parse element that already bound";var s=loopParser(a,l,i,e);s?(t.remove(),s=$(s),n?s.insertBefore(n):o?s.insertAfter(o):r.append(s)):(t.attr("sf-bind-list",i.split(" in ")[1]),clearElementData(this))}))},$(function(){"function"==typeof MutationObserver&&MutationObserver.prototype.observe?new MutationObserver(function(e){if(bindingEnabled)for(var t in e)for(var r in e[t].removedNodes){var n=e[t].removedNodes[r].nodeName;"TEXT"===n&&"#comment"===n&&DOMNodeRemoved(e[t].removedNodes[r])}}).observe(document.body,{childList:!0,subtree:!0}):document.body.addEventListener("DOMNodeRemoved",function(e){if(bindingEnabled){var t=e.target.nodeName;if("TEXT"!==t||"#comment"!==t)return;DOMNodeRemoved(e.target)}})});var removeBinding=function(e,t){if(e.attributes){var r=e.attributes;if(r["sf-bind-id"]){var n=r["sf-bind-id"].value;if(!bindRef[n])return;for(var o=bindRef[n],i=0;i").join("--\x3e"),d=JSON.parse(d),!$.isEmptyObject(d)))for(var u=0;u=0;r--)0!==$('link[href*="'+t[r]+'"]').length&&t.splice(r,1);if(0===t.length)return}e.totalContent=e.totalContent+t.length;var n="";for(r=0;r';$(function(){document.getElementsByTagName("body")[0].innerHTML+=n})},e.js=function(t){if(e.DOMWasLoaded){for(var r=t.length-1;r>=0;r--)0!==$('script[src*="'+t[r]+'"]').length&&t.splice(r,1);if(0===t.length)return}e.totalContent=e.totalContent+t.length;for(r=0;r=0;r--)-1!==t[r].indexOf("$")&&t.splice(r,1);return t.join("|")};var clearElementData=function(e){$&&$.cleanData&&$.cleanData(e.getElementsByTagName("*")),e.innerHTML="";for(var t=0;t\&]/gim,function(e){return"&#"+e.charCodeAt(0)+";"})})},uniqueDataParser=function(e,t,r,n){var o={length:0,take:function(e,o){if(!e)return dataParser(this[o],t,r,n);var i='"use strict";var ',a=!0;for(var l in e)"string"==typeof e[l]?e[l]='"'+e[l].split('"').join('\\"')+'"':"object"==typeof e[l]&&(e[l]=JSON.stringify(e[l])),a||(i+=","),i+=l+" = "+e[l],a=!1;return i=i.split("(").join("").split(")").join(""),dataParser(this[o],t,r,n,i+";")}};e=e.replace(/{\[([\s\S]*?)\]}/g,function(e,t){return o[o.length]=t,o.length++,"_result_ += _content_.take(&VarPass&, "+(o.length-1)+");"});var i=self.root[n],a=RegExp(sf.regex.strictVar+"("+self.modelKeys(i)+")"+sf.regex.avoidQuotes+"\\b","g");if(r)var l=RegExp(sf.regex.strictVar+r+"\\."+sf.regex.avoidQuotes+"\\b","g");return e.replace(/{{(@[\s\S]*?)}}/g,function(e,n){n=n.split('\\"').join("\\$%*").split("\\'").join("\\%$*"),r&&(n=n.replace(l,function(e){return"_model_."+e[0].slice(1)}));var s=!1;if(1!=(s=(n=(n=n.replace(a,function(e,t){return"_modelScope."+t})).split("\\$%*").join('\\"').split("\\%$*").join("\\'")).split("@if ")).length&&(s=s[1].split(":"),localEval.apply(self.root,[s[0],t,i,o])))return s.shift(),s.join(":");for(var f=/(var|let)([\w,\s]+)(?=\s(?==|in|of))/g,c=[],d=null;null!==(d=f.exec(n));)c.push(d[2]);if(c.length){for(var u=[],p=0;p").split("&").join("&"),n=localEval.apply(self.root,[s,t,i,o])):""})},bindArray=function(e,t,r,n,o,i){for(var a=t.slice(0),l=["pop","push","splice","shift","unshift","softRefresh","hardRefresh"],s=function(t,a,l,s){var f=$("[sf-controller='"+n+"']",i);if(0!==f.length){f=f.find("[sf-bind-list='"+o+"']");var c=!1;if(self.root[n]["on$"+o]&&(c=self.root[n]["on$"+o]),-1===t){for(var d=self.root[n][o],u="",p=0;p=3)arguments[0]=!1,t="softRefresh";else{var n=arguments[0];n<0&&(n=r+n);var o=arguments[1];o||(o=a.length);for(var i=o-1;i>=0;i--)s(n+i)}else"unshift"===t&&s(0,!0,!0);if("softRefresh"===t)if(arguments[0]||0===arguments[0])s(arguments[0],!!a[arguments[0]]);else{var l=!1;if(a.length>this.length)for(i=a.length-1;i>=this.length;i--)-1===this.indexOf(a[i])&&(l=!0,s(i));if(a.lengthe.length&&l.splice(e.length),l}}),bindArray(t,l,a,e,i[1],n)}return o},bindInput=function(e){$("input[sf-bound]",e).each(function(){var e=$(this),t=e.parents("[sf-controller]").attr("sf-controller");if(t){var r=e.attr("sf-bound");void 0!==typeof self.root[t][r]?(e.attr("sf-bounded",r),e.removeAttr("sf-bound"),e.keyup(function(n){self.root[t][r]=e.val()}),e.attr("value","{{"+r+"}}"),bindObject(e,self.root[t],r,"attr")):console.error('Cannot get reference for self.root["'+t+'"]["'+r+'"]')}})},alreadyInitialized=!1;function DOMNodeRemoved(e){var t=sf.controller.modelName(e);$("[sf-bind-id], [sf-bind-list], [sf-bounded], [sf-repeat-this]",e).each(function(){removeBinding(this,t)}),removeBinding(e)}self.init=function(e){alreadyInitialized||(alreadyInitialized=!0,setTimeout(function(){alreadyInitialized=!1},50),e=e?$(e)[0]:document.body,self.parsePreprocess(self.queuePreprocess(e)),bindInput(e),$("[sf-repeat-this]",e).each(function(){var t=$(this),r=t.parent(),n=t.next();n.length&&t[0]!==n[0]||(n=!1);var o=t.before();o.length&&t[0]!==o[0]||(o=!1);var i=t.attr("sf-repeat-this");t.removeAttr("sf-repeat-this");var a=sf.controller.modelName(this),l=this.outerHTML;if(/sf-bind-id|sf-bind-list/.test(l))throw"Can't parse element that already bound";var s=loopParser(a,l,i,e);s?(t.remove(),s=$(s),n?s.insertBefore(n):o?s.insertAfter(o):r.append(s)):(t.attr("sf-bind-list",i.split(" in ")[1]),clearElementData(this))}))},$(function(){"function"==typeof MutationObserver&&MutationObserver.prototype.observe?new MutationObserver(function(e){if(bindingEnabled)for(var t in e)for(var r in e[t].removedNodes){var n=e[t].removedNodes[r].nodeName;"TEXT"===n&&"#comment"===n&&DOMNodeRemoved(e[t].removedNodes[r])}}).observe(document.body,{childList:!0,subtree:!0}):document.body.addEventListener("DOMNodeRemoved",function(e){if(bindingEnabled){var t=e.target.nodeName;if("TEXT"!==t||"#comment"!==t)return;DOMNodeRemoved(e.target)}})});var removeBinding=function(e,t){if(e.attributes){var r=e.attributes;if(r["sf-bind-id"]){var n=r["sf-bind-id"].value;if(!bindRef[n])return;for(var o=bindRef[n],i=0;i").join("--\x3e"),d=JSON.parse(d),!$.isEmptyObject(d)))for(var u=0;u= 0; i--) {\r\n\t\t\t\tif($('link[href*=\"'+list[i]+'\"]').length!==0)\r\n\t\t\t\t\tlist.splice(i, 1);\r\n\t\t\t}\r\n\t\t\tif(list.length === 0) return;\r\n\t\t}\r\n\t\tself.totalContent = self.totalContent + list.length;\r\n\t\tvar temp = '';\r\n\t\tfor(var i = 0; i < list.length; i++){\r\n\t\t\ttemp += '';\r\n\t\t}\r\n\r\n\t\t$(function(){\r\n\t\t\tdocument.getElementsByTagName('body')[0].innerHTML += temp;\r\n\t\t});\r\n\t}\r\n\r\n\tself.js = function(list){\r\n\t\tif(self.DOMWasLoaded){\r\n\t\t\t// check if some list was loaded\r\n\t\t\tfor (var i = list.length - 1; i >= 0; i--) {\r\n\t\t\t\tif($('script[src*=\"'+list[i]+'\"]').length!==0)\r\n\t\t\t\t\tlist.splice(i, 1);\r\n\t\t\t}\r\n\t\t\tif(list.length === 0) return;\r\n\t\t}\r\n\t\tself.totalContent = self.totalContent + list.length;\r\n\t\tfor(var i = 0; i < list.length; i++){\r\n\t\t\t$.ajax({\r\n\t\t\t url: list[i],\r\n\t\t\t dataType: \"script\",\r\n\t\t\t cache: true,\r\n\t\t\t complete: sf.loader.f\r\n\t\t\t});\r\n\t\t}\r\n\t}\r\n\r\n\tsetTimeout(function(){\r\n\t\tif(self.totalContent === 0)\r\n\t\t\tself.loadedContent = self.totalContent = 1;\r\n\t}, 10000);\r\n\tvar everythingLoaded = setInterval(function() {\r\n\tif (/loaded|complete/.test(document.readyState)) {\r\n\t\tif(self.loadedContent < self.totalContent || self.loadedContent === 0)\r\n\t\t\treturn;\r\n\r\n\t\tclearInterval(everythingLoaded);\r\n\t\tself.DOMWasLoaded = true;\r\n\t\tfor (var i = 0; i < whenDOMLoaded.length; i++) {\r\n\t\t\ttry{\r\n\t\t\t\twhenDOMLoaded[i]();\r\n\t\t\t} catch(e){\r\n\t\t\t\tconsole.error(e);\r\n\t\t\t}\r\n\t\t}\r\n\t\twhenProgress.splice(0);\r\n\t\twhenDOMLoaded.splice(0);\r\n\r\n\t\t// Last init\r\n\t\tsf.controller.init();\r\n\t\tsf.model.init();\r\n\t\tsf.router.init();\r\n\t}\r\n\t}, 100);\r\n};\r\nsf.prototype.constructor = sf.loader.onFinish;\r\n\r\n// Find images\r\n$(function(){\r\n\t$('img:not(onload)[src]').each(function(){\r\n\t\tsf.loader.totalContent++;\r\n\t\tthis.setAttribute('onload', \"sf.loader.f(this)\");\r\n\t});\r\n});","// Data save and HTML content binding\r\nsf.model = new function(){\r\n\tvar self = this;\r\n\tvar bindingEnabled = false;\r\n\tself.root = {};\r\n\tvar root_ = function(scope){\r\n\t\tif(!self.root[scope])\r\n\t\t\tself.root[scope] = {};\r\n\r\n\t\tif(sf.controller.pending[scope])\r\n\t\t\tsf.controller.run(scope);\r\n\r\n\t\treturn self.root[scope];\r\n\t};\r\n\r\n\tvar processingElement = null;\r\n\r\n\tvar bracketMatch = RegExp('([\\\\w.]*?[\\\\S\\\\s])\\\\('+sf.regex.avoidQuotes, 'g');\r\n\tvar chackValidFunctionCall = /[a-zA-Z0-9 \\]\\$\\)]/;\r\n\tvar allowedFunction = [':', 'for', 'if', 'while', '_content_.take', 'console.log'];\r\n\tvar localEval = function(script_, _model_, _modelScope, _content_){\r\n\t\tvar script = script_;\r\n\t\tscript_ = script_.split('\\\\\"').join('\\\\$%*').split(\"\\\\'\").join('\\\\%$*'); // ToDo: Escape\r\n\r\n\t\t// Prevent vulnerability by remove bracket to avoid a function call\r\n\t\tvar preventExecution = false;\r\n\t\tvar check = null;\r\n\t\twhile((check = bracketMatch.exec(script_)) !== null){\r\n\t\t\tcheck[1] = check[1].trim();\r\n\r\n\t\t\tif(allowedFunction.indexOf(check[1]) === -1 &&\r\n\t\t\t\tcheck[1].split('.')[0] !== '_modelScope' &&\r\n\t\t\t\tchackValidFunctionCall.test(check[1][check[1].length-1])\r\n\t\t\t){\r\n\t\t\t\tpreventExecution = check[1];\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t}\r\n\t\t\r\n\t\tvar _result_ = '';\r\n\t\tscript_ = script_.split('\\\\$%*').join('\\\\\"').split('\\\\%$*').join(\"\\\\'\"); // ToDo: Unescape\r\n\t\tif(preventExecution){\r\n\t\t\tconsole.error(\"Trying to executing unrecognized function (\"+preventExecution+\")\");\r\n\t\t\tconsole.log($(processingElement.outerHTML)[0]);\r\n\t\t\tconsole.log(script_);\r\n\t\t\treturn '';\r\n\t\t}\r\n\t\ttry{\r\n\t\t\tvar _evaled_ = eval(script_);\r\n\t\t} catch(e){\r\n\t\t\tconsole.error(e);\r\n\t\t\tconsole.log(script_);\r\n\t\t\tconsole.log($(processingElement.outerHTML)[0]);\r\n\t\t\treturn '';\r\n\t\t}\r\n\r\n\t\tif(_result_ !== '') return _result_;\r\n\t\treturn _evaled_;\r\n\t}\r\n\r\n\tself.index = function(element){\r\n\t\treturn $(element).prevAll(element.tagName).length;\r\n\t}\r\n\r\n\tself.for = function(name, func){\r\n\t\tif(!sf.loader.DOMWasLoaded)\r\n\t\t\treturn sf(function(){\r\n\t\t\t\tself.for(name, func);\r\n\t\t\t});\r\n\t\t\r\n\t\tfunc(root_(name), root_);\r\n\t}\r\n\r\n\tself.modelKeys = function(modelRef){\r\n\t\tvar keys = Object.keys(modelRef);\r\n\t\tfor (var i = keys.length - 1; i >= 0; i--) {\r\n\t\t\tif(keys[i].indexOf('$') !== -1)\r\n\t\t\t\tkeys.splice(i, 1);\r\n\t\t}\r\n\t\treturn keys.join('|');\r\n\t}\r\n\r\n\tvar clearElementData = function(current){\r\n\t\t// Clean associated data on jQuery\r\n\t\tif($ && $.cleanData)\r\n\t\t\t$.cleanData(current.getElementsByTagName(\"*\"));\r\n\r\n\t\tcurrent.innerHTML = '';\r\n\t\tfor (var i = 0; i < current.attributes.length; i++) {\r\n\t\t\tvar name = current.attributes[i].name;\r\n\t\t\tif(name !== 'sf-bind-list')\r\n\t\t\t\tcurrent.removeAttribute(name);\r\n\t\t}\r\n\t\tcurrent.setAttribute('style', 'display:none');\r\n\t}\r\n\r\n\t// For contributor of this library\r\n\t// Please be careful when you're passing the eval argument\r\n\tvar dataParser = function(html, _model_, mask, scope, runEval){\r\n\t\tvar _modelScope = self.root[scope];\r\n\t\tif(!runEval) runEval = '';\r\n\r\n\t\t// Don't match text inside quote, or object keys\r\n\t\tvar scopeMask = RegExp(sf.regex.strictVar+'('+self.modelKeys(_modelScope)+')'+sf.regex.avoidQuotes+'\\\\b', 'g');\r\n\r\n\t\tif(mask)\r\n\t\t\tvar itemMask = RegExp(sf.regex.strictVar+mask+'\\\\.'+sf.regex.avoidQuotes+'\\\\b', 'g');\r\n\r\n\t\tbindingEnabled = true;\r\n\r\n\t\treturn html.replace(/{{([^@][\\s\\S]*?)}}/g, function(actual, temp){\r\n\t\t\t// ToDo: The regex should be optimized to avoid match in a quote (but not escaped quote)\r\n\t\t\ttemp = temp.split('\\\\\"').join('\\\\$%*').split(\"\\\\'\").join('\\\\%$*'); // ToDo: Escape\r\n\r\n\t\t\t// Mask item variable\r\n\t\t\tif(mask)\r\n\t\t\t\ttemp = temp.replace(itemMask, function(matched){\r\n\t\t\t\t\treturn '_model_.'+matched[0].slice(1);\r\n\t\t\t\t});\r\n\r\n\t\t\t// Mask model for variable\r\n\t\t\ttemp = temp.replace(scopeMask, function(full, matched){\r\n\t\t\t\treturn '_modelScope.'+matched;\r\n\t\t\t});\r\n\r\n\t\t\ttemp = temp.split('\\\\$%*').join('\\\\\"').split('\\\\%$*').join(\"\\\\'\"); // ToDo: Unescape\r\n\r\n\t\t\t// Evaluate\r\n\t\t\ttemp = '' + localEval.apply(self.root, [runEval + temp, _model_, _modelScope]);\r\n\r\n\t\t\treturn temp.replace(/[\\u00A0-\\u9999<>\\&]/gim, function(i) {\r\n\t\t return '&#'+i.charCodeAt(0)+';';\r\n\t\t });\r\n\t\t});\r\n\t}\r\n\r\n\tvar uniqueDataParser = function(html, _model_, mask, scope){\r\n\t\t// Get prepared html content\r\n\t\tvar _content_ = {\r\n\t\t\tlength:0,\r\n\t\t\ttake:function(passVar, currentIndex){\r\n\t\t\t\tif(!passVar)\r\n\t\t\t\t\treturn dataParser(this[currentIndex], _model_, mask, scope);\r\n\r\n\t\t\t\tvar strDeclare = '\"use strict\";var ';\r\n\t\t\t\tvar firstTime = true;\r\n\r\n\t\t\t\tfor(var key in passVar){\r\n\t\t\t\t\tif(typeof passVar[key] === 'string')\r\n\t\t\t\t\t\tpassVar[key] = '\"'+passVar[key].split('\"').join('\\\\\"')+'\"';\r\n\t\t\t\t\telse if(typeof passVar[key] === 'object')\r\n\t\t\t\t\t\tpassVar[key] = JSON.stringify(passVar[key]);\r\n\r\n\t\t\t\t\tif(!firstTime)\r\n\t\t\t\t\t\tstrDeclare += ',';\r\n\r\n\t\t\t\t\tstrDeclare += key + ' = ' + passVar[key];\r\n\t\t\t\t\tfirstTime = false;\r\n\t\t\t\t}\r\n\r\n\t\t\t\t// Disable function call for addional security eval protection\r\n\t\t\t\tstrDeclare = strDeclare.split('(').join('').split(')').join('');\r\n\r\n\t\t\t\treturn dataParser(this[currentIndex], _model_, mask, scope, strDeclare + ';');\r\n\t\t\t}\r\n\t\t};\r\n\r\n\t\thtml = html.replace(/{\\[([\\s\\S]*?)\\]}/g, function(full, matched){\r\n\t\t\t_content_[_content_.length] = matched;\r\n\t\t\t_content_.length++;\r\n\t\t\treturn '_result_ += _content_.take(&VarPass&, '+(_content_.length - 1)+');';\r\n\t\t});\r\n\r\n\t\tvar _modelScope = self.root[scope];\r\n\r\n\t\t// Don't match text inside quote, or object keys\r\n\t\tvar scopeMask = RegExp(sf.regex.strictVar+'('+self.modelKeys(_modelScope)+')'+sf.regex.avoidQuotes+'\\\\b', 'g');\r\n\r\n\t\tif(mask)\r\n\t\t\tvar itemMask = RegExp(sf.regex.strictVar+mask+'\\\\.'+sf.regex.avoidQuotes+'\\\\b', 'g');\r\n\r\n\t\treturn html.replace(/{{(@[\\s\\S]*?)}}/g, function(actual, temp){\r\n\t\t\t// ToDo: The regex should be optimized to avoid match in a quote (but not escaped quote)\r\n\t\t\ttemp = temp.split('\\\\\"').join('\\\\$%*').split(\"\\\\'\").join('\\\\%$*'); // ToDo: Escape\r\n\r\n\t\t\t// Mask item variable\r\n\t\t\tif(mask)\r\n\t\t\t\ttemp = temp.replace(itemMask, function(matched){\r\n\t\t\t\t\treturn '_model_.'+matched[0].slice(1);\r\n\t\t\t\t});\r\n\r\n\t\t\t// Mask model for variable\r\n\t\t\ttemp = temp.replace(scopeMask, function(full, matched){\r\n\t\t\t\treturn '_modelScope.'+matched;\r\n\t\t\t});\r\n\t\t\ttemp = temp.split('\\\\$%*').join('\\\\\"').split('\\\\%$*').join(\"\\\\'\"); // ToDo: Unescape\r\n\r\n\t\t\tvar result = '';\r\n\t\t\tvar check = false;\r\n\r\n\t\t\tcheck = temp.split('@if ');\r\n\t\t\tif(check.length != 1){\r\n\t\t\t\tcheck = check[1].split(':');\r\n\t\t\t\r\n\t\t\t\t// If condition was meet\r\n\t\t\t\tif(localEval.apply(self.root, [check[0], _model_, _modelScope, _content_])){\r\n\t\t\t\t\tcheck.shift();\r\n\t\t\t\t\treturn check.join(':');\r\n\t\t\t\t}\r\n\t\t\t}\r\n\r\n\t\t\t// Get defined variables\r\n\t\t\tvar VarPass_ = /(var|let)([\\w,\\s]+)(?=\\s(?==|in|of))/g;\r\n\t\t\tvar VarPass = [];\r\n\t\t\tvar s1 = null;\r\n\t\t\twhile((s1 = VarPass_.exec(temp)) !== null){\r\n\t\t\t\tVarPass.push(s1[2]);\r\n\t\t\t}\r\n\t\t\tif(VarPass.length){\r\n\t\t\t\tvar obtained = [];\r\n\t\t\t\tfor (var i = 0; i < VarPass.length; i++) {\r\n\t\t\t\t\tVarPass[i].replace(/([\\n\\t\\r]| )+/g, '').split(',').forEach(function(val){\r\n\t\t\t\t\t\tobtained.push(val);\r\n\t\t\t\t\t});\r\n\t\t\t\t};\r\n\t\t\t\tVarPass = obtained;\r\n\t\t\t\tfor (var i = 0; i < VarPass.length; i++) {\r\n\t\t\t\t\tVarPass[i] += ':(typeof '+VarPass[i]+'!=\"undefined\"?'+VarPass[i]+':undefined)';\r\n\t\t\t\t}\r\n\t\t\t\tVarPass = '{'+VarPass.join(',')+'}';\r\n\t\t\t\ttemp = temp.split('&VarPass&').join(VarPass);\r\n\t\t\t}\r\n\t\t\ttemp = temp.split('&VarPass&').join('{}'); \r\n\r\n\t\t\t// Warning! Avoid unencoded user inputted content\r\n\t\t\t// And always check/remove closing ']}' in user content\r\n\t\t\t// Any function call will be removed for addional security\r\n\t\t\tcheck = temp.split('@exec');\r\n\t\t\tif(check.length != 1){\r\n\t\t\t\tcheck = check[1].split('<').join('<').split('>').join('>').split('&').join('&');\r\n\r\n\t\t\t\ttemp = localEval.apply(self.root, [check, _model_, _modelScope, _content_]);\r\n\t\t\t\treturn temp;\r\n\t\t\t}\r\n\t\t\treturn '';\r\n\t\t});\r\n\t}\r\n\r\n\tvar bindArray = function(html, list, mask, modelName, propertyName, targetNode){\r\n\t\tvar oldArray = list.slice(0);\r\n\t\tvar editProperty = ['pop', 'push', 'splice', 'shift', 'unshift', 'softRefresh', 'hardRefresh'];\r\n\t\tvar processElement = function(index, update, insertBefore, insertAfter){\r\n\t\t\tvar exist = $(\"[sf-controller='\"+modelName+\"']\", targetNode);\r\n\t\t\tif(exist.length === 0) return;\r\n\r\n\t\t\texist = exist.find(\"[sf-bind-list='\"+propertyName+\"']\");\r\n\r\n\t\t\tvar callback = false;\r\n\t\t\tif(self.root[modelName]['on$'+propertyName])\r\n\t\t\t\tcallback = self.root[modelName]['on$'+propertyName];\r\n\r\n\t\t\t// Hard refresh\r\n\t\t\tif(index === -1){\r\n\t\t\t\tvar item = self.root[modelName][propertyName];\r\n\t\t\t\tvar all = '';\r\n\t\t\t\tfor (var i = 0; i < item.length; i++) {\r\n\t\t\t\t\tvar temp = uniqueDataParser(html, item[i], mask, modelName);\r\n\t\t\t\t\tall += dataParser(temp, item[i], mask, modelName);\r\n\t\t\t\t}\r\n\r\n\t\t\t\t// Get first element\r\n\t\t\t\tvar first = exist.eq(0).before();\r\n\t\t\t\tif(first[0] === exist[0])\r\n\t\t\t\t\texist.parent().prepend(all);\r\n\t\t\t\telse\r\n\t\t\t\t\t$(all).insertAfter(first);\r\n\t\t\t\texist.remove();\r\n\t\t\t\t\r\n\t\t\t\treturn;\r\n\t\t\t}\r\n\r\n\t\t\t// Remove\r\n\t\t\tif(!update){\r\n\t\t\t\tif(exist[index]){\r\n\t\t\t\t\tvar currentRemoved = false;\r\n\t\t\t\t\tvar startRemove = function(){\r\n\t\t\t\t\t\tif(currentRemoved) return;\r\n\t\t\t\t\t\tcurrentRemoved = true;\r\n\r\n\t\t\t\t\t\tif(exist.length <= 1)\r\n\t\t\t\t\t\t\treturn clearElementData(exist[index]);\r\n\r\n\t\t\t\t\t\texist[index].remove();\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t\tif(callback.remove){\r\n\t\t\t\t\t\t// Auto remove if return false\r\n\t\t\t\t\t\tif(!callback.remove(exist[index], startRemove))\r\n\t\t\t\t\t\t\tsetTimeout(startRemove, 800);\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t\t// Auto remove if no callback\r\n\t\t\t\t\telse startRemove();\r\n\t\t\t\t}\r\n\t\t\t\treturn;\r\n\t\t\t}\r\n\r\n\t\t\t// Create or update\r\n\t\t\tvar item = self.root[modelName][propertyName][index];\r\n\r\n\t\t\tvar temp = uniqueDataParser(html, item, mask, modelName);\r\n\t\t\ttemp = dataParser(temp, item, mask, modelName);\r\n\t\t\ttemp = $(temp);\r\n\r\n\t\t\t// Create\r\n\t\t\tif(!exist[index] || insertAfter){\r\n\t\t\t\tif(callback.create)\r\n\t\t\t\t\tcallback.create(temp[0]);\r\n\r\n\t\t\t\ttemp.insertAfter(exist[index !== 0 ? index - 1 : (exist.length - 1)]);\r\n\t\t\t}\r\n\r\n\t\t\telse{\r\n\t\t\t\t// Create\r\n\t\t\t\tif(insertBefore){\r\n\t\t\t\t\tif(callback.create)\r\n\t\t\t\t\t\tcallback.create(temp[0]);\r\n\r\n\t\t\t\t\ttemp.insertBefore(exist[0]);\r\n\t\t\t\t}\r\n\r\n\t\t\t\t// Update\r\n\t\t\t\telse{\r\n\t\t\t\t\tif(callback.update)\r\n\t\t\t\t\t\tcallback.update(temp[0]);\r\n\r\n\t\t\t\t\t// Clean associated data on jQuery\r\n\t\t\t\t\tif($ && $.cleanData){\r\n\t\t\t\t\t\t$.cleanData(exist[index].getElementsByTagName(\"*\"));\r\n\t\t\t\t\t\t$.cleanData(exist[index]);\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t\texist[index].outerHTML = temp[0].outerHTML;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t\tvar propertyProxy = function(subject, name){\r\n\t\t\tObject.defineProperty(subject, name, {\r\n\t\t\t\tenumerable: false,\r\n\t\t\t\tconfigurable: true,\r\n\t\t\t\tvalue: function(){\r\n\t\t\t\t\tvar temp = undefined;\r\n\t\t\t\t\tvar lastLength = this.length;\r\n\r\n\t\t\t\t\tif(Array.prototype[name])\r\n\t\t\t\t\t\ttemp = Array.prototype[name].apply(this, arguments);\r\n\r\n\t\t\t\t\tif(name === 'pop')\r\n\t\t\t\t\t\tprocessElement(lastLength - 1);\r\n\r\n\t\t\t\t\telse if(name === 'push')\r\n\t\t\t\t\t\tprocessElement(lastLength, true);\r\n\r\n\t\t\t\t\telse if(name === 'shift')\r\n\t\t\t\t\t\tprocessElement(0);\r\n\r\n\t\t\t\t\telse if(name === 'splice'){\r\n\t\t\t\t\t\tif(arguments.length >= 3){ // Inserting data\r\n\t\t\t\t\t\t\targuments[0] = false;\r\n\t\t\t\t\t\t\tname = 'softRefresh';\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t\telse{ // Removing data\r\n\t\t\t\t\t\t\tvar real = arguments[0];\r\n\t\t\t\t\t\t\tif(real < 0) real = lastLength + real;\r\n\r\n\t\t\t\t\t\t\tvar limit = arguments[1];\r\n\t\t\t\t\t\t\tif(!limit) limit = oldArray.length;\r\n\t\t\t\t\t\t\t\r\n\t\t\t\t\t\t\tfor (var i = limit - 1; i >= 0; i--) {\r\n\t\t\t\t\t\t\t\tprocessElement(real + i);\r\n\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t\telse if(name === 'unshift')\r\n\t\t\t\t\t\tprocessElement(0, true, true);\r\n\r\n\t\t\t\t\tif(name === 'softRefresh'){\r\n\t\t\t\t\t\tif(arguments[0] || arguments[0] === 0)\r\n\t\t\t\t\t\t\tprocessElement(arguments[0], !!oldArray[arguments[0]]);\r\n\t\t\t\t\t\telse {\r\n\t\t\t\t\t\t\tvar foundChanges = false;\r\n\r\n\t\t\t\t\t\t\t// Removal\r\n\t\t\t\t\t\t\tif(oldArray.length > this.length){\r\n\t\t\t\t\t\t\t\tfor (var i = oldArray.length - 1; i >= this.length; i--) {\r\n\t\t\t\t\t\t\t\t\tif(this.indexOf(oldArray[i]) === -1){\r\n\t\t\t\t\t\t\t\t\t\tfoundChanges = true;\r\n\t\t\t\t\t\t\t\t\t\tprocessElement(i);\r\n\t\t\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t\t\t// Creates\r\n\t\t\t\t\t\t\tif(oldArray.length < this.length){\r\n\t\t\t\t\t\t\t\tfor (var i = oldArray.length - 1; i < this.length; i++) {\r\n\t\t\t\t\t\t\t\t\tfoundChanges = true;\r\n\t\t\t\t\t\t\t\t\tprocessElement(i, true, true);\r\n\t\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t\t\t// Update\r\n\t\t\t\t\t\t\tfor (var i = 0; i < this.length; i++) {\r\n\t\t\t\t\t\t\t\tif(compareObject(oldArray[i], this[i]) === false){\r\n\t\t\t\t\t\t\t\t\tfoundChanges = true;\r\n\t\t\t\t\t\t\t\t\tprocessElement(i, true);\r\n\t\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t\t\tif(foundChanges)\r\n\t\t\t\t\t\t\t\toldArray = this.slice(0);\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t}\r\n\t\t\t\t\telse if(name === 'hardRefresh'){\r\n\t\t\t\t\t\toldArray = this.slice(0);\r\n\t\t\t\t\t\tprocessElement(-1);\r\n\t\t\t\t\t}\r\n\t\t\t\t\telse Array.prototype[name].apply(oldArray, arguments);\r\n\r\n\t\t\t\t\treturn temp;\r\n\t\t\t\t}\r\n\t\t\t});\r\n\t\t}\r\n\r\n\t\tfor (var i = 0; i < editProperty.length; i++) {\r\n\t\t\tpropertyProxy(list, editProperty[i]);\r\n\t\t}\r\n\t}\r\n\r\n\tfunction compareObject(obj1, obj2){\r\n\t\tif(!obj1 || !obj2)\r\n\t\t\treturn false;\r\n\r\n\t\tfor(var i in obj1){\r\n\t\t\tif(typeof obj1[i] !== 'object' && obj1[i] !== obj2[i])\r\n\t\t\t\treturn false;\r\n\t\t}\r\n\t\treturn true;\r\n\t}\r\n\r\n\tvar loopParser = function(name, content, script, targetNode){\r\n\t\tvar returns = '';\r\n\t\tvar method = script.split(' in ');\r\n\t\tvar mask = method[0];\r\n\r\n\t\tif(!self.root[name])\r\n\t\t\treturn console.error(\"Can't parse element because model for '\"+name+\"' was not found\", $(content)[0]);\r\n\r\n\t\tvar items = self.root[name][method[1]];\r\n\r\n\t\t// Get reference for debugging\r\n\t\tprocessingElement = $(content).attr('sf-bind-list', method[1])[0];\r\n\r\n\t\tcontent = processingElement.outerHTML;\r\n\t\tcontent = content.replace(/ +|\\t+/g, '');\r\n\r\n\t\tif(method.length === 2){\r\n\t\t\tfor(var i in items){\r\n\t\t\t\tvar item = items[i];\r\n\r\n\t\t\t\ttemp = uniqueDataParser(content, item, mask, name);\r\n\t\t\t\ttemp = dataParser(temp, item, mask, name);\r\n\t\t\t\treturns += temp;\r\n\t\t\t}\r\n\t\t\tObject.defineProperty(self.root[name], method[1], {\r\n\t\t\t\tenumerable: true,\r\n\t\t\t\tconfigurable: true,\r\n\t\t\t\tget:function(){\r\n\t\t\t\t\treturn items;\r\n\t\t\t\t},\r\n\t\t\t\tset:function(val){\r\n\t\t\t\t\tfor (var i = 0; i < val.length; i++) {\r\n\t\t\t\t\t\tif(items[i]){\r\n\t\t\t\t\t\t\titems[i] = val[i];\r\n\t\t\t\t\t\t\titems.softRefresh(i);\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t\telse items.push(val[i]);\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t\tif(items.length > val.length)\r\n\t\t\t\t\t\titems.splice(val.length);\r\n\r\n\t\t\t\t\treturn items;\r\n\t\t\t\t}\r\n\t\t\t});\r\n\t\t\tbindArray(content, items, mask, name, method[1], targetNode);\r\n\t\t}\r\n\t\treturn returns;\r\n\t}\r\n\r\n\tvar bindInput = function(targetNode){\r\n\t\t$('input[sf-bound]', targetNode).each(function(){\r\n\t\t\tvar element = $(this);\r\n\t\t\tvar model = element.parents('[sf-controller]').attr('sf-controller');\r\n\t\t\tif(!model) return;\r\n\r\n\t\t\tvar whichVar = element.attr('sf-bound');\r\n\r\n\t\t\t// Get reference\r\n\t\t\tif(typeof self.root[model][whichVar] === undefined){\r\n\t\t\t\tconsole.error('Cannot get reference for self.root[\"' + model + '\"][\"' + whichVar+'\"]');\r\n\t\t\t\treturn;\r\n\t\t\t}\r\n\r\n\t\t\telement.attr('sf-bounded', whichVar);\r\n\t\t\telement.removeAttr('sf-bound');\r\n\r\n\t\t\t// Bound key up\r\n\t\t\telement.keyup(function(e){\r\n\t\t\t\tself.root[model][whichVar] = element.val();\r\n\t\t\t});\r\n\r\n\t\t\t// Bind value\r\n\t\t\telement.attr('value', '{{'+whichVar+'}}');\r\n\t\t\tbindObject(element, self.root[model], whichVar, 'attr');\r\n\t\t});\r\n\t}\r\n\r\n\tvar alreadyInitialized = false;\r\n\tself.init = function(targetNode){\r\n\t\tif(alreadyInitialized) return;\r\n\t\talreadyInitialized = true;\r\n\t\tsetTimeout(function(){\r\n\t\t\talreadyInitialized = false;\r\n\t\t}, 50);\r\n\r\n\t\ttargetNode = targetNode ? $(targetNode)[0] : document.body;\r\n\t\tself.parsePreprocess(self.queuePreprocess(targetNode));\r\n\t\tbindInput(targetNode);\r\n\r\n\t\t$('[sf-repeat-this]', targetNode).each(function(){\r\n\t\t\tvar self = $(this);\r\n\t\t\tvar parent = self.parent();\r\n\r\n\t\t\tvar after = self.next();\r\n\t\t\tif(!after.length || self[0] === after[0])\r\n\t\t\t\tafter = false;\r\n\r\n\t\t\tvar before = self.before();\r\n\t\t\tif(!before.length || self[0] === before[0])\r\n\t\t\t\tbefore = false;\r\n\r\n\t\t\tvar script = self.attr('sf-repeat-this');\r\n\t\t\tself.removeAttr('sf-repeat-this');\r\n\t\t\tvar controller = sf.controller.modelName(this);\r\n\r\n\t\t\tvar content = this.outerHTML;\r\n\r\n\t\t\t// Check if the element was already bound to prevent vulnerability\r\n\t\t\tif(/sf-bind-id|sf-bind-list/.test(content))\r\n\t\t\t\tthrow \"Can't parse element that already bound\";\r\n\r\n\t\t\tvar data = loopParser(controller, content, script, targetNode);\r\n\t\t\tif(data){\r\n\t\t\t\tself.remove();\r\n\t\t\t\t\r\n\t\t\t\tdata = $(data);\r\n\t\t\t\tif(after)\r\n\t\t\t\t\tdata.insertBefore(after);\r\n\t\t\t\telse if(before)\r\n\t\t\t\t\tdata.insertAfter(before);\r\n\t\t\t\telse\r\n\t\t\t\t\tparent.append(data);\r\n\t\t\t}\r\n\t\t\telse{\r\n\t\t\t\tself.attr('sf-bind-list', script.split(' in ')[1]);\r\n\t\t\t\tclearElementData(this);\r\n\t\t\t}\r\n\t\t});\r\n\t}\r\n\r\n\t// Reset model properties\r\n\t// Don't call if the removed element is TEXT or #comment\r\n\tfunction DOMNodeRemoved(element){\r\n\t\tvar model = sf.controller.modelName(element);\r\n\r\n\t\t$('[sf-bind-id], [sf-bind-list], [sf-bounded], [sf-repeat-this]', element).each(function(){\r\n\t\t\tremoveBinding(this, model);\r\n\t\t});\r\n\r\n\t\tremoveBinding(element);\r\n\t}\r\n\r\n\t$(function(){\r\n\t\tif(typeof MutationObserver === 'function' && MutationObserver.prototype.observe){\r\n\t\t\tvar observer = new MutationObserver(function(records){\r\n\t\t\t\tif(!bindingEnabled) return;\r\n\r\n\t\t\t\tfor(var i in records){\r\n\t\t\t\t\tfor(var a in records[i].removedNodes){\r\n\t\t\t\t\t\tvar tagName = records[i].removedNodes[a].nodeName;\r\n\t\t\t\t\t\tif(tagName !== 'TEXT' || tagName !== '#comment') continue;\r\n\t\t\t\t\t\tDOMNodeRemoved(records[i].removedNodes[a]);\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t});\r\n\t\t\tobserver.observe(document.body, { childList: true, subtree: true });\r\n\t\t}\r\n\t\telse {\r\n\t\t\tdocument.body.addEventListener('DOMNodeRemoved', function(e){\r\n\t\t\t\tif(bindingEnabled){\r\n\t\t\t\t\tvar tagName = e.target.nodeName;\r\n\t\t\t\t\tif(tagName !== 'TEXT' || tagName !== '#comment') return;\r\n\t\t\t\t\tDOMNodeRemoved(e.target);\r\n\t\t\t\t}\r\n\t\t\t});\r\n\t\t}\r\n\t});\r\n\r\n\tvar removeBinding = function(element, modelNames){\r\n\t\tif(!element.attributes) return;\r\n\r\n\t\tvar attrs = element.attributes;\r\n\t\tif(attrs['sf-bind-id']){\r\n\t\t\tvar id = attrs['sf-bind-id'].value;\r\n\r\n\t\t\tif(!bindRef[id]) return;\r\n\t\t\tvar ref = bindRef[id];\r\n\r\n\t\t\tfor (var i = 0; i < ref.propertyName.length; i++) {\r\n\t\t\t\tvar value = ref.object[ref.propertyName[i]];\r\n\t\t\t\tObject.defineProperty(ref.object, ref.propertyName[i], {\r\n\t\t\t\t\tconfigurable: true,\r\n\t\t\t\t\tenumerable:true,\r\n\t\t\t\t\twritable:true,\r\n\t\t\t\t\tvalue:value\r\n\t\t\t\t});\r\n\t\t\t}\r\n\r\n\t\t\tdelete bindRef[id];\r\n\r\n\t\t\t// Remove callback left\r\n\t\t\tvar cache = bindRef.cache\r\n\t\t\tfor(var i in cache){\r\n\t\t\t\tif(cache[i].callback && cache[i].callback[id])\r\n\t\t\t\t\tdelete cache[i].callback[id];\r\n\t\t\t\tif($.isEmptyObject(cache[i].callback))\r\n\t\t\t\t\tdelete cache[i];\r\n\t\t\t}\r\n\r\n\t\t\tif(cache[id]){\r\n\t\t\t\tdelete cache[id].attrs;\r\n\t\t\t\tdelete cache[id].innerHTML;\r\n\t\t\t\tdelete cache[id].modelName;\r\n\t\t\t\tdelete cache[id].model;\r\n\t\t\t\tdelete cache[id].created;\r\n\t\t\t\tdelete cache[id].element;\r\n\t\t\t}\r\n\r\n\t\t\tbindRef.length--;\r\n\t\t\tif(bindRef.length === 0)\r\n\t\t\t\tbindRef.index = 0;\r\n\t\t}\r\n\r\n\t\tif(!modelNames) return;\r\n\r\n\t\tvar propertyName = false;\r\n\t\tif(attrs['sf-bind-list'])\r\n\t\t\tpropertyName = attrs['sf-bind-list'].value;\r\n\r\n\t\tif(attrs['sf-repeat-this'])\r\n\t\t\tpropertyName = attrs['sf-repeat-this'].value.split(' in ')[1];\r\n\r\n\t\tif(attrs['sf-bounded'])\r\n\t\t\tpropertyName = attrs['sf-bounded'].value;\r\n\r\n\t\tfor (var i = 0; i < modelNames.length; i++) {\r\n\t\t\tvar modelRef = self.root[modelNames[i]];\r\n\t\t\tif(!modelRef[propertyName]) continue;\r\n\r\n\t\t\tvar value = modelRef[propertyName].slice(0);\r\n\t\t\tObject.defineProperty(modelRef, propertyName, {\r\n\t\t\t\tconfigurable: true,\r\n\t\t\t\tenumerable:true,\r\n\t\t\t\twritable:true,\r\n\t\t\t\tvalue:value\r\n\t\t\t});\r\n\t\t}\r\n\t}\r\n\r\n\t/*{\r\n\t\tid:{\r\n\t\t\tobject,\r\n\t\t\t[propertyName]\r\n\t\t}\r\n\t}*/\r\n\t// For resetting object property it the element was removed from DOM\r\n\tvar bindRef = {length:0, index:0, cache:{}};\r\n\tself.bindRef = bindRef;\r\n\tvar dcBracket = /{{[\\s\\S]*?}}/;\r\n\tvar bindObject = function(element, object, propertyName, which){\r\n\t\tif(!(element instanceof Node))\r\n\t\t\telement = element[0];\r\n\r\n\t\t// Get reference for debugging\r\n\t\tprocessingElement = element;\r\n\r\n\t\t// First initialization\r\n\t\tvar id = bindRef.index;\r\n\t\t$(element).attr('sf-bind-id', id);\r\n\r\n\t\tbindRef.index++;\r\n\t\tbindRef.length++;\r\n\t\tbindRef.cache[id] = {};\r\n\t\tvar cache = bindRef.cache[id];\r\n\r\n\t\tcache.attrs = {};\r\n\t\tcache.innerHTML = '';\r\n\t\tcache.modelName = sf.controller.modelName(element);\r\n\t\tcache.model = self.root[cache.modelName];\r\n\t\tcache.created = Date.now();\r\n\r\n\t\tif(which === 'attr' || !which){\r\n\t\t\tfor(var i in element.attributes){\r\n\t\t\t\t// Check if it has a bracket\r\n\t\t\t\tif(!dcBracket.test(element.attributes[i].value))\r\n\t\t\t\t\tcontinue;\r\n\r\n\t\t\t\tvar attrName = element.attributes[i].name;\r\n\t\t\t\tcache.attrs[attrName] = element.attributes[i].value;\r\n\r\n\t\t\t\tif(attrName === 'value')\r\n\t\t\t\t\telement.removeAttribute(attrName);\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tif(which === 'html' || !which)\r\n\t\t\tcache.innerHTML = element.innerHTML;\r\n\r\n\t\t// Get current object reference\r\n\t\tif(!bindRef[id]) bindRef[id] = {object:object, propertyName:[]};\r\n\t\tbindRef[id].propertyName.push(propertyName);\r\n\r\n\t\tcache.element = $(element);\r\n\t\tvar callbackFunction = function(){\r\n\t\t\tif(which === 'attr' || !which){\r\n\t\t\t\tfor(var name in cache.attrs){\r\n\t\t\t\t\tif(cache.attrs[name].indexOf(propertyName) === -1)\r\n\t\t\t\t\t\tcontinue;\r\n\r\n\t\t\t\t\tvar temp = dataParser(cache.attrs[name], cache.model, false, cache.modelName);\r\n\t\t\t\t\tif(name === 'value')\r\n\t\t\t\t\t\tcache.element.val(temp);\r\n\t\t\t\t\telse\r\n\t\t\t\t\t\tcache.element.attr(name, temp);\r\n\t\t\t\t\tbreak;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\r\n\t\t\tif(which === 'html' || !which){\r\n\t\t\t\tvar temp = uniqueDataParser(cache.innerHTML, cache.model, false, cache.modelName);\r\n\t\t\t\ttemp = dataParser(temp, cache.model, false, cache.modelName);\r\n\t\t\t\tcache.element.html(temp);\r\n\t\t\t}\r\n\t\t};\r\n\r\n\t\tif(Object.getOwnPropertyDescriptor(cache.model, propertyName)['set']){\r\n\t\t\tfor(var i in bindRef){\r\n\t\t\t\tif(cache.model === bindRef[i].object && bindRef[i].propertyName.indexOf(propertyName) !== -1){\r\n\t\t\t\t\tbindRef.cache[i].callback[id] = callbackFunction;\r\n\t\t\t\t\tbreak;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\treturn;\r\n\t\t}\r\n\r\n\t\tcache.callback = {};\r\n\t\tcache.callback[id] = callbackFunction;\r\n\r\n\t\tvar objValue = object[propertyName]; // Object value\r\n\t\tObject.defineProperty(object, propertyName, {\r\n\t\t\tenumerable: true,\r\n\t\t\tconfigurable: true,\r\n\t\t\tget:function(){\r\n\t\t\t\treturn objValue;\r\n\t\t\t},\r\n\t\t\tset:function(val){\r\n\t\t\t\tobjValue = val;\r\n\r\n\t\t\t\tfor(var i in cache.callback){\r\n\t\t\t\t\tcache.callback[i]();\r\n\t\t\t\t}\r\n\r\n\t\t\t\treturn objValue;\r\n\t\t\t}\r\n\t\t});\r\n\t}\r\n\r\n\tself.bindElement = function(element, which){\r\n\t\tvar modelName = sf.controller.modelName(element);\r\n\t\tvar model = self.root[modelName];\r\n\t\tif(!model) return console.error(\"Model for \"+modelName+\" was not found while binding:\", element);\r\n\r\n\t\tvar html = element.outerHTML;\r\n\r\n\t\t// Check if the child element was already bound to prevent vulnerability\r\n\t\tif(/sf-bind-id|sf-bind-list/.test(html))\r\n\t\t\tthrow \"Can't parse element that already bound\";\r\n\r\n\t\tif(which === 'attr')\r\n\t\t\thtml = html.replace(element.innerHTML, '');\r\n\r\n\t\tvar brackets = /{{([\\s\\S]*?)}}/g;\r\n\t\tvar scopeMask = RegExp('\\\\b[^.]|^|\\\\n| +|\\\\t|\\\\W ('+self.modelKeys(model)+')'+sf.regex.avoidQuotes+'\\\\b', 'g');\r\n\t\tvar s1, s2 = null;\r\n\t\twhile((s1 = brackets.exec(html)) !== null){\r\n\t\t\twhile ((s2 = scopeMask.exec(s1[1])) !== null) {\r\n\t\t\t\tbindObject(element, model, s2[1], which);\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\tself.queuePreprocess = function(targetNode){\r\n\t\tvar childNodes = (targetNode || document.body).childNodes;\r\n\r\n\t\tvar excludes = ['html','head','style','link','meta','script','object','iframe'];\r\n\t\tfor (var i = 0; i < excludes.length; i++) {\r\n\t\t\texcludes[i] = excludes[i].toUpperCase();\r\n\t\t}\r\n\r\n\t\tvar temp = [];\r\n\t\tfor (var i = 0; i < childNodes.length; i++) {\r\n\t\t\tvar currentNode = childNodes[i];\r\n\t\t\tif(excludes.indexOf(currentNode.nodeName) !== -1)\r\n\t\t\t\tcontinue;\r\n\r\n\t\t\tif(currentNode.nodeType === 1){ // Tag\r\n\t\t\t\tvar attrs = currentNode.attributes;\r\n\r\n\t\t\t\t// Skip element and it's childs that already bound to prevent vulnerability\r\n\t\t\t\tif(attrs['sf-bind-id'] || attrs['sf-repeat-this'] || attrs['sf-bind-list']) continue;\r\n\r\n\t\t\t\tfor (var a = 0; a < attrs.length; a++) {\r\n\t\t\t\t\tif(attrs[a].value.indexOf('{{') !== -1){\r\n\t\t\t\t\t\tcurrentNode.setAttribute('sf-preprocess', 'attronly');\r\n\t\t\t\t\t\ttemp.push(currentNode);\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\r\n\t\t\t\ttemp = temp.concat(self.queuePreprocess(currentNode));\r\n\t\t\t}\r\n\r\n\t\t\telse if(currentNode.nodeType === 3){ // Text\r\n\t\t\t\tif(currentNode.nodeValue.indexOf('{{') !== -1){\r\n\t\t\t\t\tcurrentNode.parentNode.setAttribute('sf-preprocess', '');\r\n\r\n\t\t\t\t\t// Reset Siblings\r\n\t\t\t\t\tfor (var a = 0; a < temp.length; a++) {\r\n\t\t\t\t\t\ttemp[a].removeAttribute('sf-preprocess');\r\n\t\t\t\t\t}\r\n\t\t\t\t\ttemp.push(currentNode.parentNode);\r\n\r\n\t\t\t\t\tbreak;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\treturn temp;\r\n\t}\r\n\r\n\tself.parsePreprocess = function(nodes){\r\n\t\tfor (var a = 0; a < nodes.length; a++) {\r\n\t\t\tvar model = sf.controller.modelName(nodes[a]);\r\n\t\t\tnodes[a].removeAttribute('sf-preprocess');\r\n\r\n\t\t\tif(!self.root[model])\r\n\t\t\t\treturn console.error(\"Can't parse element because model for '\"+model+\"' was not found\", nodes[a]);\r\n\r\n\t\t\t// Get reference for debugging\r\n\t\t\tprocessingElement = nodes[a];\r\n\r\n\t\t\t// Double check if the child element already bound to prevent vulnerability\r\n\t\t\tif(/sf-bind-id|sf-bind-list/.test(nodes[a].innerHTML)){\r\n\t\t\t\tconsole.error(\"Can't parse element that already bound\");\r\n\t\t\t\tconsole.log($(processingElement.outerHTML)[0]);\r\n\t\t\t\treturn;\r\n\t\t\t}\r\n\r\n\t\t\tif($(nodes[a]).attr('sf-bind'))\r\n\t\t\t\tself.bindElement(nodes[a], $(nodes[a]).attr('sf-bind'));\r\n\r\n\t\t\t// Avoid editing the outerHTML because it will remove the bind\r\n\t\t\tvar temp = uniqueDataParser(nodes[a].innerHTML, self.root[model], false, model);\r\n\t\t\tnodes[a].innerHTML = dataParser(temp, self.root[model], false, model);\r\n\t\t\tfor (var i = 0; i < nodes[a].attributes.length; i++) {\r\n\t\t\t\tif(nodes[a].attributes[i].value.indexOf('{{') !== -1){\r\n\t\t\t\t\tnodes[a].attributes[i].value = dataParser(nodes[a].attributes[i].value, self.root[model], false, model);\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n}","sf.router = new function(){\r\n\tvar self = this;\r\n\tself.loading = false;\r\n\tself.enabled = false;\r\n\tself.pauseRenderOnTransition = false;\r\n\tself.currentPage = [];\r\n\tvar initialized = false;\r\n\tvar lazyRouting = false;\r\n\tvar currentRouterURL = '';\r\n\r\n\t// Should be called if not using lazy page load\r\n\tself.init = function(targetNode){\r\n\t\tif(!sf.loader.DOMWasLoaded)\r\n\t\t\treturn sf(function(){\r\n\t\t\t\tself.init();\r\n\t\t\t});\r\n\r\n\t\t// Reinit lazy router\r\n\t\tself.lazy();\r\n\r\n\t\t// Run 'before' event for new page view\r\n\t\t$('[sf-controller], [sf-page]', $(targetNode)[0]).each(function(){\r\n\t\t\tif(this.attributes['sf-controller'])\r\n\t\t\t\tsf.controller.run(this.attributes['sf-controller'].value);\r\n\t\t\t\r\n\t\t\tif(this.attributes['sf-page']){\r\n\t\t\t\tvar name = this.attributes['sf-page'].value;\r\n\t\t\t\tbeforeEvent(name);\r\n\t\t\t}\r\n\t\t});\r\n\r\n\t\tinitialized = true;\r\n\t\tcurrentRouterURL = window.location.pathname;\r\n\t}\r\n\r\n\tself.enable = function(status){\r\n\t\tif(status === undefined) status = true;\r\n\t\tif(self.enabled === status) return;\r\n\t\tself.enabled = status;\r\n\r\n\t\tif(status)\r\n\t\t\tself.lazy();\r\n\t\telse{\r\n\t\t\t$('a[href][onclick]').each(function(){\r\n\t\t\t\tvar current = $(this);\r\n\t\t\t\tif(current.attr('onclick') === 'return sf.router.load(this)')\r\n\t\t\t\t\tcurrent.removeAttr('onclick');\r\n\t\t\t});\r\n\t\t}\r\n\r\n\t\twindow.addEventListener('popstate', function(event) {\r\n\t\t\t// Don't continue if the last routing was error\r\n\t\t\tif(routingError){\r\n\t\t\t\troutingError = false;\r\n\t\t\t\treturn;\r\n\t\t\t}\r\n\r\n\t\t\troutingBack = true;\r\n\t\t\tself.goto(window.location.pathname);\r\n\t\t}, false);\r\n\t}\r\n\r\n\tvar before = {};\r\n\t// Set index with number if you want to replace old function\r\n\tself.before = function(name, func, index){\r\n\t\tif(!before[name])\r\n\t\t\tbefore[name] = [];\r\n\r\n\t\tif(index === undefined){\r\n\t\t\tif(before[name].indexOf(func) === -1)\r\n\t\t\t\tbefore[name].push(func);\r\n\t\t}\r\n\t\telse\r\n\t\t\tbefore[name][index] = func;\r\n\t}\r\n\r\n\tvar after = {};\r\n\t// Set index with number if you want to replace old function\r\n\tself.after = function(name, func, index){\r\n\t\tif(!after[name])\r\n\t\t\tafter[name] = [];\r\n\r\n\t\tif(index === undefined){\r\n\t\t\tif(after[name].indexOf(func) === -1)\r\n\t\t\t\tafter[name].push(func);\r\n\t\t}\r\n\t\telse\r\n\t\t\tafter[name][index] = func;\r\n\t}\r\n\r\n\tvar root_ = function(scope){\r\n\t\tif(!sf.model.root[scope])\r\n\t\t\tsf.model.root[scope] = {};\r\n\r\n\t\tif(!sf.model.root[scope])\r\n\t\t\tsf.controller.run(scope);\r\n\t\t\r\n\t\treturn sf.model.root[scope];\r\n\t}\r\n\r\n\t// Running 'before' new page going to be displayed\r\n\tvar beforeEvent = function(name){\r\n\t\tif(self.currentPage.indexOf(name) === -1)\r\n\t\t\tself.currentPage.push(name);\r\n\r\n\t\tif(before[name]){\r\n\t\t\tfor (var i = 0; i < before[name].length; i++) {\r\n\t\t\t\tbefore[name][i](root_);\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\t// Running 'after' old page going to be removed\r\n\tvar afterEvent = function(name){\r\n\t\tif(self.currentPage.indexOf(name) === -1)\r\n\t\t\tself.currentPage.splice(self.currentPage.indexOf(name), 1);\r\n\r\n\t\tif(after[name]){\r\n\t\t\tfor (var i = 0; i < after[name].length; i++) {\r\n\t\t\t\tafter[name][i](root_);\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\tvar onEvent = {\r\n\t\t'loading':[],\r\n\t\t'loaded':[],\r\n\t\t'special':[],\r\n\t\t'error':[]\r\n\t};\r\n\tself.on = function(event, func){\r\n\t\tif(onEvent[event].indexOf(func) === -1)\r\n\t\t\tonEvent[event].push(func);\r\n\t}\r\n\r\n\tself.lazyViewPoint = {};\r\n\t/*\r\n\t\t{\r\n\t\t\toldURlPattern:{\r\n\t\t\t\tnewURLPattern:'.viewPoint'\r\n\t\t\t}\r\n\t\t}\r\n\t*/\r\n\tself.lazy = function(){\r\n\t\tif(!self.enabled) return;\r\n\r\n\t\t$('a[href]:not([onclick])').each(function(){\r\n\t\t\tvar url = this.href;\r\n\t\t\tif(url.indexOf('#') !== -1)\r\n\t\t\t\treturn;\r\n\r\n\t\t\tif(url.indexOf(window.location.origin) !== 0 && url.charAt(0) !== '/')\r\n\t\t\t\treturn; //Not current domain origin\r\n\r\n\t\t\t$(this).attr('onclick', 'return sf.router.load(this)');\r\n\t\t});\r\n\t}\r\n\r\n\tself.load = function(elem){\r\n\t\tif(!history.pushState || $(elem).attr('sf-router') == 'ignore')\r\n\t\t\treturn true;\r\n\r\n\t\treturn !self.goto(elem.href.replace(window.location.origin, ''));\r\n\t}\r\n\r\n\tvar RouterLoading = false;\r\n\tvar routingBack = false;\r\n\tvar routingError = false;\r\n\tself.goto = function(path, data, method){\r\n\t\tif(!method) method = 'GET';\r\n else method = method.toUpperCase();\r\n\r\n\t\tfor (var i = 0; i < onEvent['loading'].length; i++) {\r\n\t\t\tif(onEvent['loading'][i](path)) return;\r\n\t\t}\r\n\t\tvar oldPath = window.location.pathname;\r\n\t\tinitialized = false;\r\n\r\n\t\tif(RouterLoading) RouterLoading.abort();\r\n\t\tRouterLoading = $.ajax({\r\n\t\t\turl:window.location.origin + path,\r\n\t\t\tmethod:method,\r\n data:Object.assign(data, {\r\n _scarlets:'.dynamic.'\r\n }),\r\n\t\t\tsuccess:function(data){\r\n\t\t\t\tif(initialized) return;\r\n\t\t\t\tlazyRouting = true;\r\n\r\n\t\t\t\t// Run 'loaded' event\r\n\t\t\t\tRouterLoading = false;\r\n\r\n\t\t\t\t// Find special data\r\n\t\t\t\tvar regex = RegExp(''+sf.regex.avoidQuotes, 'gm');\r\n\t\t\t\tvar special = regex.exec(data);\r\n\t\t\t\tif(special && special.length !== 1){\r\n\t\t\t\t\tspecial = special[1].split('--|&>').join('-->');\r\n\t\t\t\t\tspecial = JSON.parse(special);\r\n\r\n\t\t\t\t\tif(!$.isEmptyObject(special)){\r\n\t\t\t\t\t\tfor (var i = 0; i < onEvent['special'].length; i++) {\r\n\t\t\t\t\t\t\tif(onEvent['special'][i](special)) return;\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\r\n\t\t\t\tvar DOMReference = false;\r\n\t\t\t\tvar foundAction = function(ref){\r\n\t\t\t\t\tDOMReference = $(ref);\r\n\r\n\t\t\t\t\t// Run 'after' event for old page view\r\n\t\t\t\t\tafterEvent($('[sf-page]', DOMReference[0]).attr('sf-page'));\r\n\r\n\t\t\t\t\t// Redefine title if exist\r\n\t\t\t\t\tif(special && special.title)\r\n\t\t\t\t\t\t$('head title').html(special.title);\r\n\r\n\t\t\t\t\tfound = true;\r\n\t\t\t\t};\r\n\r\n\t\t\t\tvar found = false;\r\n\t\t\t\tfor(var oldURL in self.lazyViewPoint){\r\n\t\t\t\t\tif(currentRouterURL.indexOf(oldURL) !== -1){\r\n\t\t\t\t\t\tfor(var newURL in self.lazyViewPoint[oldURL]){\r\n\t\t\t\t\t\t\tif(currentRouterURL.indexOf(oldURL) !== -1){\r\n\t\t\t\t\t\t\t\tfoundAction(self.lazyViewPoint[oldURL][newURL]);\r\n\t\t\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t}\r\n\t\t\t\t\tif(found) break;\r\n\t\t\t\t}\r\n\r\n\t\t\t\t// When the view point was not found\r\n\t\t\t\tif(!found){\r\n\t\t\t\t\t// Use fallback if exist\r\n\t\t\t\t\tif(sf.router.lazyViewPoint[\"@default\"])\r\n\t\t\t\t\t\tfoundAction(sf.router.lazyViewPoint[\"@default\"]);\r\n\r\n\t\t\t\t\tif(!found){\r\n\t\t\t\t\t\tfor (var i = 0; i < onEvent['error'].length; i++) {\r\n\t\t\t\t\t\t\tonEvent['error'][i]('sf.router.lazyViewPoint[\"'+oldURL+'\"][\"'+newURL+'\"] was not found');\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\r\n\t\t\t\t// Reinit lazy router\r\n\t\t\t\tself.lazy();\r\n\r\n\t\t\t\t// Run 'before' event for new page view\r\n\t\t\t\tif(!DOMReference) DOMReference = $(document.body);\r\n\t\t\t\tif(self.pauseRenderOnTransition)\r\n\t\t\t\t\tself.pauseRenderOnTransition.css('display', 'none');\r\n\r\n\t\t\t\t// Let page script running first, then update the data binding\r\n\t\t\t\tDOMReference.html(data);\r\n\r\n\t\t\t\t// Parse the DOM data binding\r\n\t\t\t\tsf.model.init(DOMReference);\r\n\r\n\t\t\t\t// Init template to model binding\r\n\t\t\t\t$('[sf-page]', DOMReference[0]).each(function(){\r\n\t\t\t\t\tif(this.attributes['sf-page'])\r\n\t\t\t\t\t\tbeforeEvent(this.attributes['sf-page'].value);\r\n\t\t\t\t});\r\n\r\n\t\t\t\tif(self.pauseRenderOnTransition)\r\n\t\t\t\t\tself.pauseRenderOnTransition.css('display', '');\r\n\r\n\t\t\t\trouterLoaded(currentRouterURL, path, DOMReference);\r\n\r\n\t\t\t\tinitialized = true;\r\n\t\t\t\tlazyRouting = false;\r\n\r\n\t\t\t\tcurrentRouterURL = path;\r\n\t\t\t\troutingError = false;\r\n\t\t\t},\r\n\t\t\terror:function(xhr, data){\r\n\t\t\t\troutingError = true;\r\n\t\t\t\tif(xhr.aborted) return;\r\n\r\n\t\t\t\tRouterLoading = false;\r\n\t\t\t\tfor (var i = 0; i < onEvent['error'].length; i++) {\r\n\t\t\t\t\tonEvent['error'][i](xhr.status, data);\r\n\t\t\t\t}\r\n\r\n\t\t\t\t// Back on error\r\n\t\t\t\twindow.history.back();\r\n\t\t\t}\r\n\t\t});\r\n\r\n\t\tif(!routingBack)\r\n\t\t\twindow.history.pushState(null, \"\", path);\r\n\r\n\t\troutingBack = false;\r\n\t\treturn true;\r\n\t}\r\n\r\n\t// Trigger loaded event\r\n\tfunction routerLoaded(currentRouterURL, path, data){\r\n\t\tfor (var i = 0; i < onEvent['loaded'].length; i++) {\r\n\t\t\tonEvent['loaded'][i](currentRouterURL, path, data);\r\n\t\t}\r\n\t}\r\n};"]} \ No newline at end of file +{"version":3,"sources":["sf-a_init.js","sf-controller.js","sf-loader.js","sf-model.js","sf-router.js"],"names":["sf","_sf","apply","this","arguments","toString","constructor","Function","loader","onFinish","regex","avoidQuotes","strictVar","$","fn","setTimeout","console","clear","error","extend","obj","func","animateCSS","animationName","callback","duration","self","animationEnd","animation","OAnimation","MozAnimation","WebkitAnimation","t","undefined","style","css","addClass","one","removeClass","controller","pending","active","for","name","modelScope","element","elem","model","modelName","bindedList","attr","parents","root","bindedListIndex","prevAll","length","attributes","value","run","listenSFClick","e","target","script","eq","_modelScope","modelKeys","scopeMask","RegExp","replace","full","matched","split","method","method_","eval","shift","join","pop","root_","scope","DOMWasLoaded","init","parent","document","body","each","on","loadedContent","totalContent","whenDOMLoaded","whenProgress","indexOf","push","onProgress","f","i","removeAttribute","list","splice","temp","getElementsByTagName","innerHTML","js","ajax","url","dataType","cache","complete","everythingLoaded","setInterval","test","readyState","clearInterval","router","prototype","setAttribute","bindingEnabled","processingElement","bracketMatch","chackValidFunctionCall","allowedFunction","localEval","script_","_model_","_content_","preventExecution","check","exec","trim","_result_","log","outerHTML","_evaled_","index","tagName","modelRef","keys","Object","clearElementData","current","cleanData","dataParser","html","mask","runEval","itemMask","actual","slice","charCodeAt","uniqueDataParser","take","passVar","currentIndex","strDeclare","firstTime","key","JSON","stringify","VarPass_","VarPass","s1","obtained","forEach","val","bindArray","propertyName","targetNode","oldArray","editProperty","processElement","update","insertBefore","insertAfter","exist","find","item","all","first","before","prepend","remove","create","currentRemoved","startRemove","propertyProxy","subject","defineProperty","enumerable","configurable","lastLength","Array","real","limit","foundChanges","compareObject","obj1","obj2","loopParser","content","returns","items","get","set","softRefresh","bindInput","whichVar","removeAttr","keyup","bindObject","alreadyInitialized","DOMNodeRemoved","removeBinding","parsePreprocess","queuePreprocess","after","next","data","append","MutationObserver","observe","records","a","removedNodes","nodeName","childList","subtree","addEventListener","modelNames","attrs","id","bindRef","ref","object","writable","isEmptyObject","created","dcBracket","which","Node","Date","now","attrName","callbackFunction","getOwnPropertyDescriptor","objValue","bindElement","brackets","s2","childNodes","excludes","toUpperCase","currentNode","nodeType","concat","nodeValue","parentNode","nodes","loading","enabled","pauseRenderOnTransition","currentPage","initialized","currentRouterURL","lazy","beforeEvent","window","location","pathname","enable","status","event","routingError","routingBack","goto","onEvent","loaded","special","lazyViewPoint","href","origin","charAt","load","history","pushState","RouterLoading","path","abort","assign","_scarlets","success","parse","DOMReference","foundAction","afterEvent","title","found","oldURL","newURL","routerLoaded","xhr","aborted","back"],"mappings":"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","file":"scarletsframe.min.js","sourcesContent":["sf = function(){\r\n\tif(arguments[0].constructor === Function){\r\n\t\treturn sf.loader.onFinish.apply(null, arguments);\r\n\t}\r\n};\r\n\r\nsf.regex = {\r\n\t// ToDo: Need help to skip escaped quote\r\n\tavoidQuotes:'(?=(?:[^\"\\']*(?:\\'|\")[^\"\\']*(?:\\'|\"))*[^\"\\']*$)',\r\n\tstrictVar:'(?=\\\\b[^.]|^|\\\\n| +|\\\\t|\\\\W )'\r\n};\r\n\r\nif(typeof $ === 'undefined' || !$.fn){\r\n\tsetTimeout(function(){\r\n\t\tconsole.clear();\r\n\t\tconsole.error(\"Please load jQuery before ScarletsFrame\");\r\n\t}, 1000);\r\n}\r\n\r\nif(!$.fn.extend){\r\n\t$.fn.extend = function(obj){\r\n\t\tfor(var func in obj){\r\n\t\t\t$.fn[func] = obj[func];\r\n\t\t}\r\n\t}\r\n}\r\n\r\n// Add animate.css feature on jQuery\r\n$.fn.extend({\r\n animateCSS: function(animationName, callback, duration) {\r\n\tvar self = this;\r\n\tvar animationEnd = {\r\n\t\tanimation: 'animationend',\r\n\t\tOAnimation: 'oAnimationEnd',\r\n\t\tMozAnimation: 'mozAnimationEnd',\r\n\t\tWebkitAnimation: 'webkitAnimationEnd',\r\n\t};\r\n\r\n\tfor (var t in animationEnd)\r\n\t\tif (self[0].style[t] !== undefined){\r\n\t\t\tanimationEnd = animationEnd[t];\r\n\t\t\tbreak;\r\n\t\t}\r\n\r\n\tif(duration)\r\n\t\tself.css('-webkit-animation-duration', duration+'s').css('animation-duration', duration+'s');\r\n\r\n\tself.addClass('animated ' + animationName).one(animationEnd, function(){\r\n\t\tsetTimeout(function(){\r\n\t\t\t$(self).removeClass('animated ' + animationName);\r\n\t\t}, 1);\r\n\r\n\t\tif(duration)\r\n\t\t\t$(self).css('-webkit-animation-duration', '').css('animation-duration', '');\r\n\r\n\t\tif (typeof callback === 'function') callback();\r\n\t});\r\n\r\n\treturn self;\r\n }\r\n});","// DOM Controller on loaded app\r\nsf.controller = new function(){\r\n\tvar self = this;\r\n\tself.pending = {};\r\n\tself.active = {};\r\n\r\n\tself.for = function(name, func){\r\n\t\tself.pending[name] = func;\r\n\t}\r\n\r\n\tself.modelScope = function(element, func){\r\n\t\tvar elem = $(element);\r\n\t\tvar model = sf.controller.modelName(element);\r\n\r\n\t\tif(!model)\r\n\t\t\tthrow 'model or controller was not found';\r\n\r\n\t\tvar bindedList = elem.attr('[sf-bind-list]');\r\n\t\tif(!bindedList)\r\n\t\t\tbindedList = elem.parents('[sf-bind-list]').attr('sf-bind-list');\r\n\r\n\t\tif(!bindedList){\r\n\t\t\tif(func) return func(sf.model.root[model], -1);\r\n\t\t\telse return sf.model.root[model];\r\n\t\t}\r\n\r\n\t\t// Find index\r\n\t\tvar bindedListIndex = 0;\r\n\t\tif(bindedList)\r\n\t\t\tbindedListIndex = elem.parents('[sf-bind-list]').prevAll('[sf-bind-list]').length;\r\n\r\n\t\tif(func) return func(sf.model.root[model][bindedList], bindedListIndex);\r\n\t\telse return sf.model.root[model][bindedList][bindedListIndex];\r\n\t}\r\n\r\n\tself.modelName = function(element){\r\n\t\tvar name = undefined;\r\n\t\tif(element.attributes['sf-controller'])\r\n\t\t\tname = element.attributes['sf-controller'].value;\r\n\t\telse\r\n\t\t\tname = $(element).parents('[sf-controller]').attr('sf-controller');\r\n\r\n\t\t// Initialize it first\r\n\t\tif(name !== undefined && !self.active[name])\r\n\t\t\tself.run(name);\r\n\r\n\t\treturn name;\r\n\t}\r\n\r\n\tvar listenSFClick = function(e){\r\n\t\tvar element = $(e.target);\r\n\t\tvar script = element.attr('sf-click');\r\n\r\n\t\tif(!script){\r\n\t\t\telement = element.parents('[sf-click]').eq(0);\r\n\t\t\tscript = element.attr('sf-click');\r\n\t\t}\r\n\r\n\t\tvar model = element.parents('[sf-controller]').attr('sf-controller');\r\n\r\n\t\tif(!sf.model.root[model])\r\n\t\t\tthrow \"Couldn't find model for \"+model+\" that was called from sf-click\";\r\n\r\n\t\tvar _modelScope = sf.model.root[model];\r\n\r\n\t\tvar modelKeys = sf.model.modelKeys(_modelScope);\r\n\t\tvar scopeMask = RegExp(sf.regex.strictVar+'('+modelKeys+')'+sf.regex.avoidQuotes+'\\\\b', 'g');\r\n\r\n\t\tscript = script.replace(scopeMask, function(full, matched){\r\n\t\t\treturn '_modelScope.'+matched;\r\n\t\t});\r\n\r\n\t\tscript = script.split('(');\r\n\r\n\t\tvar method = script[0];\r\n\t\tvar method_ = method;\r\n\r\n\t\t// Get method reference\r\n\t\ttry{\r\n\t\t\tmethod = eval(method);\r\n\t\t} catch(e) {\r\n\t\t\tmethod = false;\r\n\t\t}\r\n\r\n\t\tif(!method){\r\n\t\t\tconsole.error(\"Error on sf-click for model: \" + model + ' [Cannot find '+method_+']\\n', e.target);\r\n\t\t\treturn;\r\n\t\t}\r\n\r\n\t\t// Take the argument list\r\n\t\tscript.shift();\r\n\t\tscript = script.join('(');\r\n\t\tscript = script.split(')');\r\n\t\tscript.pop();\r\n\t\tscript = script.join('(');\r\n\r\n\t\t// Turn argument as array\r\n\t\tif(script.length !== 0)\r\n\t\t\tscript = eval('['+script+']');\r\n\t\tif(!script)\r\n\t\t\tscript = [];\r\n\r\n\t\ttry{\r\n\t\t\tmethod.apply(element[0], script);\r\n\t\t} catch(e) {\r\n\t\t\tconsole.error(\"Error on sf-click for model: \" + model + '\\n', e.target, '\\n', e);\r\n\t\t}\r\n\t}\r\n\r\n\tvar root_ = function(scope){\r\n\t\tif(!sf.model.root[scope])\r\n\t\t\tsf.model.root[scope] = {};\r\n\r\n\t\tif(!sf.model.root[scope])\r\n\t\t\tsf.controller.run(scope);\r\n\t\t\r\n\t\treturn sf.model.root[scope];\r\n\t}\r\n\t// Deprecated\r\n\tself.run = function(name, func){\r\n\t\tif(!sf.loader.DOMWasLoaded)\r\n\t\t\treturn sf(function(){\r\n\t\t\t\tself.run(name, func);\r\n\t\t\t});\r\n\r\n\t\tif(self.pending[name]){\r\n\t\t\tif(!sf.model.root[name])\r\n\t\t\t\tsf.model.root[name] = {};\r\n\t\t\r\n\t\t\tself.pending[name](sf.model.root[name], root_);\r\n\t\t\tself.active[name] = true;\r\n\t\t\tdelete self.pending[name];\r\n\t\t}\r\n\r\n\t\tif(func)\r\n\t\t\tfunc(sf.model.root[name], root_);\r\n\t}\r\n\r\n\tself.init = function(parent){\r\n\t\tif(!sf.loader.DOMWasLoaded)\r\n\t\t\treturn sf(function(){\r\n\t\t\t\tself.init(name);\r\n\t\t\t});\r\n\r\n\t\t$('[sf-controller]', parent ? $(parent)[0] : document.body).each(function(){\r\n\t\t\tself.run(this.attributes['sf-controller'].value);\r\n\t\t});\r\n\t}\r\n\r\n\t$(function(){\r\n\t\t// Listen to sf-click\r\n\t\t$('body').on('click', '[sf-controller] [sf-click]', listenSFClick);\r\n\t});\r\n}","sf.loader = new function(){\r\n\tvar self = this;\r\n\tself.loadedContent = 0;\r\n\tself.totalContent = 0;\r\n\tself.DOMWasLoaded = false;\r\n\r\n\tvar whenDOMLoaded = [];\r\n\tvar whenProgress = [];\r\n\r\n\t// Make event listener\r\n\tself.onFinish = function(func){\r\n\t\tif(self.DOMWasLoaded) return func();\r\n\t\tif(whenDOMLoaded.indexOf(func) !== -1) return;\r\n\t\twhenDOMLoaded.push(func);\r\n\t}\r\n\tself.onProgress = function(func){\r\n\t\tif(self.DOMWasLoaded) return func(self.loadedContent, self.totalContent);\r\n\t\tif(whenProgress.indexOf(func) !== -1) return;\r\n\t\twhenProgress.push(func);\r\n\t}\r\n\r\n\tself.f = function(element){\r\n\t\tself.loadedContent++;\r\n\t\tfor (var i = 0; i < whenProgress.length; i++) {\r\n\t\t\twhenProgress[i](self.loadedContent, self.totalContent);\r\n\t\t}\r\n\t\tif(element && element.removeAttribute) element.removeAttribute('onload');\r\n\t}\r\n\r\n\tself.css = function(list){\r\n\t\tif(self.DOMWasLoaded){\r\n\t\t\t// check if some list was loaded\r\n\t\t\tfor (var i = list.length - 1; i >= 0; i--) {\r\n\t\t\t\tif($('link[href*=\"'+list[i]+'\"]').length!==0)\r\n\t\t\t\t\tlist.splice(i, 1);\r\n\t\t\t}\r\n\t\t\tif(list.length === 0) return;\r\n\t\t}\r\n\t\tself.totalContent = self.totalContent + list.length;\r\n\t\tvar temp = '';\r\n\t\tfor(var i = 0; i < list.length; i++){\r\n\t\t\ttemp += '';\r\n\t\t}\r\n\r\n\t\t$(function(){\r\n\t\t\tdocument.getElementsByTagName('body')[0].innerHTML += temp;\r\n\t\t});\r\n\t}\r\n\r\n\tself.js = function(list){\r\n\t\tif(self.DOMWasLoaded){\r\n\t\t\t// check if some list was loaded\r\n\t\t\tfor (var i = list.length - 1; i >= 0; i--) {\r\n\t\t\t\tif($('script[src*=\"'+list[i]+'\"]').length!==0)\r\n\t\t\t\t\tlist.splice(i, 1);\r\n\t\t\t}\r\n\t\t\tif(list.length === 0) return;\r\n\t\t}\r\n\t\tself.totalContent = self.totalContent + list.length;\r\n\t\tfor(var i = 0; i < list.length; i++){\r\n\t\t\t$.ajax({\r\n\t\t\t url: list[i],\r\n\t\t\t dataType: \"script\",\r\n\t\t\t cache: true,\r\n\t\t\t complete: sf.loader.f\r\n\t\t\t});\r\n\t\t}\r\n\t}\r\n\r\n\tsetTimeout(function(){\r\n\t\tif(self.totalContent === 0)\r\n\t\t\tself.loadedContent = self.totalContent = 1;\r\n\t}, 10000);\r\n\tvar everythingLoaded = setInterval(function() {\r\n\tif (/loaded|complete/.test(document.readyState)) {\r\n\t\tif(self.loadedContent < self.totalContent || self.loadedContent === 0)\r\n\t\t\treturn;\r\n\r\n\t\tclearInterval(everythingLoaded);\r\n\t\tself.DOMWasLoaded = true;\r\n\t\tfor (var i = 0; i < whenDOMLoaded.length; i++) {\r\n\t\t\ttry{\r\n\t\t\t\twhenDOMLoaded[i]();\r\n\t\t\t} catch(e){\r\n\t\t\t\tconsole.error(e);\r\n\t\t\t}\r\n\t\t}\r\n\t\twhenProgress.splice(0);\r\n\t\twhenDOMLoaded.splice(0);\r\n\r\n\t\t// Last init\r\n\t\tsf.controller.init();\r\n\t\tsf.model.init();\r\n\t\tsf.router.init();\r\n\t}\r\n\t}, 100);\r\n};\r\nsf.prototype.constructor = sf.loader.onFinish;\r\n\r\n// Find images\r\n$(function(){\r\n\t$('img:not(onload)[src]').each(function(){\r\n\t\tsf.loader.totalContent++;\r\n\t\tthis.setAttribute('onload', \"sf.loader.f(this)\");\r\n\t});\r\n});","// Data save and HTML content binding\r\nsf.model = new function(){\r\n\tvar self = this;\r\n\tvar bindingEnabled = false;\r\n\tself.root = {};\r\n\tvar root_ = function(scope){\r\n\t\tif(!self.root[scope])\r\n\t\t\tself.root[scope] = {};\r\n\r\n\t\tif(sf.controller.pending[scope])\r\n\t\t\tsf.controller.run(scope);\r\n\r\n\t\treturn self.root[scope];\r\n\t};\r\n\r\n\tvar processingElement = null;\r\n\r\n\tvar bracketMatch = RegExp('([\\\\w.]*?[\\\\S\\\\s])\\\\('+sf.regex.avoidQuotes, 'g');\r\n\tvar chackValidFunctionCall = /[a-zA-Z0-9 \\]\\$\\)]/;\r\n\tvar allowedFunction = [':', 'for', 'if', 'while', '_content_.take', 'console.log'];\r\n\tvar localEval = function(script_, _model_, _modelScope, _content_){\r\n\t\tvar script = script_;\r\n\t\tscript_ = script_.split('\\\\\"').join('\\\\$%*').split(\"\\\\'\").join('\\\\%$*'); // ToDo: Escape\r\n\t\tscript_ = script_.split('._modelScope').join('');\r\n\t\tscript_ = script_.split('._model_').join('');\r\n\r\n\t\t// Prevent vulnerability by remove bracket to avoid a function call\r\n\t\tvar preventExecution = false;\r\n\t\tvar check = null;\r\n\t\twhile((check = bracketMatch.exec(script_)) !== null){\r\n\t\t\tcheck[1] = check[1].trim();\r\n\r\n\t\t\tif(allowedFunction.indexOf(check[1]) === -1 &&\r\n\t\t\t\tcheck[1].split('.')[0] !== '_modelScope' &&\r\n\t\t\t\tchackValidFunctionCall.test(check[1][check[1].length-1])\r\n\t\t\t){\r\n\t\t\t\tpreventExecution = check[1];\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t}\r\n\t\t\r\n\t\tvar _result_ = '';\r\n\t\tscript_ = script_.split('\\\\$%*').join('\\\\\"').split('\\\\%$*').join(\"\\\\'\"); // ToDo: Unescape\r\n\t\tif(preventExecution){\r\n\t\t\tconsole.error(\"Trying to executing unrecognized function (\"+preventExecution+\")\");\r\n\t\t\tconsole.log($(processingElement.outerHTML)[0]);\r\n\t\t\tconsole.log(script_);\r\n\t\t\treturn '';\r\n\t\t}\r\n\t\ttry{\r\n\t\t\tvar _evaled_ = eval(script_);\r\n\t\t} catch(e){\r\n\t\t\tconsole.error(e);\r\n\t\t\tconsole.log(script_);\r\n\t\t\tconsole.log($(processingElement.outerHTML)[0]);\r\n\t\t\treturn '';\r\n\t\t}\r\n\r\n\t\tif(_result_ !== '') return _result_;\r\n\t\treturn _evaled_;\r\n\t}\r\n\r\n\tself.index = function(element){\r\n\t\treturn $(element).prevAll(element.tagName).length;\r\n\t}\r\n\r\n\tself.for = function(name, func){\r\n\t\tif(!sf.loader.DOMWasLoaded)\r\n\t\t\treturn sf(function(){\r\n\t\t\t\tself.for(name, func);\r\n\t\t\t});\r\n\t\t\r\n\t\tfunc(root_(name), root_);\r\n\t}\r\n\r\n\tself.modelKeys = function(modelRef){\r\n\t\tvar keys = Object.keys(modelRef);\r\n\t\tfor (var i = keys.length - 1; i >= 0; i--) {\r\n\t\t\tif(keys[i].indexOf('$') !== -1)\r\n\t\t\t\tkeys.splice(i, 1);\r\n\t\t}\r\n\t\treturn keys.join('|');\r\n\t}\r\n\r\n\tvar clearElementData = function(current){\r\n\t\t// Clean associated data on jQuery\r\n\t\tif($ && $.cleanData)\r\n\t\t\t$.cleanData(current.getElementsByTagName(\"*\"));\r\n\r\n\t\tcurrent.innerHTML = '';\r\n\t\tfor (var i = 0; i < current.attributes.length; i++) {\r\n\t\t\tvar name = current.attributes[i].name;\r\n\t\t\tif(name !== 'sf-bind-list')\r\n\t\t\t\tcurrent.removeAttribute(name);\r\n\t\t}\r\n\t\tcurrent.setAttribute('style', 'display:none');\r\n\t}\r\n\r\n\t// For contributor of this library\r\n\t// Please be careful when you're passing the eval argument\r\n\tvar dataParser = function(html, _model_, mask, scope, runEval){\r\n\t\tvar _modelScope = self.root[scope];\r\n\t\tif(!runEval) runEval = '';\r\n\r\n\t\t// Don't match text inside quote, or object keys\r\n\t\tvar scopeMask = RegExp(sf.regex.strictVar+'('+self.modelKeys(_modelScope)+')'+sf.regex.avoidQuotes+'\\\\b', 'g');\r\n\r\n\t\tif(mask)\r\n\t\t\tvar itemMask = RegExp(sf.regex.strictVar+mask+'\\\\.'+sf.regex.avoidQuotes+'\\\\b', 'g');\r\n\r\n\t\tbindingEnabled = true;\r\n\r\n\t\treturn html.replace(/{{([^@][\\s\\S]*?)}}/g, function(actual, temp){\r\n\t\t\t// ToDo: The regex should be optimized to avoid match in a quote (but not escaped quote)\r\n\t\t\ttemp = temp.split('\\\\\"').join('\\\\$%*').split(\"\\\\'\").join('\\\\%$*'); // ToDo: Escape\r\n\r\n\t\t\t// Mask item variable\r\n\t\t\tif(mask)\r\n\t\t\t\ttemp = temp.replace(itemMask, function(matched){\r\n\t\t\t\t\treturn '_model_.'+matched[0].slice(1);\r\n\t\t\t\t});\r\n\r\n\t\t\t// Mask model for variable\r\n\t\t\ttemp = temp.replace(scopeMask, function(full, matched){\r\n\t\t\t\treturn '_modelScope.'+matched;\r\n\t\t\t});\r\n\r\n\t\t\ttemp = temp.split('\\\\$%*').join('\\\\\"').split('\\\\%$*').join(\"\\\\'\"); // ToDo: Unescape\r\n\r\n\t\t\t// Evaluate\r\n\t\t\ttemp = '' + localEval.apply(self.root, [runEval + temp, _model_, _modelScope]);\r\n\r\n\t\t\treturn temp.replace(/[\\u00A0-\\u9999<>\\&]/gim, function(i) {\r\n\t\t return '&#'+i.charCodeAt(0)+';';\r\n\t\t });\r\n\t\t});\r\n\t}\r\n\r\n\tvar uniqueDataParser = function(html, _model_, mask, scope){\r\n\t\t// Get prepared html content\r\n\t\tvar _content_ = {\r\n\t\t\tlength:0,\r\n\t\t\ttake:function(passVar, currentIndex){\r\n\t\t\t\tif(!passVar)\r\n\t\t\t\t\treturn dataParser(this[currentIndex], _model_, mask, scope);\r\n\r\n\t\t\t\tvar strDeclare = '\"use strict\";var ';\r\n\t\t\t\tvar firstTime = true;\r\n\r\n\t\t\t\tfor(var key in passVar){\r\n\t\t\t\t\tif(typeof passVar[key] === 'string')\r\n\t\t\t\t\t\tpassVar[key] = '\"'+passVar[key].split('\"').join('\\\\\"')+'\"';\r\n\t\t\t\t\telse if(typeof passVar[key] === 'object')\r\n\t\t\t\t\t\tpassVar[key] = JSON.stringify(passVar[key]);\r\n\r\n\t\t\t\t\tif(!firstTime)\r\n\t\t\t\t\t\tstrDeclare += ',';\r\n\r\n\t\t\t\t\tstrDeclare += key + ' = ' + passVar[key];\r\n\t\t\t\t\tfirstTime = false;\r\n\t\t\t\t}\r\n\r\n\t\t\t\t// Disable function call for addional security eval protection\r\n\t\t\t\tstrDeclare = strDeclare.split('(').join('').split(')').join('');\r\n\r\n\t\t\t\treturn dataParser(this[currentIndex], _model_, mask, scope, strDeclare + ';');\r\n\t\t\t}\r\n\t\t};\r\n\r\n\t\thtml = html.replace(/{\\[([\\s\\S]*?)\\]}/g, function(full, matched){\r\n\t\t\t_content_[_content_.length] = matched;\r\n\t\t\t_content_.length++;\r\n\t\t\treturn '_result_ += _content_.take(&VarPass&, '+(_content_.length - 1)+');';\r\n\t\t});\r\n\r\n\t\tvar _modelScope = self.root[scope];\r\n\r\n\t\t// Don't match text inside quote, or object keys\r\n\t\tvar scopeMask = RegExp(sf.regex.strictVar+'('+self.modelKeys(_modelScope)+')'+sf.regex.avoidQuotes+'\\\\b', 'g');\r\n\r\n\t\tif(mask)\r\n\t\t\tvar itemMask = RegExp(sf.regex.strictVar+mask+'\\\\.'+sf.regex.avoidQuotes+'\\\\b', 'g');\r\n\r\n\t\treturn html.replace(/{{(@[\\s\\S]*?)}}/g, function(actual, temp){\r\n\t\t\t// ToDo: The regex should be optimized to avoid match in a quote (but not escaped quote)\r\n\t\t\ttemp = temp.split('\\\\\"').join('\\\\$%*').split(\"\\\\'\").join('\\\\%$*'); // ToDo: Escape\r\n\r\n\t\t\t// Mask item variable\r\n\t\t\tif(mask)\r\n\t\t\t\ttemp = temp.replace(itemMask, function(matched){\r\n\t\t\t\t\treturn '_model_.'+matched[0].slice(1);\r\n\t\t\t\t});\r\n\r\n\t\t\t// Mask model for variable\r\n\t\t\ttemp = temp.replace(scopeMask, function(full, matched){\r\n\t\t\t\treturn '_modelScope.'+matched;\r\n\t\t\t});\r\n\t\t\ttemp = temp.split('\\\\$%*').join('\\\\\"').split('\\\\%$*').join(\"\\\\'\"); // ToDo: Unescape\r\n\r\n\t\t\tvar result = '';\r\n\t\t\tvar check = false;\r\n\r\n\t\t\tcheck = temp.split('@if ');\r\n\t\t\tif(check.length != 1){\r\n\t\t\t\tcheck = check[1].split(':');\r\n\t\t\t\r\n\t\t\t\t// If condition was meet\r\n\t\t\t\tif(localEval.apply(self.root, [check[0], _model_, _modelScope, _content_])){\r\n\t\t\t\t\tcheck.shift();\r\n\t\t\t\t\treturn check.join(':');\r\n\t\t\t\t}\r\n\t\t\t}\r\n\r\n\t\t\t// Get defined variables\r\n\t\t\tvar VarPass_ = /(var|let)([\\w,\\s]+)(?=\\s(?==|in|of))/g;\r\n\t\t\tvar VarPass = [];\r\n\t\t\tvar s1 = null;\r\n\t\t\twhile((s1 = VarPass_.exec(temp)) !== null){\r\n\t\t\t\tVarPass.push(s1[2]);\r\n\t\t\t}\r\n\t\t\tif(VarPass.length){\r\n\t\t\t\tvar obtained = [];\r\n\t\t\t\tfor (var i = 0; i < VarPass.length; i++) {\r\n\t\t\t\t\tVarPass[i].replace(/([\\n\\t\\r]| )+/g, '').split(',').forEach(function(val){\r\n\t\t\t\t\t\tobtained.push(val);\r\n\t\t\t\t\t});\r\n\t\t\t\t};\r\n\t\t\t\tVarPass = obtained;\r\n\t\t\t\tfor (var i = 0; i < VarPass.length; i++) {\r\n\t\t\t\t\tVarPass[i] += ':(typeof '+VarPass[i]+'!=\"undefined\"?'+VarPass[i]+':undefined)';\r\n\t\t\t\t}\r\n\t\t\t\tVarPass = '{'+VarPass.join(',')+'}';\r\n\t\t\t\ttemp = temp.split('&VarPass&').join(VarPass);\r\n\t\t\t}\r\n\t\t\ttemp = temp.split('&VarPass&').join('{}'); \r\n\r\n\t\t\t// Warning! Avoid unencoded user inputted content\r\n\t\t\t// And always check/remove closing ']}' in user content\r\n\t\t\t// Any function call will be removed for addional security\r\n\t\t\tcheck = temp.split('@exec');\r\n\t\t\tif(check.length != 1){\r\n\t\t\t\tcheck = check[1].split('<').join('<').split('>').join('>').split('&').join('&');\r\n\r\n\t\t\t\ttemp = localEval.apply(self.root, [check, _model_, _modelScope, _content_]);\r\n\t\t\t\treturn temp;\r\n\t\t\t}\r\n\t\t\treturn '';\r\n\t\t});\r\n\t}\r\n\r\n\tvar bindArray = function(html, list, mask, modelName, propertyName, targetNode){\r\n\t\tvar oldArray = list.slice(0);\r\n\t\tvar editProperty = ['pop', 'push', 'splice', 'shift', 'unshift', 'softRefresh', 'hardRefresh'];\r\n\t\tvar processElement = function(index, update, insertBefore, insertAfter){\r\n\t\t\tvar exist = $(\"[sf-controller='\"+modelName+\"']\", targetNode);\r\n\t\t\tif(exist.length === 0) return;\r\n\r\n\t\t\texist = exist.find(\"[sf-bind-list='\"+propertyName+\"']\");\r\n\r\n\t\t\tvar callback = false;\r\n\t\t\tif(self.root[modelName]['on$'+propertyName])\r\n\t\t\t\tcallback = self.root[modelName]['on$'+propertyName];\r\n\r\n\t\t\t// Hard refresh\r\n\t\t\tif(index === -1){\r\n\t\t\t\tvar item = self.root[modelName][propertyName];\r\n\t\t\t\tvar all = '';\r\n\t\t\t\tfor (var i = 0; i < item.length; i++) {\r\n\t\t\t\t\tvar temp = uniqueDataParser(html, item[i], mask, modelName);\r\n\t\t\t\t\tall += dataParser(temp, item[i], mask, modelName);\r\n\t\t\t\t}\r\n\r\n\t\t\t\t// Get first element\r\n\t\t\t\tvar first = exist.eq(0).before();\r\n\t\t\t\tif(first[0] === exist[0])\r\n\t\t\t\t\texist.parent().prepend(all);\r\n\t\t\t\telse\r\n\t\t\t\t\t$(all).insertAfter(first);\r\n\t\t\t\texist.remove();\r\n\t\t\t\t\r\n\t\t\t\treturn;\r\n\t\t\t}\r\n\r\n\t\t\t// Remove\r\n\t\t\tif(!update){\r\n\t\t\t\tif(exist[index]){\r\n\t\t\t\t\tvar currentRemoved = false;\r\n\t\t\t\t\tvar startRemove = function(){\r\n\t\t\t\t\t\tif(currentRemoved) return;\r\n\t\t\t\t\t\tcurrentRemoved = true;\r\n\r\n\t\t\t\t\t\tif(exist.length <= 1)\r\n\t\t\t\t\t\t\treturn clearElementData(exist[index]);\r\n\r\n\t\t\t\t\t\texist[index].remove();\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t\tif(callback.remove){\r\n\t\t\t\t\t\t// Auto remove if return false\r\n\t\t\t\t\t\tif(!callback.remove(exist[index], startRemove))\r\n\t\t\t\t\t\t\tsetTimeout(startRemove, 800);\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t\t// Auto remove if no callback\r\n\t\t\t\t\telse startRemove();\r\n\t\t\t\t}\r\n\t\t\t\treturn;\r\n\t\t\t}\r\n\r\n\t\t\t// Create or update\r\n\t\t\tvar item = self.root[modelName][propertyName][index];\r\n\r\n\t\t\tvar temp = uniqueDataParser(html, item, mask, modelName);\r\n\t\t\ttemp = dataParser(temp, item, mask, modelName);\r\n\t\t\ttemp = $(temp);\r\n\r\n\t\t\t// Create\r\n\t\t\tif(!exist[index] || insertAfter){\r\n\t\t\t\tif(callback.create)\r\n\t\t\t\t\tcallback.create(temp[0]);\r\n\r\n\t\t\t\ttemp.insertAfter(exist[index !== 0 ? index - 1 : (exist.length - 1)]);\r\n\t\t\t}\r\n\r\n\t\t\telse{\r\n\t\t\t\t// Create\r\n\t\t\t\tif(insertBefore){\r\n\t\t\t\t\tif(callback.create)\r\n\t\t\t\t\t\tcallback.create(temp[0]);\r\n\r\n\t\t\t\t\ttemp.insertBefore(exist[0]);\r\n\t\t\t\t}\r\n\r\n\t\t\t\t// Update\r\n\t\t\t\telse{\r\n\t\t\t\t\tif(callback.update)\r\n\t\t\t\t\t\tcallback.update(temp[0]);\r\n\r\n\t\t\t\t\t// Clean associated data on jQuery\r\n\t\t\t\t\tif($ && $.cleanData){\r\n\t\t\t\t\t\t$.cleanData(exist[index].getElementsByTagName(\"*\"));\r\n\t\t\t\t\t\t$.cleanData(exist[index]);\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t\texist[index].outerHTML = temp[0].outerHTML;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t\tvar propertyProxy = function(subject, name){\r\n\t\t\tObject.defineProperty(subject, name, {\r\n\t\t\t\tenumerable: false,\r\n\t\t\t\tconfigurable: true,\r\n\t\t\t\tvalue: function(){\r\n\t\t\t\t\tvar temp = undefined;\r\n\t\t\t\t\tvar lastLength = this.length;\r\n\r\n\t\t\t\t\tif(Array.prototype[name])\r\n\t\t\t\t\t\ttemp = Array.prototype[name].apply(this, arguments);\r\n\r\n\t\t\t\t\tif(name === 'pop')\r\n\t\t\t\t\t\tprocessElement(lastLength - 1);\r\n\r\n\t\t\t\t\telse if(name === 'push')\r\n\t\t\t\t\t\tprocessElement(lastLength, true);\r\n\r\n\t\t\t\t\telse if(name === 'shift')\r\n\t\t\t\t\t\tprocessElement(0);\r\n\r\n\t\t\t\t\telse if(name === 'splice'){\r\n\t\t\t\t\t\tif(arguments.length >= 3){ // Inserting data\r\n\t\t\t\t\t\t\targuments[0] = false;\r\n\t\t\t\t\t\t\tname = 'softRefresh';\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t\telse{ // Removing data\r\n\t\t\t\t\t\t\tvar real = arguments[0];\r\n\t\t\t\t\t\t\tif(real < 0) real = lastLength + real;\r\n\r\n\t\t\t\t\t\t\tvar limit = arguments[1];\r\n\t\t\t\t\t\t\tif(!limit) limit = oldArray.length;\r\n\t\t\t\t\t\t\t\r\n\t\t\t\t\t\t\tfor (var i = limit - 1; i >= 0; i--) {\r\n\t\t\t\t\t\t\t\tprocessElement(real + i);\r\n\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t\telse if(name === 'unshift')\r\n\t\t\t\t\t\tprocessElement(0, true, true);\r\n\r\n\t\t\t\t\tif(name === 'softRefresh'){\r\n\t\t\t\t\t\tif(arguments[0] || arguments[0] === 0)\r\n\t\t\t\t\t\t\tprocessElement(arguments[0], !!oldArray[arguments[0]]);\r\n\t\t\t\t\t\telse {\r\n\t\t\t\t\t\t\tvar foundChanges = false;\r\n\r\n\t\t\t\t\t\t\t// Removal\r\n\t\t\t\t\t\t\tif(oldArray.length > this.length){\r\n\t\t\t\t\t\t\t\tfor (var i = oldArray.length - 1; i >= this.length; i--) {\r\n\t\t\t\t\t\t\t\t\tif(this.indexOf(oldArray[i]) === -1){\r\n\t\t\t\t\t\t\t\t\t\tfoundChanges = true;\r\n\t\t\t\t\t\t\t\t\t\tprocessElement(i);\r\n\t\t\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t\t\t// Creates\r\n\t\t\t\t\t\t\tif(oldArray.length < this.length){\r\n\t\t\t\t\t\t\t\tfor (var i = oldArray.length - 1; i < this.length; i++) {\r\n\t\t\t\t\t\t\t\t\tfoundChanges = true;\r\n\t\t\t\t\t\t\t\t\tprocessElement(i, true, true);\r\n\t\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t\t\t// Update\r\n\t\t\t\t\t\t\tfor (var i = 0; i < this.length; i++) {\r\n\t\t\t\t\t\t\t\tif(compareObject(oldArray[i], this[i]) === false){\r\n\t\t\t\t\t\t\t\t\tfoundChanges = true;\r\n\t\t\t\t\t\t\t\t\tprocessElement(i, true);\r\n\t\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t\t\tif(foundChanges)\r\n\t\t\t\t\t\t\t\toldArray = this.slice(0);\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t}\r\n\t\t\t\t\telse if(name === 'hardRefresh'){\r\n\t\t\t\t\t\toldArray = this.slice(0);\r\n\t\t\t\t\t\tprocessElement(-1);\r\n\t\t\t\t\t}\r\n\t\t\t\t\telse Array.prototype[name].apply(oldArray, arguments);\r\n\r\n\t\t\t\t\treturn temp;\r\n\t\t\t\t}\r\n\t\t\t});\r\n\t\t}\r\n\r\n\t\tfor (var i = 0; i < editProperty.length; i++) {\r\n\t\t\tpropertyProxy(list, editProperty[i]);\r\n\t\t}\r\n\t}\r\n\r\n\tfunction compareObject(obj1, obj2){\r\n\t\tif(!obj1 || !obj2)\r\n\t\t\treturn false;\r\n\r\n\t\tfor(var i in obj1){\r\n\t\t\tif(typeof obj1[i] !== 'object' && obj1[i] !== obj2[i])\r\n\t\t\t\treturn false;\r\n\t\t}\r\n\t\treturn true;\r\n\t}\r\n\r\n\tvar loopParser = function(name, content, script, targetNode){\r\n\t\tvar returns = '';\r\n\t\tvar method = script.split(' in ');\r\n\t\tvar mask = method[0];\r\n\r\n\t\tif(!self.root[name])\r\n\t\t\treturn console.error(\"Can't parse element because model for '\"+name+\"' was not found\", $(content)[0]);\r\n\r\n\t\tvar items = self.root[name][method[1]];\r\n\r\n\t\t// Get reference for debugging\r\n\t\tprocessingElement = $(content).attr('sf-bind-list', method[1])[0];\r\n\r\n\t\tcontent = processingElement.outerHTML;\r\n\t\tcontent = content.replace(/ +|\\t+/g, '');\r\n\r\n\t\tif(method.length === 2){\r\n\t\t\tfor(var i in items){\r\n\t\t\t\tvar item = items[i];\r\n\r\n\t\t\t\ttemp = uniqueDataParser(content, item, mask, name);\r\n\t\t\t\ttemp = dataParser(temp, item, mask, name);\r\n\t\t\t\treturns += temp;\r\n\t\t\t}\r\n\t\t\tObject.defineProperty(self.root[name], method[1], {\r\n\t\t\t\tenumerable: true,\r\n\t\t\t\tconfigurable: true,\r\n\t\t\t\tget:function(){\r\n\t\t\t\t\treturn items;\r\n\t\t\t\t},\r\n\t\t\t\tset:function(val){\r\n\t\t\t\t\tfor (var i = 0; i < val.length; i++) {\r\n\t\t\t\t\t\tif(items[i]){\r\n\t\t\t\t\t\t\titems[i] = val[i];\r\n\t\t\t\t\t\t\titems.softRefresh(i);\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t\telse items.push(val[i]);\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t\tif(items.length > val.length)\r\n\t\t\t\t\t\titems.splice(val.length);\r\n\r\n\t\t\t\t\treturn items;\r\n\t\t\t\t}\r\n\t\t\t});\r\n\t\t\tbindArray(content, items, mask, name, method[1], targetNode);\r\n\t\t}\r\n\t\treturn returns;\r\n\t}\r\n\r\n\tvar bindInput = function(targetNode){\r\n\t\t$('input[sf-bound]', targetNode).each(function(){\r\n\t\t\tvar element = $(this);\r\n\t\t\tvar model = element.parents('[sf-controller]').attr('sf-controller');\r\n\t\t\tif(!model) return;\r\n\r\n\t\t\tvar whichVar = element.attr('sf-bound');\r\n\r\n\t\t\t// Get reference\r\n\t\t\tif(typeof self.root[model][whichVar] === undefined){\r\n\t\t\t\tconsole.error('Cannot get reference for self.root[\"' + model + '\"][\"' + whichVar+'\"]');\r\n\t\t\t\treturn;\r\n\t\t\t}\r\n\r\n\t\t\telement.attr('sf-bounded', whichVar);\r\n\t\t\telement.removeAttr('sf-bound');\r\n\r\n\t\t\t// Bound key up\r\n\t\t\telement.keyup(function(e){\r\n\t\t\t\tself.root[model][whichVar] = element.val();\r\n\t\t\t});\r\n\r\n\t\t\t// Bind value\r\n\t\t\telement.attr('value', '{{'+whichVar+'}}');\r\n\t\t\tbindObject(element, self.root[model], whichVar, 'attr');\r\n\t\t});\r\n\t}\r\n\r\n\tvar alreadyInitialized = false;\r\n\tself.init = function(targetNode){\r\n\t\tif(alreadyInitialized) return;\r\n\t\talreadyInitialized = true;\r\n\t\tsetTimeout(function(){\r\n\t\t\talreadyInitialized = false;\r\n\t\t}, 50);\r\n\r\n\t\ttargetNode = targetNode ? $(targetNode)[0] : document.body;\r\n\t\tself.parsePreprocess(self.queuePreprocess(targetNode));\r\n\t\tbindInput(targetNode);\r\n\r\n\t\t$('[sf-repeat-this]', targetNode).each(function(){\r\n\t\t\tvar self = $(this);\r\n\t\t\tvar parent = self.parent();\r\n\r\n\t\t\tvar after = self.next();\r\n\t\t\tif(!after.length || self[0] === after[0])\r\n\t\t\t\tafter = false;\r\n\r\n\t\t\tvar before = self.before();\r\n\t\t\tif(!before.length || self[0] === before[0])\r\n\t\t\t\tbefore = false;\r\n\r\n\t\t\tvar script = self.attr('sf-repeat-this');\r\n\t\t\tself.removeAttr('sf-repeat-this');\r\n\t\t\tvar controller = sf.controller.modelName(this);\r\n\r\n\t\t\tvar content = this.outerHTML;\r\n\r\n\t\t\t// Check if the element was already bound to prevent vulnerability\r\n\t\t\tif(/sf-bind-id|sf-bind-list/.test(content))\r\n\t\t\t\tthrow \"Can't parse element that already bound\";\r\n\r\n\t\t\tvar data = loopParser(controller, content, script, targetNode);\r\n\t\t\tif(data){\r\n\t\t\t\tself.remove();\r\n\t\t\t\t\r\n\t\t\t\tdata = $(data);\r\n\t\t\t\tif(after)\r\n\t\t\t\t\tdata.insertBefore(after);\r\n\t\t\t\telse if(before)\r\n\t\t\t\t\tdata.insertAfter(before);\r\n\t\t\t\telse\r\n\t\t\t\t\tparent.append(data);\r\n\t\t\t}\r\n\t\t\telse{\r\n\t\t\t\tself.attr('sf-bind-list', script.split(' in ')[1]);\r\n\t\t\t\tclearElementData(this);\r\n\t\t\t}\r\n\t\t});\r\n\t}\r\n\r\n\t// Reset model properties\r\n\t// Don't call if the removed element is TEXT or #comment\r\n\tfunction DOMNodeRemoved(element){\r\n\t\tvar model = sf.controller.modelName(element);\r\n\r\n\t\t$('[sf-bind-id], [sf-bind-list], [sf-bounded], [sf-repeat-this]', element).each(function(){\r\n\t\t\tremoveBinding(this, model);\r\n\t\t});\r\n\r\n\t\tremoveBinding(element);\r\n\t}\r\n\r\n\t$(function(){\r\n\t\tif(typeof MutationObserver === 'function' && MutationObserver.prototype.observe){\r\n\t\t\tvar observer = new MutationObserver(function(records){\r\n\t\t\t\tif(!bindingEnabled) return;\r\n\r\n\t\t\t\tfor(var i in records){\r\n\t\t\t\t\tfor(var a in records[i].removedNodes){\r\n\t\t\t\t\t\tvar tagName = records[i].removedNodes[a].nodeName;\r\n\t\t\t\t\t\tif(tagName !== 'TEXT' || tagName !== '#comment') continue;\r\n\t\t\t\t\t\tDOMNodeRemoved(records[i].removedNodes[a]);\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t});\r\n\t\t\tobserver.observe(document.body, { childList: true, subtree: true });\r\n\t\t}\r\n\t\telse {\r\n\t\t\tdocument.body.addEventListener('DOMNodeRemoved', function(e){\r\n\t\t\t\tif(bindingEnabled){\r\n\t\t\t\t\tvar tagName = e.target.nodeName;\r\n\t\t\t\t\tif(tagName !== 'TEXT' || tagName !== '#comment') return;\r\n\t\t\t\t\tDOMNodeRemoved(e.target);\r\n\t\t\t\t}\r\n\t\t\t});\r\n\t\t}\r\n\t});\r\n\r\n\tvar removeBinding = function(element, modelNames){\r\n\t\tif(!element.attributes) return;\r\n\r\n\t\tvar attrs = element.attributes;\r\n\t\tif(attrs['sf-bind-id']){\r\n\t\t\tvar id = attrs['sf-bind-id'].value;\r\n\r\n\t\t\tif(!bindRef[id]) return;\r\n\t\t\tvar ref = bindRef[id];\r\n\r\n\t\t\tfor (var i = 0; i < ref.propertyName.length; i++) {\r\n\t\t\t\tvar value = ref.object[ref.propertyName[i]];\r\n\t\t\t\tObject.defineProperty(ref.object, ref.propertyName[i], {\r\n\t\t\t\t\tconfigurable: true,\r\n\t\t\t\t\tenumerable:true,\r\n\t\t\t\t\twritable:true,\r\n\t\t\t\t\tvalue:value\r\n\t\t\t\t});\r\n\t\t\t}\r\n\r\n\t\t\tdelete bindRef[id];\r\n\r\n\t\t\t// Remove callback left\r\n\t\t\tvar cache = bindRef.cache\r\n\t\t\tfor(var i in cache){\r\n\t\t\t\tif(cache[i].callback && cache[i].callback[id])\r\n\t\t\t\t\tdelete cache[i].callback[id];\r\n\t\t\t\tif($.isEmptyObject(cache[i].callback))\r\n\t\t\t\t\tdelete cache[i];\r\n\t\t\t}\r\n\r\n\t\t\tif(cache[id]){\r\n\t\t\t\tdelete cache[id].attrs;\r\n\t\t\t\tdelete cache[id].innerHTML;\r\n\t\t\t\tdelete cache[id].modelName;\r\n\t\t\t\tdelete cache[id].model;\r\n\t\t\t\tdelete cache[id].created;\r\n\t\t\t\tdelete cache[id].element;\r\n\t\t\t}\r\n\r\n\t\t\tbindRef.length--;\r\n\t\t\tif(bindRef.length === 0)\r\n\t\t\t\tbindRef.index = 0;\r\n\t\t}\r\n\r\n\t\tif(!modelNames) return;\r\n\r\n\t\tvar propertyName = false;\r\n\t\tif(attrs['sf-bind-list'])\r\n\t\t\tpropertyName = attrs['sf-bind-list'].value;\r\n\r\n\t\tif(attrs['sf-repeat-this'])\r\n\t\t\tpropertyName = attrs['sf-repeat-this'].value.split(' in ')[1];\r\n\r\n\t\tif(attrs['sf-bounded'])\r\n\t\t\tpropertyName = attrs['sf-bounded'].value;\r\n\r\n\t\tfor (var i = 0; i < modelNames.length; i++) {\r\n\t\t\tvar modelRef = self.root[modelNames[i]];\r\n\t\t\tif(!modelRef[propertyName]) continue;\r\n\r\n\t\t\tvar value = modelRef[propertyName].slice(0);\r\n\t\t\tObject.defineProperty(modelRef, propertyName, {\r\n\t\t\t\tconfigurable: true,\r\n\t\t\t\tenumerable:true,\r\n\t\t\t\twritable:true,\r\n\t\t\t\tvalue:value\r\n\t\t\t});\r\n\t\t}\r\n\t}\r\n\r\n\t/*{\r\n\t\tid:{\r\n\t\t\tobject,\r\n\t\t\t[propertyName]\r\n\t\t}\r\n\t}*/\r\n\t// For resetting object property it the element was removed from DOM\r\n\tvar bindRef = {length:0, index:0, cache:{}};\r\n\tself.bindRef = bindRef;\r\n\tvar dcBracket = /{{[\\s\\S]*?}}/;\r\n\tvar bindObject = function(element, object, propertyName, which){\r\n\t\tif(!(element instanceof Node))\r\n\t\t\telement = element[0];\r\n\r\n\t\t// Get reference for debugging\r\n\t\tprocessingElement = element;\r\n\r\n\t\t// First initialization\r\n\t\tvar id = bindRef.index;\r\n\t\t$(element).attr('sf-bind-id', id);\r\n\r\n\t\tbindRef.index++;\r\n\t\tbindRef.length++;\r\n\t\tbindRef.cache[id] = {};\r\n\t\tvar cache = bindRef.cache[id];\r\n\r\n\t\tcache.attrs = {};\r\n\t\tcache.innerHTML = '';\r\n\t\tcache.modelName = sf.controller.modelName(element);\r\n\t\tcache.model = self.root[cache.modelName];\r\n\t\tcache.created = Date.now();\r\n\r\n\t\tif(which === 'attr' || !which){\r\n\t\t\tfor(var i in element.attributes){\r\n\t\t\t\t// Check if it has a bracket\r\n\t\t\t\tif(!dcBracket.test(element.attributes[i].value))\r\n\t\t\t\t\tcontinue;\r\n\r\n\t\t\t\tvar attrName = element.attributes[i].name;\r\n\t\t\t\tcache.attrs[attrName] = element.attributes[i].value;\r\n\r\n\t\t\t\tif(attrName === 'value')\r\n\t\t\t\t\telement.removeAttribute(attrName);\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tif(which === 'html' || !which)\r\n\t\t\tcache.innerHTML = element.innerHTML;\r\n\r\n\t\t// Get current object reference\r\n\t\tif(!bindRef[id]) bindRef[id] = {object:object, propertyName:[]};\r\n\t\tbindRef[id].propertyName.push(propertyName);\r\n\r\n\t\tcache.element = $(element);\r\n\t\tvar callbackFunction = function(){\r\n\t\t\tif(which === 'attr' || !which){\r\n\t\t\t\tfor(var name in cache.attrs){\r\n\t\t\t\t\tif(cache.attrs[name].indexOf(propertyName) === -1)\r\n\t\t\t\t\t\tcontinue;\r\n\r\n\t\t\t\t\tvar temp = dataParser(cache.attrs[name], cache.model, false, cache.modelName);\r\n\t\t\t\t\tif(name === 'value')\r\n\t\t\t\t\t\tcache.element.val(temp);\r\n\t\t\t\t\telse\r\n\t\t\t\t\t\tcache.element.attr(name, temp);\r\n\t\t\t\t\tbreak;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\r\n\t\t\tif(which === 'html' || !which){\r\n\t\t\t\tvar temp = uniqueDataParser(cache.innerHTML, cache.model, false, cache.modelName);\r\n\t\t\t\ttemp = dataParser(temp, cache.model, false, cache.modelName);\r\n\t\t\t\tcache.element.html(temp);\r\n\t\t\t}\r\n\t\t};\r\n\r\n\t\tif(Object.getOwnPropertyDescriptor(cache.model, propertyName)['set']){\r\n\t\t\tfor(var i in bindRef){\r\n\t\t\t\tif(cache.model === bindRef[i].object && bindRef[i].propertyName.indexOf(propertyName) !== -1){\r\n\t\t\t\t\tbindRef.cache[i].callback[id] = callbackFunction;\r\n\t\t\t\t\tbreak;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\treturn;\r\n\t\t}\r\n\r\n\t\tcache.callback = {};\r\n\t\tcache.callback[id] = callbackFunction;\r\n\r\n\t\tvar objValue = object[propertyName]; // Object value\r\n\t\tObject.defineProperty(object, propertyName, {\r\n\t\t\tenumerable: true,\r\n\t\t\tconfigurable: true,\r\n\t\t\tget:function(){\r\n\t\t\t\treturn objValue;\r\n\t\t\t},\r\n\t\t\tset:function(val){\r\n\t\t\t\tobjValue = val;\r\n\r\n\t\t\t\tfor(var i in cache.callback){\r\n\t\t\t\t\tcache.callback[i]();\r\n\t\t\t\t}\r\n\r\n\t\t\t\treturn objValue;\r\n\t\t\t}\r\n\t\t});\r\n\t}\r\n\r\n\tself.bindElement = function(element, which){\r\n\t\tvar modelName = sf.controller.modelName(element);\r\n\t\tvar model = self.root[modelName];\r\n\t\tif(!model) return console.error(\"Model for \"+modelName+\" was not found while binding:\", element);\r\n\r\n\t\tvar html = element.outerHTML;\r\n\r\n\t\t// Check if the child element was already bound to prevent vulnerability\r\n\t\tif(/sf-bind-id|sf-bind-list/.test(html))\r\n\t\t\tthrow \"Can't parse element that already bound\";\r\n\r\n\t\tif(which === 'attr')\r\n\t\t\thtml = html.replace(element.innerHTML, '');\r\n\r\n\t\tvar brackets = /{{([\\s\\S]*?)}}/g;\r\n\t\tvar scopeMask = RegExp('\\\\b[^.]|^|\\\\n| +|\\\\t|\\\\W ('+self.modelKeys(model)+')'+sf.regex.avoidQuotes+'\\\\b', 'g');\r\n\t\tvar s1, s2 = null;\r\n\t\twhile((s1 = brackets.exec(html)) !== null){\r\n\t\t\twhile ((s2 = scopeMask.exec(s1[1])) !== null) {\r\n\t\t\t\tbindObject(element, model, s2[1], which);\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\tself.queuePreprocess = function(targetNode){\r\n\t\tvar childNodes = (targetNode || document.body).childNodes;\r\n\r\n\t\tvar excludes = ['html','head','style','link','meta','script','object','iframe'];\r\n\t\tfor (var i = 0; i < excludes.length; i++) {\r\n\t\t\texcludes[i] = excludes[i].toUpperCase();\r\n\t\t}\r\n\r\n\t\tvar temp = [];\r\n\t\tfor (var i = 0; i < childNodes.length; i++) {\r\n\t\t\tvar currentNode = childNodes[i];\r\n\t\t\tif(excludes.indexOf(currentNode.nodeName) !== -1)\r\n\t\t\t\tcontinue;\r\n\r\n\t\t\tif(currentNode.nodeType === 1){ // Tag\r\n\t\t\t\tvar attrs = currentNode.attributes;\r\n\r\n\t\t\t\t// Skip element and it's childs that already bound to prevent vulnerability\r\n\t\t\t\tif(attrs['sf-bind-id'] || attrs['sf-repeat-this'] || attrs['sf-bind-list']) continue;\r\n\r\n\t\t\t\tfor (var a = 0; a < attrs.length; a++) {\r\n\t\t\t\t\tif(attrs[a].value.indexOf('{{') !== -1){\r\n\t\t\t\t\t\tcurrentNode.setAttribute('sf-preprocess', 'attronly');\r\n\t\t\t\t\t\ttemp.push(currentNode);\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\r\n\t\t\t\ttemp = temp.concat(self.queuePreprocess(currentNode));\r\n\t\t\t}\r\n\r\n\t\t\telse if(currentNode.nodeType === 3){ // Text\r\n\t\t\t\tif(currentNode.nodeValue.indexOf('{{') !== -1){\r\n\t\t\t\t\tcurrentNode.parentNode.setAttribute('sf-preprocess', '');\r\n\r\n\t\t\t\t\t// Reset Siblings\r\n\t\t\t\t\tfor (var a = 0; a < temp.length; a++) {\r\n\t\t\t\t\t\ttemp[a].removeAttribute('sf-preprocess');\r\n\t\t\t\t\t}\r\n\t\t\t\t\ttemp.push(currentNode.parentNode);\r\n\r\n\t\t\t\t\tbreak;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\treturn temp;\r\n\t}\r\n\r\n\tself.parsePreprocess = function(nodes){\r\n\t\tfor (var a = 0; a < nodes.length; a++) {\r\n\t\t\tvar model = sf.controller.modelName(nodes[a]);\r\n\t\t\tnodes[a].removeAttribute('sf-preprocess');\r\n\r\n\t\t\tif(!self.root[model])\r\n\t\t\t\treturn console.error(\"Can't parse element because model for '\"+model+\"' was not found\", nodes[a]);\r\n\r\n\t\t\t// Get reference for debugging\r\n\t\t\tprocessingElement = nodes[a];\r\n\r\n\t\t\t// Double check if the child element already bound to prevent vulnerability\r\n\t\t\tif(/sf-bind-id|sf-bind-list/.test(nodes[a].innerHTML)){\r\n\t\t\t\tconsole.error(\"Can't parse element that already bound\");\r\n\t\t\t\tconsole.log($(processingElement.outerHTML)[0]);\r\n\t\t\t\treturn;\r\n\t\t\t}\r\n\r\n\t\t\tif($(nodes[a]).attr('sf-bind'))\r\n\t\t\t\tself.bindElement(nodes[a], $(nodes[a]).attr('sf-bind'));\r\n\r\n\t\t\t// Avoid editing the outerHTML because it will remove the bind\r\n\t\t\tvar temp = uniqueDataParser(nodes[a].innerHTML, self.root[model], false, model);\r\n\t\t\tnodes[a].innerHTML = dataParser(temp, self.root[model], false, model);\r\n\t\t\tfor (var i = 0; i < nodes[a].attributes.length; i++) {\r\n\t\t\t\tif(nodes[a].attributes[i].value.indexOf('{{') !== -1){\r\n\t\t\t\t\tnodes[a].attributes[i].value = dataParser(nodes[a].attributes[i].value, self.root[model], false, model);\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n}","sf.router = new function(){\r\n\tvar self = this;\r\n\tself.loading = false;\r\n\tself.enabled = false;\r\n\tself.pauseRenderOnTransition = false;\r\n\tself.currentPage = [];\r\n\tvar initialized = false;\r\n\tvar lazyRouting = false;\r\n\tvar currentRouterURL = '';\r\n\r\n\t// Should be called if not using lazy page load\r\n\tself.init = function(targetNode){\r\n\t\tif(!sf.loader.DOMWasLoaded)\r\n\t\t\treturn sf(function(){\r\n\t\t\t\tself.init();\r\n\t\t\t});\r\n\r\n\t\t// Reinit lazy router\r\n\t\tself.lazy();\r\n\r\n\t\t// Run 'before' event for new page view\r\n\t\t$('[sf-controller], [sf-page]', $(targetNode)[0]).each(function(){\r\n\t\t\tif(this.attributes['sf-controller'])\r\n\t\t\t\tsf.controller.run(this.attributes['sf-controller'].value);\r\n\t\t\t\r\n\t\t\tif(this.attributes['sf-page']){\r\n\t\t\t\tvar name = this.attributes['sf-page'].value;\r\n\t\t\t\tbeforeEvent(name);\r\n\t\t\t}\r\n\t\t});\r\n\r\n\t\tinitialized = true;\r\n\t\tcurrentRouterURL = window.location.pathname;\r\n\t}\r\n\r\n\tself.enable = function(status){\r\n\t\tif(status === undefined) status = true;\r\n\t\tif(self.enabled === status) return;\r\n\t\tself.enabled = status;\r\n\r\n\t\tif(status)\r\n\t\t\tself.lazy();\r\n\t\telse{\r\n\t\t\t$('a[href][onclick]').each(function(){\r\n\t\t\t\tvar current = $(this);\r\n\t\t\t\tif(current.attr('onclick') === 'return sf.router.load(this)')\r\n\t\t\t\t\tcurrent.removeAttr('onclick');\r\n\t\t\t});\r\n\t\t}\r\n\r\n\t\twindow.addEventListener('popstate', function(event) {\r\n\t\t\t// Don't continue if the last routing was error\r\n\t\t\tif(routingError){\r\n\t\t\t\troutingError = false;\r\n\t\t\t\treturn;\r\n\t\t\t}\r\n\r\n\t\t\troutingBack = true;\r\n\t\t\tself.goto(window.location.pathname);\r\n\t\t}, false);\r\n\t}\r\n\r\n\tvar before = {};\r\n\t// Set index with number if you want to replace old function\r\n\tself.before = function(name, func, index){\r\n\t\tif(!before[name])\r\n\t\t\tbefore[name] = [];\r\n\r\n\t\tif(index === undefined){\r\n\t\t\tif(before[name].indexOf(func) === -1)\r\n\t\t\t\tbefore[name].push(func);\r\n\t\t}\r\n\t\telse\r\n\t\t\tbefore[name][index] = func;\r\n\t}\r\n\r\n\tvar after = {};\r\n\t// Set index with number if you want to replace old function\r\n\tself.after = function(name, func, index){\r\n\t\tif(!after[name])\r\n\t\t\tafter[name] = [];\r\n\r\n\t\tif(index === undefined){\r\n\t\t\tif(after[name].indexOf(func) === -1)\r\n\t\t\t\tafter[name].push(func);\r\n\t\t}\r\n\t\telse\r\n\t\t\tafter[name][index] = func;\r\n\t}\r\n\r\n\tvar root_ = function(scope){\r\n\t\tif(!sf.model.root[scope])\r\n\t\t\tsf.model.root[scope] = {};\r\n\r\n\t\tif(!sf.model.root[scope])\r\n\t\t\tsf.controller.run(scope);\r\n\t\t\r\n\t\treturn sf.model.root[scope];\r\n\t}\r\n\r\n\t// Running 'before' new page going to be displayed\r\n\tvar beforeEvent = function(name){\r\n\t\tif(self.currentPage.indexOf(name) === -1)\r\n\t\t\tself.currentPage.push(name);\r\n\r\n\t\tif(before[name]){\r\n\t\t\tfor (var i = 0; i < before[name].length; i++) {\r\n\t\t\t\tbefore[name][i](root_);\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\t// Running 'after' old page going to be removed\r\n\tvar afterEvent = function(name){\r\n\t\tif(self.currentPage.indexOf(name) === -1)\r\n\t\t\tself.currentPage.splice(self.currentPage.indexOf(name), 1);\r\n\r\n\t\tif(after[name]){\r\n\t\t\tfor (var i = 0; i < after[name].length; i++) {\r\n\t\t\t\tafter[name][i](root_);\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\tvar onEvent = {\r\n\t\t'loading':[],\r\n\t\t'loaded':[],\r\n\t\t'special':[],\r\n\t\t'error':[]\r\n\t};\r\n\tself.on = function(event, func){\r\n\t\tif(onEvent[event].indexOf(func) === -1)\r\n\t\t\tonEvent[event].push(func);\r\n\t}\r\n\r\n\tself.lazyViewPoint = {};\r\n\t/*\r\n\t\t{\r\n\t\t\toldURlPattern:{\r\n\t\t\t\tnewURLPattern:'.viewPoint'\r\n\t\t\t}\r\n\t\t}\r\n\t*/\r\n\tself.lazy = function(){\r\n\t\tif(!self.enabled) return;\r\n\r\n\t\t$('a[href]:not([onclick])').each(function(){\r\n\t\t\tvar url = this.href;\r\n\t\t\tif(url.indexOf('#') !== -1)\r\n\t\t\t\treturn;\r\n\r\n\t\t\tif(url.indexOf(window.location.origin) !== 0 && url.charAt(0) !== '/')\r\n\t\t\t\treturn; //Not current domain origin\r\n\r\n\t\t\t$(this).attr('onclick', 'return sf.router.load(this)');\r\n\t\t});\r\n\t}\r\n\r\n\tself.load = function(elem){\r\n\t\tif(!history.pushState || $(elem).attr('sf-router') == 'ignore')\r\n\t\t\treturn true;\r\n\r\n\t\treturn !self.goto(elem.href.replace(window.location.origin, ''));\r\n\t}\r\n\r\n\tvar RouterLoading = false;\r\n\tvar routingBack = false;\r\n\tvar routingError = false;\r\n\tself.goto = function(path, data, method){\r\n\t\tif(!method) method = 'GET';\r\n else method = method.toUpperCase();\r\n\r\n\t\tfor (var i = 0; i < onEvent['loading'].length; i++) {\r\n\t\t\tif(onEvent['loading'][i](path)) return;\r\n\t\t}\r\n\t\tvar oldPath = window.location.pathname;\r\n\t\tinitialized = false;\r\n\r\n\t\tif(RouterLoading) RouterLoading.abort();\r\n\t\tRouterLoading = $.ajax({\r\n\t\t\turl:window.location.origin + path,\r\n\t\t\tmethod:method,\r\n data:Object.assign(data, {\r\n _scarlets:'.dynamic.'\r\n }),\r\n\t\t\tsuccess:function(data){\r\n\t\t\t\tif(initialized) return;\r\n\t\t\t\tlazyRouting = true;\r\n\r\n\t\t\t\t// Run 'loaded' event\r\n\t\t\t\tRouterLoading = false;\r\n\r\n\t\t\t\t// Find special data\r\n\t\t\t\tvar regex = RegExp(''+sf.regex.avoidQuotes, 'gm');\r\n\t\t\t\tvar special = regex.exec(data);\r\n\t\t\t\tif(special && special.length !== 1){\r\n\t\t\t\t\tspecial = special[1].split('--|&>').join('-->');\r\n\t\t\t\t\tspecial = JSON.parse(special);\r\n\r\n\t\t\t\t\tif(!$.isEmptyObject(special)){\r\n\t\t\t\t\t\tfor (var i = 0; i < onEvent['special'].length; i++) {\r\n\t\t\t\t\t\t\tif(onEvent['special'][i](special)) return;\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\r\n\t\t\t\tvar DOMReference = false;\r\n\t\t\t\tvar foundAction = function(ref){\r\n\t\t\t\t\tDOMReference = $(ref);\r\n\r\n\t\t\t\t\t// Run 'after' event for old page view\r\n\t\t\t\t\tafterEvent($('[sf-page]', DOMReference[0]).attr('sf-page'));\r\n\r\n\t\t\t\t\t// Redefine title if exist\r\n\t\t\t\t\tif(special && special.title)\r\n\t\t\t\t\t\t$('head title').html(special.title);\r\n\r\n\t\t\t\t\tfound = true;\r\n\t\t\t\t};\r\n\r\n\t\t\t\tvar found = false;\r\n\t\t\t\tfor(var oldURL in self.lazyViewPoint){\r\n\t\t\t\t\tif(currentRouterURL.indexOf(oldURL) !== -1){\r\n\t\t\t\t\t\tfor(var newURL in self.lazyViewPoint[oldURL]){\r\n\t\t\t\t\t\t\tif(currentRouterURL.indexOf(oldURL) !== -1){\r\n\t\t\t\t\t\t\t\tfoundAction(self.lazyViewPoint[oldURL][newURL]);\r\n\t\t\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t}\r\n\t\t\t\t\tif(found) break;\r\n\t\t\t\t}\r\n\r\n\t\t\t\t// When the view point was not found\r\n\t\t\t\tif(!found){\r\n\t\t\t\t\t// Use fallback if exist\r\n\t\t\t\t\tif(sf.router.lazyViewPoint[\"@default\"])\r\n\t\t\t\t\t\tfoundAction(sf.router.lazyViewPoint[\"@default\"]);\r\n\r\n\t\t\t\t\tif(!found){\r\n\t\t\t\t\t\tfor (var i = 0; i < onEvent['error'].length; i++) {\r\n\t\t\t\t\t\t\tonEvent['error'][i]('sf.router.lazyViewPoint[\"'+oldURL+'\"][\"'+newURL+'\"] was not found');\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\r\n\t\t\t\t// Reinit lazy router\r\n\t\t\t\tself.lazy();\r\n\r\n\t\t\t\t// Run 'before' event for new page view\r\n\t\t\t\tif(!DOMReference) DOMReference = $(document.body);\r\n\t\t\t\tif(self.pauseRenderOnTransition)\r\n\t\t\t\t\tself.pauseRenderOnTransition.css('display', 'none');\r\n\r\n\t\t\t\t// Let page script running first, then update the data binding\r\n\t\t\t\tDOMReference.html(data);\r\n\r\n\t\t\t\t// Parse the DOM data binding\r\n\t\t\t\tsf.model.init(DOMReference);\r\n\r\n\t\t\t\t// Init template to model binding\r\n\t\t\t\t$('[sf-page]', DOMReference[0]).each(function(){\r\n\t\t\t\t\tif(this.attributes['sf-page'])\r\n\t\t\t\t\t\tbeforeEvent(this.attributes['sf-page'].value);\r\n\t\t\t\t});\r\n\r\n\t\t\t\tif(self.pauseRenderOnTransition)\r\n\t\t\t\t\tself.pauseRenderOnTransition.css('display', '');\r\n\r\n\t\t\t\trouterLoaded(currentRouterURL, path, DOMReference);\r\n\r\n\t\t\t\tinitialized = true;\r\n\t\t\t\tlazyRouting = false;\r\n\r\n\t\t\t\tcurrentRouterURL = path;\r\n\t\t\t\troutingError = false;\r\n\t\t\t},\r\n\t\t\terror:function(xhr, data){\r\n\t\t\t\troutingError = true;\r\n\t\t\t\tif(xhr.aborted) return;\r\n\r\n\t\t\t\tRouterLoading = false;\r\n\t\t\t\tfor (var i = 0; i < onEvent['error'].length; i++) {\r\n\t\t\t\t\tonEvent['error'][i](xhr.status, data);\r\n\t\t\t\t}\r\n\r\n\t\t\t\t// Back on error\r\n\t\t\t\twindow.history.back();\r\n\t\t\t}\r\n\t\t});\r\n\r\n\t\tif(!routingBack)\r\n\t\t\twindow.history.pushState(null, \"\", path);\r\n\r\n\t\troutingBack = false;\r\n\t\treturn true;\r\n\t}\r\n\r\n\t// Trigger loaded event\r\n\tfunction routerLoaded(currentRouterURL, path, data){\r\n\t\tfor (var i = 0; i < onEvent['loaded'].length; i++) {\r\n\t\t\tonEvent['loaded'][i](currentRouterURL, path, data);\r\n\t\t}\r\n\t}\r\n};"]} \ No newline at end of file