Skip to content
Snippets Groups Projects
Commit c898d16c authored by Commander-lol's avatar Commander-lol
Browse files

Initial version of plugin. Floating render and insertion render available

parent ee173b8f
No related branches found
No related tags found
No related merge requests found
/*jslint node: true */
(function () {
'use strict';
var globalOptions = {
ignoreUndefined: false,
escape: "general",
escapeSets: {
xml: {
"<": "&lt;",
">": "&gt;",
"&": "&amp;",
"\"": "&quot;"
},
general: {
"\"": "\\\"",
"\'": "\\\'"
}
}
},
deepMergeJson = function (obja, objb) {
var prop;
for (prop in objb) {
if (objb.hasOwnProperty(prop)) {
if (typeof (obja[prop]) === 'object' && typeof (objb[prop]) === 'object') {
obja[prop] = deepMergeJson(obja[prop], objb[prop]);
} else {
obja[prop] = objb[prop];
}
}
}
return obja;
},
setDeepProperty = function (ident, value, obj) {
var list,
recurse = function (propList, value, obj) {
if (propList.length > 1) {
recurse(propList, value, obj[list.shift()]);
} else {
obj[propList[0]] = value;
}
};
if (!ident.push && !ident.map) {
list = ident.split(".").map(function (e) {return e.trim(); });
} else {
list = ident;
}
recurse(list, value, obj);
return obj;
},
getDeepProperty = function (ident, obj) {
var ret = null,
list,
recurse = function (propList, obj) {
var curident;
if (propList.length > 1) {
if (obj.hasOwnProperty(propList[0])) {
recurse(propList, obj[list.shift()]);
} else {
curident = propList.reduce(function (a, b, i) {
return a + (i > 0 ? "." : "") + b;
});
throw new Error("Invalid proprty, missing expected data \"" + curident + "\" (IDENT: " + ident + ") from data " + JSON.stringify(obj));
}
} else {
if (obj.hasOwnProperty(propList[0])) {
ret = obj[propList[0]];
} else {
throw new Error("Invalid proprty, missing expected data \"" + propList[0] + "\" (IDENT: " + ident + ") from data " + JSON.stringify(obj));
}
}
};
if (!ident.push && !ident.map) {
list = ident.split(".").map(function (e) {return e.trim(); });
} else {
list = ident;
}
recurse(list, obj);
return ret;
},
resolveNamespace = function (ident, blockStack) {
var l = blockStack.length, i, ret = "";
for (i = 0; i < l; i += 1) {
ret += blockStack[i] + ".";
}
return ret + ident;
},
safeDeepMergeJson = function (obja, objb) {
if (typeof (obja) !== 'object') {
throw new TypeError("Cannot deep merge with an " + typeof (obja) + ": [Param 1]");
}
if (typeof (objb) !== 'object') {
throw new TypeError("Cannot deep merge with an " + typeof (objb) + ": [Param 2]");
}
return deepMergeJson(deepMergeJson({}, obja), objb);
},
/**
* Using this Regex
* This regular expression will match and split all valid tags for Sideburns, and provides
* all data needed to appropriately lex each tag
*
* Result indexes (from re.exec()):
* [0] The whole tag that has been matched
* [1, 9] These are the opening and closing double square brackets, respectively. Always present
* [2] The Tag modifier. This will either be '/' for a closing tag, '#' for a pre-process directive
* or undefined for all other tags. Processing should branch here depending on whether or not this
* token is a hash ('#'). Indexes for one branch will be undefined in case of the other branch.
*
* == In case of Directive ==
* [3] The identifier of the directive to set. Always present
* [4] The value to set the directive. Always present
*
* == In case of other tag ==
* [5] The Block modifier. Will be '*' for arrays, '&' for context and undefined for simple tags
* [6] The Data modifier. Will be '!' for an escape with the global set, '!([7])' for an escape with a
* specified set or undefined for unescaped data
* [7] If a set has been specified, this will be the name of the set on its own, seperate from the data
* modifier. It will otherwise be undefined
* [8] The identifier for the data or block that the tag represents. Always present
**/
captureTags = /(\[\[)(\#|\/)?\s*(?:([a-zA-Z]+[a-zA-Z0-9]*)\s*\:\s*([a-zA-Z]+[a-zA-Z0-9]*)|([\*\&]?)\s*((?:\!(?:\(([a-zA-Z]+[a-zA-Z0-9]*)\))?)?)\s*([a-zA-Z](?:[a-zA-Z0-9]*(?:\.(?=[a-zA-Z]))?)+))\s*(\]\])/,
Stack = function () {
var self = this;
this.length = 0;
this.push = function (val) {
self[self.length] = val;
self.length += 1;
};
this.pop = function (val) {
var ret = null;
if (self.length > 0) {
ret = self[self.length - 1];
self[self.length - 1] = null;
self.length -= 1;
}
return ret;
};
this.peek = function () {
return this.length > 0 ? self[self.length - 1] : null;
};
this.contains = function (value, compare) {
compare = compare || function (a, b) {
return a === b;
};
var i = this.length;
while (i--) {
if (compare(this[i], value)) {
return true;
}
}
return false;
};
return this;
},
Node = function (type, val, modifiers) {
this.ident = type || "N_NULL";
this.val = val || null;
this.content = modifiers || {};
return this;
},
Token = function (ident, val, info) {
this.ident = ident || "T_NULL";
this.val = val || null;
this.info = info || {};
return this;
},
tokenise = function (src) {
var tokens = [],
last = 0,
i = 0,
match = null,
matcher,
chunk,
tok;
matcher = function () {
return ((match = captureTags.exec(chunk)) !== null);
};
while (i < src.length) {
chunk = src.substr(i);
if (matcher()) {
if (match.index > 0) {
tokens.push(new Token("STRING", match.input.substr(0, match.index)));
}
tok = new Token("T_NULL", null, {close: false, escape: false, escapeType: null});
if (match[2] === '#') {
tok.ident = "T_DIRECTIVE";
tok.val = {};
tok.val[match[3]] = match[4];
} else {
if (match[2] === '/') {
tok.info.close = true;
}
if (match[5] === "*") {
tok.ident = "T_LOOP";
} else if (match[5] === "&") {
tok.ident = "T_BLOCK";
} else {
tok.ident = "T_DATA";
}
if (typeof (match[6]) !== 'undefined' && match[6].charAt(0) === "!") {
tok.info.escape = true;
if (typeof (match[7]) !== 'undefined') {
tok.info.escapeType = match[7];
}
}
tok.val = match[8];
}
tokens.push(tok);
i += match.index + match[0].length;
} else {
tokens.push(new Token("STRING", chunk));
i += chunk.length;
}
}
tokens.push(new Token("EOD"));
return tokens;
},
collapseParse = function (tokens) {
var tokenList,
i = 0,
j,
targetToken,
targetNode;
while (i < tokens.length) {
if (tokens[i].info && tokens[i].info.close) {
tokenList = [];
targetToken = tokens[i];
j = i - 1;
while (!(tokens[j].ident === targetToken.ident && tokens[j].val === targetToken.val)) {
tokenList.push(tokens[j]);
j -= 1;
if (j < 0) {
throw new Error("Unmatched Closing Tag " + targetNode + " at index " + i);
}
}
if (targetToken.ident === "T_LOOP") {
targetNode = new Node("N_LOOP", targetToken.val, tokenList.slice().reverse());
} else {
targetNode = new Node("N_BLOCK", targetToken.val, tokenList.slice().reverse());
}
tokens.splice(j, (i - j) + 1, targetNode);
i = 0;
} else {
i += 1;
}
}
return tokens;
},
unwindNode = function (output, node, index, arr) {
var innerArr, dataArr, content, i, dataVal;
switch (node.ident) {
case "STRING":
return output + node.val;
case "T_DATA":
dataVal = node.val;
if (arr.loopTag) {
if (node.val === arr.loopTag.slice(0, -1)) {
dataVal = arr.loopTag + "." + (arr.i).toString();
}
}
return output + getDeepProperty(dataVal, arr.data);
case "N_LOOP":
content = "";
innerArr = node.content;
innerArr.data = arr.data;
innerArr.loopTag = node.val;
dataArr = getDeepProperty(node.val, arr.data);
for (i = 0; i < dataArr.length; i += 1) {
innerArr.i = i;
content += innerArr.reduce(unwindNode, "");
}
return output + content;
case "N_BLOCK":
innerArr = node.content;
innerArr.data = getDeepProperty(node.val, arr.data);
innerArr.loopTag = null;
return output + innerArr.reduce(unwindNode, "");
default:
return output;
}
},
render = function (src, data, options) {
var nodes = collapseParse(tokenise(src));
nodes.data = data;
nodes.loopTag = null;
nodes.i = null;
return nodes.reduce(unwindNode, "");
};
render.partial = function (src) {
return function (tokens, data, options) {
tokens.data = data;
tokens.loopTag = null;
tokens.i = null;
return tokens.reduce(unwindNode, "");
}.bind(null, collapseParse(tokenise(src)));
};
if (typeof module !== "undefined" && module.exports) {
module.exports = render;
} else {
window.sideburns = render;
}
}());
!function(){"use strict";var t,e,n;Element&&!Element.prototype.matches&&(t=Element.prototype,t.matches=t.matchesSelector||t.mozMatchesSelector||t.msMatchesSelector||t.oMatchesSelector||t.webkitMatchesSelector),e=function(t){var e,n,r;if(null===t||"undefined"==typeof t)this.length=0;else if("string"==typeof t)for(e=document.querySelectorAll(t),this.length=e.length,n=0;n<e.length;n++)r=e.item(n),this[n]=r;else if(t.length)for(n=0;n<t.length;n++)r=t[n],this[n]=r;else this[0]=t,this.length=1;return this},n=function(t){return new e(t)},n.fn=e.prototype={each:function(t){for(var e=this.length;e--;)t(e,this[e],this);return this},on:function(t,e,n){return"string"==typeof e?this.each(function(r,s){s.addEventListener(t,function(t){var r=t.target,i=!1;do r&&r.matches(e)?(n.call(r,t),i=!0):(r=r.parentNode,r&&r.matches&&r!==s||(i=!0));while(i!==!0)})}):(n=e,this.each(function(e,r){r.addEventListener(t,n)})),this},first:function(){return"undefined"!=typeof this[0]?n(this[0]):null},parent:function(t){var e=this[0].parentNode,r=!0;if(n.exists(t)){for(;null!==e&&e!==document;){if(e.matches(t)){r=!1;break}e=e.parentNode}e=r?null:e}return n(e)},children:function(){var t,e=this[0].childNodes,r=[];for(t=0;t<e.length;t++)n.isElement(e[t])&&r.push(e[t]);return n(r)},data:function(t,e){return"undefined"!=typeof e?(this.each(function(n,r){r.setAttribute("data-"+t,e)}),this):this[0].getAttribute("data-"+t)},attr:function(t,e){return"undefined"!=typeof e?(this.each(function(n,r){r.setAttribute(t,e)}),this):this[0].getAttribute(t)},"class":function(t,e){return this.each(n.exists(e)?function(n,r){r.classList.toggle(t,e)}:function(e,n){n.classList.toggle(t)}),this},trigger:function(t,e,r,s){r=n.exists(r)?r:!0,s=n.exists(s)?s:!0;var i=new CustomEvent(t,e,r,s);return this.each(function(t,e){e.dispatchEvent(i)}),this}},n.ready=function(t){document.addEventListener("DOMContentLoaded",t)},n.isElement=function(t){var e=!1;try{e=t instanceof HTMLElement}catch(n){e=t.nodeType&&1===t.nodeType}return e},n.isJson=function(t){try{return JSON.parse(t),null!==t&&"undefined"!=typeof t}catch(e){return!1}},n.exists=function(t){return null!==t&&"undefined"!=typeof t},n.merge=function(t,e){if(this.exists(t)&&this.exists(e)){var n;for(n in e)e.hasOwnProperty(n)&&(t[n]=e[n]);return t}return null},n.byID=function(t){return n(document.getElementById(t))},n.triggerOn=function(t,e,r,s,i){s=n.exists(s)?s:!0,i=n.exists(i)?i:!0,t.dispatchEvent(new CustomEvent(e,r,s,i))},n.json={keys:function(t){var e,n=[];for(e in t)t.hasOwnProperty(e)&&n.push(e);return n}},n.ajax=function(t){var e,n,r=new XMLHttpRequest,s={method:"GET",url:"",async:!0,user:null,password:null,responseType:"text",data:null,headers:[],callbacks:{}},i=function(t){return function(e){t(e.currentTarget.response,e)}};if(this.merge(s,t),r.responseType=s.responseType,this.exists(s.callbacks))for(e in s.callbacks)s.callbacks.hasOwnProperty(e)&&r.addEventListener(e,i(s.callbacks[e]));for(r.open(s.method,s.url,s.async,s.user,s.password),n=0;n<s.headers.length;n++)r.setRequestHeader(s.headers[n].header,s.headers[n].value);return r.send(s.data),r},window.μ||(window.μ=n),window.mu||(window.mu=n)}();
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>SB test</title>
<script src="td.js"></script>
<script src="sb.js"></script>
<script src="../tinyDOM-Sideburns.js"></script>
</head>
<body>
<main id="content"></main>
<script type="x-template/sideburns" data-name="list">
<ul>
[[* items ]]
<li>[[item]]</li>
[[/* items ]]
</ul>
</script>
<script type="application/javascript">
mu.ready(function(){
mu("#content").render("list",
{
items: ["hello", "this", "is", "list"]
},
{
useHtml: true
});
});
</script>
</body>
</html>
/*globals console, mu */
(function () {
"use strict";
if (!window.mu) {
throw new Error("tinyDOM-Sideburns requires tinyDOM to be in use on the page");
}
mu.templates = {};
mu.render = function (path, data, options) {
if (mu.templates.hasOwnProperty(path)) {
return mu.templates[path](data, options);
} else {
return window.sideburns(path, data, options);
}
};
mu.fn.render = function (path, data, options) {
var rendered = mu.render(path, data, options),
opts = options || {useHtml: true};
if (typeof opts.useHtml === "undefined") {
opts.useHtml = true;
}
this.each(function (i, e) {
if (opts.useHtml) {
e.innerHTML = rendered;
} else {
e.textContent = rendered;
}
});
};
mu.ready(function () {
mu("[type='x-template/sideburns']").each(function (i, e) {
var name = e.getAttribute("data-name");
mu.templates[name] = window.sideburns.partial(e.textContent);
});
});
}());
!function(){"use strict";if(!window.mu)throw new Error("tinyDOM-Sideburns requires tinyDOM to be in use on the page");mu.templates={},mu.render=function(e,t,n){return mu.templates.hasOwnProperty(e)?mu.templates[e](t,n):window.sideburns(e,t,n)},mu.fn.render=function(e,t,n){var r=mu.render(e,t,n),u=n||{useHtml:!0};"undefined"==typeof u.useHtml&&(u.useHtml=!0),this.each(function(e,t){u.useHtml?t.innerHTML=r:t.textContent=r})},mu.ready(function(){mu("[type='x-template/sideburns']").each(function(e,t){var n=t.getAttribute("data-name");mu.templates[n]=window.sideburns.partial(t.textContent)})})}();
//# sourceMappingURL=tinyDOM-Sideburns.min.js.map
{"version":3,"sources":["tinyDOM-Sideburns.js"],"names":["window","mu","Error","templates","render","path","data","options","hasOwnProperty","sideburns","fn","rendered","opts","useHtml","this","each","i","e","innerHTML","textContent","ready","name","getAttribute","partial"],"mappings":"CACC,WACG,YAEA,KAAKA,OAAOC,GACR,KAAM,IAAIC,OAAM,8DAGpBD,IAAGE,aAEHF,GAAGG,OAAS,SAAUC,EAAMC,EAAMC,GAC9B,MAAIN,IAAGE,UAAUK,eAAeH,GACrBJ,GAAGE,UAAUE,GAAMC,EAAMC,GAEzBP,OAAOS,UAAUJ,EAAMC,EAAMC,IAK5CN,GAAGS,GAAGN,OAAS,SAAUC,EAAMC,EAAMC,GACjC,GAAII,GAAWV,GAAGG,OAAOC,EAAMC,EAAMC,GACjCK,EAAOL,IAAYM,SAAS,EACJ,oBAAjBD,GAAKC,UACZD,EAAKC,SAAU,GAGnBC,KAAKC,KAAK,SAAUC,EAAGC,GACfL,EAAKC,QACLI,EAAEC,UAAYP,EAEdM,EAAEE,YAAcR,KAK5BV,GAAGmB,MAAM,WACLnB,GAAG,iCAAiCc,KAAK,SAAUC,EAAGC,GAClD,GAAII,GAAOJ,EAAEK,aAAa,YAC1BrB,IAAGE,UAAUkB,GAAQrB,OAAOS,UAAUc,QAAQN,EAAEE"}
\ No newline at end of file
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment