thinfront
Version:
A lightweight frontend framework for building web applications.
1 lines • 17.8 kB
JavaScript
(()=>{(function(window){function thinFront(){var settings,url_rewrite=null,currentLayout=null,curPage=null,_pageperm=[],cachedViews={},cachedLayouts={},_session={},oldHashChange="",methods={init:function(e){$.ajax({url:"settings.json",method:"get",success:function(t){settings=null!=e?$.extend(e,t):t,settings=$.extend({home:"home",viewFolder:"pages",layouts:{home:"layout.html"}},settings),this.settings=settings,window.onhashchange=function(e){handleNavigation(e.newURL,e.oldURL)?oldHashChange="":(oldHashChange=e.oldURL,window.location.href=e.oldURL)},handleNavigation()},cache:!1}),$.ajax({url:"url_rewrite.json",method:"get",success:function(e){url_rewrite=e}})},navigate:function(e){window.location.href="/"==e?window.location.origin:window.location.origin+window.location.pathname+"#"+e},page:function(){return curPage},path:{combine:function(){var e="";for(x=0;x<arguments.length;x++)e.length>0&&(e+="/"),e+=arguments[x];return e}},settings:function(){return settings},cookies:{set:function(e,t,n){var r="";if(n){var a=new Date;a.setTime(a.getTime()+24*n*60*60*1e3),r="; expires="+a.toUTCString()}document.cookie=e+"="+(t||"")+r+"; path=/"},get:function(e){for(var t=e+"=",n=document.cookie.split(";"),r=0;r<n.length;r++){for(var a=n[r];" "==a.charAt(0);)a=a.substring(1,a.length);if(0==a.indexOf(t))return a.substring(t.length,a.length)}return null},erase:function(e){document.cookie=e+"=; Max-Age=-99999999; path=/"}},binder:{scatter:function(e,t){$(t).find("[data-repeat]").each((function(t,n){var r,a=$(n),i=a.attr("data-repeat");i.includes(".")&&(r=e[i.split(".")[0]],i=i.split(".")[1]),r||(r=[]);var o=r[i],s=a.children()[0].outerHTML;if(a.empty(),null==o||"undefined"==o.length||0==o.length){var l=$(s);a.append(l),l.hide(),a.data("empty",!0)}else{var c=0;for(c=0;c<o.length;c++){l=$(s);var p=o[c];l.attr("data-row",c);var u=l.attr("data-if");l.attr("data-repeat-item")&&evalBindExp(l.attr("data-repeat-item"),p,l),evalif(u,r)&&l.find("[data-repeat-item]").each((function(e,t){(t=$(t)).attr("data-repeat-item").split("|").forEach((e=>{evalBindExp(e,p,t)}))})),a.append(l),l.show(),a.data("empty",!1)}}})),$(t).find("[data-bind]").each((function(t,n){var r=$(n),a=r.attr("data-bind");evalif(r.attr("data-if"),e)&&a.split("|").forEach((t=>{evalBindExp(t,e,r)}))}))},gather:function(e,t){$(e).find("[data-bind]").each((function(e,n){var r=$(n),a="input"==r[0].tagName.toLowerCase()||"select"==r[0].tagName.toLowerCase()?r.val():r.text();t[r.attr("data-bind")]=a})),$(e).find("[data-repeat]").each((function(e,n){var r=$(n);if(1!=r.data("empty")){t[r.attr("data-repeat")];var a=0;r.find("[data-row]").each((function(e,n){(n=$(n)).find("[data-repeat-item]").each((function(e,n){var i="input"==(n=$(n))[0].tagName.toLowerCase()||"select"==n[0].tagName.toLowerCase()?n.val():n.text();null==t[r.attr("data-repeat")]&&(t[r.attr("data-repeat")]=[]),t[r.attr("data-repeat")].length<=a&&t[r.attr("data-repeat")].push({});var o=n.attr("data-repeat-item");o=o.split("|")[0],t[r.attr("data-repeat")][a][o]=i})),a++}))}else t[r.attr("data-repeat")]=[]}))}},session:{values:{},clear:function(){localStorage.setItem("tf__session","")}},viewState:{},process:{attach:function(e){e instanceof TFProcess&&(this.list.push(e),e.start())},list:[]},security:{pagePermission:((_pageperm=JSON.parse(localStorage.getItem("__pagePerm")))||(_pageperm=[]),{defaultPerm:!0,set:function(e,t,n,r){if(e&&t&&n)if("allow"==n||"deny"==n){var a=this.find(e,t);a?(a.type=n,a.activities=r):_pageperm.push({cont:e,act:t,type:n,activities:r}),localStorage.setItem("__pagePerm",JSON.stringify(_pageperm))}else console.error("invalid permission type, only 'allow' or 'deny' is permitted");else console.error("invalid parameters")},find:function(e,t,n=!0){var r=null;for(let i=0;i<_pageperm.length;i++){var a=_pageperm[i];if(a.cont=a.cont.toLowerCase().trim(),e=e.toLowerCase().trim(),t=t.toLowerCase().trim(),a.act=a.act.toLowerCase().trim(),a.cont==e&&(a.act==t||a.act==(1==n?t:"*"))){r=a;break}}return r},get:function(e,t,n){var r={cont:e,act:t,type:n||(this.defaultPerm?"allow":"deny"),activities:[]};if(0==_pageperm.length)return r;var a=this.find(e,t);if(a)return a;var i=this.find(e,t,!1);return i||r},check:function(e,t,n){if(0==_pageperm.length)return n||this.defaultPerm;var r=this.find(e,t);if(r)return"allow"==r.type;var a=this.find(e,t,!1);return a?"allow"==a.type:n||this.defaultPerm},clear:function(){_pageperm=[],localStorage.setItem("__pagePerm",JSON.stringify(_pageperm))}})},user:{loggedIn:function(e,t,n){"JWT"==settings.authType&&(delete(e=parseJWT(t)).iat,delete e.exp,delete e.credValid),localStorage.setItem("userInfo",JSON.stringify(e)),tf.cookies.set("accessToken",t),tf.cookies.set("refreshToken",n)},isLoggedIn:function(){if(!settings.requireLogin)return console.log("login not required"),!0;var e=tf.cookies.get("accessToken"),t=tf.cookies.get("refreshToken");if(!e)return console.log("token not available"),!1;if("JWT"==settings.authType){var n=new Date;if(new Date(1e3*parseJWT(e).exp)>n)return tf.user.loggedIn(null,e,t),!0;console.log("token is expired, checking refresh token");n=new Date;return new Date(1e3*parseJWT(t).exp)>n?(console.log("refresh token is valid, renewing the token"),this.refreshToken(),!0):(console.log("refresh token is also expired, redirecting to login"),!1)}},refreshToken:function(){var e=!1,t=JSON.stringify({refreshToken:this.getRefreshToken()});return $.ajax({url:tf.path.combine(settings.serviceUrl,settings.refTokenUrl),method:"POST",async:!1,data:t,contentType:"application/json",beforeSend:function(e){e.setRequestHeader("Authorization","Bearer "+tf.cookies.get("accessToken"))},success:function(t){t.success?(tf.user.loggedIn(null,t.data.tokens.accessToken,t.data.tokens.refreshToken),e=!0):e=!1},error:function(t){e=!1}}),e},getToken:function(){return tf.cookies.get("accessToken")},getRefreshToken:function(){return tf.cookies.get("refreshToken")},getInfo:function(){return JSON.parse(localStorage.getItem("userInfo"))},logout:function(){localStorage.removeItem("userInfo"),tf.cookies.erase("accessToken"),tf.cookies.erase("refreshToken"),tf.navigate("/")}},loadScript:function(e,t=!0,n){let r=document.createElement("script");r.setAttribute("src",e),r.setAttribute("type","text/javascript"),r.setAttribute("async",t),document.body.appendChild(r),r.addEventListener("load",(()=>{console.log("File loaded"),n&&n()})),r.addEventListener("error",(e=>{console.log("Error on loading file",e)}))}};try{_session=JSON.parse(localStorage.getItem("tf__session")),_session||(_session={})}catch(e){_session={}}function applyPageActivityPermission(e,t){for(x=0;x<t.activities.length;x++){var n=t.activities[x],r=e.find("[permission="+n.activity+"]");if("true"!=n.permission&&"false"!=n.permission||(n.permission="true"==n.permission),"string"==typeof n.permission){var a=n.permission.split(";");for(y=0;y<a.length;y++){var i=a[y].split("=")[0],o=a[y].split("=")[1];"value"==i?r.val(o):"text"==i?r.text(o):"class"==i?r.addClass(o):r.attr(i,o)}}else n.permission||r.remove()}}function findHashPart(e){var t=e.split("#");return t.length>1?t[1]:"/"}function parseJWT(e){var t=e.split(".")[1].replace(/-/g,"+").replace(/_/g,"/"),n=decodeURIComponent(atob(t).split("").map((function(e){return"%"+("00"+e.charCodeAt(0).toString(16)).slice(-2)})).join(""));return n=JSON.parse(n)}function evalif(exp,data){try{for(var key in data)if(data.hasOwnProperty(key)){var re=new RegExp("{"+key+"}","g");exp=exp.replace(re,data[key])}var comp=!0;comp=eval(exp)}catch(e){comp=!0}return comp}function evalBindExp(bindExp,data,elem){var expPart=bindExp.split("~"),attr="",propName=expPart[0];expPart.length>1&&(attr=expPart[0],propName=expPart[1]);var props=propName.split("+"),propVal="",y=0,propFound=!1;if(data){for(y=0;y<props.length;y++)data.hasOwnProperty(props[y])&&(null!=data[props[y]]&&(propVal+=data[props[y]]),propFound=!0);if(!propFound)try{var exp=propName;for(var key in data)if(data.hasOwnProperty(key)){var re=new RegExp("{"+key+"}","g");exp=exp.replace(re,data[key])}propVal=eval(exp)}catch(e){}}"input"==elem[0].tagName.toLowerCase()||"select"==elem[0].tagName.toLowerCase()?""==attr||"value"==attr?("input"==elem[0].tagName.toLowerCase()||""!=propVal)&&elem.val(propVal):elem.attr(attr,propVal):""==attr||"value"==attr?elem.text(propVal):"class"==attr?elem.addClass(propVal):"stylebg"!=attr?elem.attr(attr,propVal):""!=propVal?$(elem).attr("style","background-image:url("+propVal+")"):$(elem).attr("style","background-image:url('assets/images/productimage.jpg')")}function handleNavigation(e,t){if(oldHashChange==e)return!0;if(e&&tf.page.unload){console.log("page unload");var n=parseNavUrl(findHashPart(e)),r=parseNavUrl(findHashPart(t));if(!tf.page.unload(n,r))return!1}if(null!=settings){var a=window.location.hash;a.startsWith("#")&&(a=a.substr(1,a.length-1));var i=parseNavUrl(a,t),o=tf.user.isLoggedIn();if(!o){var s=parseNavUrl(settings.loginUrl);if(s.controller==i.controller&&s.action==i.action)o=!0;else{var l=!1;if(settings.publicUrls)for(var c=0;c<settings.publicUrls.length;c++){var p=settings.publicUrls[c];if((p=parseNavUrl(p)).controller==i.controller&&p.action==i.action){l=!0;break}}l?o=!0:tf.navigate(settings.loginUrl)}}if(o){var u=!0;settings.securePages&&(u=methods.security.pagePermission.check(i.controller,i.action)),u&&(methods.page=i,renderView(methods.page.url)),tf.events&&tf.events.pagePermission&&methods.events.pagePermission(i,u)}}return!0}function loadLayout(e,t){if(currentLayout==e){if(null!=t&&"function"==typeof t)return void t()}else""!=e&&null!=e?(null!=tf.events&&null!=tf.events.beforeLayoutRender&&"function"==typeof tf.events.beforeLayoutRender&&tf.events.beforeLayoutRender(e),$.ajax({url:methods.path.combine("layouts",settings.layouts[e]),method:"get",success:function(n){n=$(n);var r=$("#__app_layout");r.empty(),r.append(n),includeHTML("layout"),clearScripts("layout"),loadScripts(n,"layout"),currentLayout=e,null!=t&&"function"==typeof t&&t(),null!=tf.events&&null!=tf.events.afterLayoutRender&&"function"==typeof tf.events.afterLayoutRender&&tf.events.afterLayoutRender(e)},cache:settings.allowBrowserCache})):(currentLayout="",t())}function parseNavUrl(e,t){var n=e.split("?");n[0]=translate_url(n[0]),""==n[0]&&(n[0]=settings.home);var r=n[0].split("/"),a=""==r[0]?settings.home:r[0],i="index",o=[],s={},l=tf.page.layout;return r.length>1&&(isNaN(r[1])?(i=r[1],r.slice(2).forEach((e=>{""!=e&&o.push(e)}))):r.slice(1).forEach((e=>{""!=e&&o.push(e)}))),n.length>1&&n[1].split("&").forEach((e=>{var t=e.split("=");s[t[0]]=decodeURI(t[1])})),null==t&&(t=""),new pageObject({controller:a,action:i,url:a+"/"+i+".html",args:o,queryString:s,fullUrl:e,layout:l,rebuildUrl:function(){var e="";e+=a+"/"+i,e+=this.args.join("/");var t="";for(key in this.queryString)t+=key+"="+this.queryString[key];return t.length>0&&(t="?"+t),e+=t},loadPartialView:function(e,t,n){e.endsWith(".html")||(e+=".html"),"string"==typeof t&&(t=$(t)),renderPartialView(e,t,n)},prevURL:findHashPart(t)})}function clearScripts(e){$("#__"+e+"_scripts").empty()}function loadScripts(htmlContent,scope){var mainTag=$("<div></div>");mainTag.append(htmlContent.clone());var scrArray=mainTag.find("script");scrArray.each((function(idx,element){if(element=$(element),element.attr("src")){var srcPath=element.attr("src");if(0==$("#__"+scope+"_scripts").length&&$("body").append("<script id='__"+scope+"_scripts'><\/script>"),0==$("#__"+scope+"_scripts").find("script[src='"+srcPath+"']").length){var newSrc=$("<script><\/script>");$("#__"+scope+"_scripts").append(newSrc),newSrc.attr("src",srcPath+(settings.allowBrowserCache?"":"?_="+(new Date).getTime()))}}else eval(element.innerHTML)}))}function translate_url(e){var t=e;return null!=url_rewrite&&url_rewrite.forEach((n=>{n.source!=e||(t=n.target)})),t}function renderView(e,t){e=settings.viewFolder+"/"+e;var n=function(t){var n=$(t),r=n.attr("app-layout"),a=(""!=n.attr("app-title")&&null!=n.attr("app-title")?n.attr("app-title")+" - ":"")+(""!=settings.applicationTitle&&null!=settings.applicationTitle?settings.applicationTitle:"");a&&(document.title=a);var i=function(){null!=r&&""!=r||$("#__app_layout").empty();var e=$('[container="view"]');0==e.length&&(e=$("#__app_layout")),e.empty(),clearScripts("view"),e.append(n),e.find("script").remove(),loadScripts(n,"view"),includeHTML("view"),setDefaultState(),null!=methods.page.ready&&"function"==typeof methods.page.ready&&methods.page.ready()};methods.viewState={},null!=tf.events&&null!=tf.events.beforeViewRender&&"function"==typeof tf.events.beforeViewRender&&tf.events.beforeViewRender(e),methods.page.layout!=r?(methods.page.layout=r,loadLayout(r,i),console.log("layout loaded")):(console.log("used existingn layout"),i()),null!=tf.events&&null!=tf.events.afterViewRender&&"function"==typeof tf.events.afterViewRender&&tf.events.afterViewRender(e)};if(null!=cachedViews[e])return html=cachedViews[e],void n(html);$.ajax({url:e.toLowerCase(),method:"get",success:function(t){cachedViews[e]=t,n(t)},error:function(t,n){404==t.status&&(t="<h1>Not Found</h1><p><h5>"+e+"</h5>");var r=$('[container="view"]');0==r.length&&(r=$("#__app_layout")),0==r.length&&(r=$("body")),r.empty(),r.append(t)},cache:settings.allowBrowserCache})}function renderPartialView(e,t,n){e=settings.viewFolder+"/"+e;var r=function(e){var n=$(e);t.empty(),t.append(n),includeHTML("view")};if(null!=cachedViews[e])return html=cachedViews[e],void r(html);$.ajax({url:e.toLowerCase(),method:"get",success:function(t){cachedViews[e]=t,r(t),n&&n()},error:function(n){404==n.status&&(n="<h1>Not Found</h1><p><h5>"+e+"</h5>"),t.empty(),t.append(n)},cache:settings.allowBrowserCache})}function setDefaultState(){var e=methods.page.queryString.__page_state;if(!e){var t=$(document).find("[page-state]");t.length>0&&(e=$(t[0]).attr("page-state"))}e&&methods.page.setState(e)}function includeHTML(e){$("[include-html]").each((function(t,n){var r=settings.viewFolder+"/"+$(n).attr("include-html");$(n).removeAttr("include-html"),r&&$.ajax({url:r,method:"get",success:function(t){loadScripts(t=$(t),e);var r=$("<div></div>");r.append(t),r.find("script").remove(),$(n).append(r),includeHTML(e)},cache:settings.allowBrowserCache})}))}methods.session.values=new Proxy(_session,{get:function(e,t){return Reflect.get(e,t)},set:function(e,t,n){Reflect.set(e,t,n),localStorage.setItem("tf__session",JSON.stringify(_session))}});var pageObject=function(e){var t="",n="";return $.extend(e,{setState:function(e){$("[page-state]").hide(),$("[page-state="+e+"]").show(),n=t,t=e},currentState:function(){return t},prevState:function(){return n}})};return methods}function initService(){var e;if(void 0!==window.tf){function t(){if(!tf.page.queryString.returnurl){var e=tf.page.fullUrl;e?tf.navigate("account?returnurl="+encodeURIComponent(e)):tf.navigate("account")}}window.tf.service={permission:((e=JSON.parse(localStorage.getItem("_service_perm")))||(e=[]),{defaultPerm:!0,set:function(t,n){if(t&&n)if("allow"==n||"deny"==n){t.startsWith("/")||(t="/"+t);var r=this.find(t);r?r.type=n:e.push({link:t,type:n}),localStorage.setItem("_service_perm",JSON.stringify(e))}else console.error("invalid permission type, only 'allow' or 'deny' is permitted");else console.error("invalid parameters")},find:function(t){t.startsWith("/")||(t="/"+t);var n=null;for(let a=0;a<e.length;a++){var r=e[a];if(r.link==t){n=r;break}}return n},check:function(t,n){if(t.startsWith("/")||(t="/"+t),0==e.length)return n||this.defaultPerm;var r=this.find(t);return r?"allow"==r.type:n||this.defaultPerm},clear:function(){e=[],localStorage.setItem("_service_perm",JSON.stringify(e))}}),call:function(e,n,r,a,i,o,s,l){if(this.permission.check(n)){if(null==l&&(l=this.showLoader),l&&this.loader&&this.loader.show(),tf.user.isLoggedIn()||!(tf.settings().loginAPIUrls.filter((e=>e.Name===n)).length>0))return function(e,n,r,a,i=!0,o="application/json",s){return $.ajax({url:tf.path.combine(tf.settings().serviceUrl,n),data:r?JSON.stringify(r):"",type:e,async:i,beforeSend:function(e){tf.settings().requireLogin&&0==tf.settings().loginAPIUrls.filter((e=>e.Name===this.url)).length&&(e=function(e){return"basic"==tf.settings().authType.toLowerCase()?e.setRequestHeader("Authorization","Basic "+tf.cookies.get("token")):"jwt"==tf.settings().authType.toLowerCase()&&e.setRequestHeader("Authorization","Bearer "+tf.cookies.get("accessToken")),e}(e))},contentType:o,success:function(e){window.tf&&window.tf.events&&window.tf.events.servicePermission&&window.tf.events.servicePermission(n,!0,"server"),this.showLoader&&this.loader&&this.loader.hide(),null!=a&&a(e,!0)},error:function(e){l&&this.loader&&this.loader.hide(),401==e.status?(tf.cookies.erase("token"),t()):403==e.status?(console.log("access denied to the API ",n),window.tf&&window.tf.events&&window.tf.events.servicePermission&&window.tf.events.servicePermission(n,!1,"server")):404==e.status||null!=a&&a(e,!1)},complete:function(e,t){l&&tf.service.loader&&tf.service.loader.hide(),s&&s(e,t)}})}(e,n,r,a,i,o,s);tf.settings().loginUrl&&t()}else window.tf&&window.tf.events&&window.tf.events.servicePermission&&window.tf.events.servicePermission(n,!1,"local")},get:function(e,t,n,r){"function"==typeof t&&(r=n,n=t,t=null),r||(r={});var a="";if(t){for(var i in t)a.length>0&&(a+="&"),a+=i+"="+encodeURI(t[i]);e.indexOf("?")<0?e+="?"+a:e+="&"+a}return this.call("get",e,null,n,r.async,r.contentType,r.complete,r.showLoader)},post:function(e,t,n,r){return r||(r={}),"function"==typeof t&&(n=t,t=null),this.call("post",e,t,n,r.async,r.contentType,r.complete,r.showLoader)}}}else console.log("tf is not defined")}void 0===window.tf&&(window.tf=new thinFront,initService()),window.onclick=function(e){"a"==e.target.tagName.toLowerCase()&&"#"==$(e.target).attr("href")&&e.preventDefault()},window.addEventListener("pageshow",(function(e){e.persisted&&window.location.reload()}))})(window)})();