From 0263c2c2aeef7b1d1409c9191d60b4fcccc89ba2 Mon Sep 17 00:00:00 2001 From: ThomasJ Date: Tue, 2 Feb 2016 17:14:08 +0900 Subject: [PATCH] ax5core 0.8.0 - Add Mustache.js --- bower.json | 2 +- dist/ax5core.js | 635 ++++++++++++++++++++++++++++++++++++++++++++ dist/ax5core.min.js | 2 +- package.json | 2 +- src/mustache.js | 634 +++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 1272 insertions(+), 3 deletions(-) mode change 100755 => 100644 dist/ax5core.js mode change 100755 => 100644 dist/ax5core.min.js create mode 100644 src/mustache.js diff --git a/bower.json b/bower.json index 0d46099..e2066a3 100644 --- a/bower.json +++ b/bower.json @@ -1,6 +1,6 @@ { "name": "ax5core", - "version": "0.7.5", + "version": "0.8.0", "authors": [ "ThomasJ " ], diff --git a/dist/ax5core.js b/dist/ax5core.js old mode 100755 new mode 100644 index 9e21084..ad2bc0d --- a/dist/ax5core.js +++ b/dist/ax5core.js @@ -2065,3 +2065,638 @@ ax5.ui = (function (core) { } })(ax5); + +/*! + * mustache.js - Logic-less {{mustache}} templates with JavaScript + * http://github.com/janl/mustache.js + * https://github.com/thomasJang/mustache.js -- imporove some variables + */ + +(function defineMustache(global, factory) { + + factory(global.mustache = {}); + +}(window.ax5, function mustacheFactory(mustache) { + + var objectToString = Object.prototype.toString; + var isArray = Array.isArray || function isArrayPolyfill(object) { + return objectToString.call(object) === '[object Array]'; + }; + + function isFunction(object) { + return typeof object === 'function'; + } + + /** + * More correct typeof string handling array + * which normally returns typeof 'object' + */ + function typeStr(obj) { + return isArray(obj) ? 'array' : typeof obj; + } + + function escapeRegExp(string) { + return string.replace(/[\-\[\]{}()*+?.,\\\^$|#\s]/g, '\\$&'); + } + + /** + * Null safe way of checking whether or not an object, + * including its prototype, has a given property + */ + function hasProperty(obj, propName) { + return obj != null && typeof obj === 'object' && (propName in obj); + } + + // Workaround for https://issues.apache.org/jira/browse/COUCHDB-577 + // See https://github.com/janl/mustache.js/issues/189 + var regExpTest = RegExp.prototype.test; + + function testRegExp(re, string) { + return regExpTest.call(re, string); + } + + var nonSpaceRe = /\S/; + + function isWhitespace(string) { + return !testRegExp(nonSpaceRe, string); + } + + var entityMap = { + '&': '&', '<': '<', '>': '>', '"': '"', "'": ''', '/': '/' + }; + + function escapeHtml(string) { + return String(string).replace(/[&<>"'\/]/g, function fromEntityMap(s) { + return entityMap[s]; + }); + } + + var whiteRe = /\s*/; + var spaceRe = /\s+/; + var equalsRe = /\s*=/; + var curlyRe = /\s*\}/; + var tagRe = /#|\^|\/|>|\{|&|=|!/; + + /** + * Breaks up the given `template` string into a tree of tokens. If the `tags` + * argument is given here it must be an array with two string values: the + * opening and closing tags used in the template (e.g. [ "<%", "%>" ]). Of + * course, the default is to use mustaches (i.e. mustache.tags). + * + * A token is an array with at least 4 elements. The first element is the + * mustache symbol that was used inside the tag, e.g. "#" or "&". If the tag + * did not contain a symbol (i.e. {{myValue}}) this element is "name". For + * all text that appears outside a symbol this element is "text". + * + * The second element of a token is its "value". For mustache tags this is + * whatever else was inside the tag besides the opening symbol. For text tokens + * this is the text itself. + * + * The third and fourth elements of the token are the start and end indices, + * respectively, of the token in the original template. + * + * Tokens that are the root node of a subtree contain two more elements: 1) an + * array of tokens in the subtree and 2) the index in the original template at + * which the closing tag for that section begins. + */ + function parseTemplate(template, tags) { + if (!template) + return []; + + var sections = []; // Stack to hold section tokens + var tokens = []; // Buffer to hold the tokens + var spaces = []; // Indices of whitespace tokens on the current line + var hasTag = false; // Is there a {{tag}} on the current line? + var nonSpace = false; // Is there a non-space char on the current line? + + // Strips all whitespace tokens array for the current line + // if there was a {{#tag}} on it and otherwise only space. + function stripSpace() { + if (hasTag && !nonSpace) { + while (spaces.length) + delete tokens[spaces.pop()]; + } + else { + spaces = []; + } + + hasTag = false; + nonSpace = false; + } + + var openingTagRe, closingTagRe, closingCurlyRe; + + function compileTags(tagsToCompile) { + if (typeof tagsToCompile === 'string') + tagsToCompile = tagsToCompile.split(spaceRe, 2); + + if (!isArray(tagsToCompile) || tagsToCompile.length !== 2) + throw new Error('Invalid tags: ' + tagsToCompile); + + openingTagRe = new RegExp(escapeRegExp(tagsToCompile[0]) + '\\s*'); + closingTagRe = new RegExp('\\s*' + escapeRegExp(tagsToCompile[1])); + closingCurlyRe = new RegExp('\\s*' + escapeRegExp('}' + tagsToCompile[1])); + } + + compileTags(tags || mustache.tags); + + var scanner = new Scanner(template); + + var start, type, value, chr, token, openSection; + while (!scanner.eos()) { + start = scanner.pos; + + // Match any text between tags. + value = scanner.scanUntil(openingTagRe); + + if (value) { + for (var i = 0, valueLength = value.length; i < valueLength; ++i) { + chr = value.charAt(i); + + if (isWhitespace(chr)) { + spaces.push(tokens.length); + } + else { + nonSpace = true; + } + + tokens.push(['text', chr, start, start + 1]); + start += 1; + + // Check for whitespace on the current line. + if (chr === '\n') + stripSpace(); + } + } + + // Match the opening tag. + if (!scanner.scan(openingTagRe)) + break; + + hasTag = true; + + // Get the tag type. + type = scanner.scan(tagRe) || 'name'; + scanner.scan(whiteRe); + + // Get the tag value. + if (type === '=') { + value = scanner.scanUntil(equalsRe); + scanner.scan(equalsRe); + scanner.scanUntil(closingTagRe); + } + else if (type === '{') { + value = scanner.scanUntil(closingCurlyRe); + scanner.scan(curlyRe); + scanner.scanUntil(closingTagRe); + type = '&'; + } + else { + value = scanner.scanUntil(closingTagRe); + } + + // Match the closing tag. + if (!scanner.scan(closingTagRe)) + throw new Error('Unclosed tag at ' + scanner.pos); + + token = [type, value, start, scanner.pos]; + tokens.push(token); + + if (type === '#' || type === '^') { + sections.push(token); + } + else if (type === '/') { + // Check section nesting. + openSection = sections.pop(); + + if (!openSection) + throw new Error('Unopened section "' + value + '" at ' + start); + + if (openSection[1] !== value) + throw new Error('Unclosed section "' + openSection[1] + '" at ' + start); + } + else if (type === 'name' || type === '{' || type === '&') { + nonSpace = true; + } + else if (type === '=') { + // Set the tags for the next time around. + compileTags(value); + } + } + + // Make sure there are no open sections when we're done. + openSection = sections.pop(); + + if (openSection) + throw new Error('Unclosed section "' + openSection[1] + '" at ' + scanner.pos); + + return nestTokens(squashTokens(tokens)); + } + + /** + * Combines the values of consecutive text tokens in the given `tokens` array + * to a single token. + */ + function squashTokens(tokens) { + var squashedTokens = []; + + var token, lastToken; + for (var i = 0, numTokens = tokens.length; i < numTokens; ++i) { + token = tokens[i]; + + if (token) { + if (token[0] === 'text' && lastToken && lastToken[0] === 'text') { + lastToken[1] += token[1]; + lastToken[3] = token[3]; + } + else { + squashedTokens.push(token); + lastToken = token; + } + } + } + + return squashedTokens; + } + + /** + * Forms the given array of `tokens` into a nested tree structure where + * tokens that represent a section have two additional items: 1) an array of + * all tokens that appear in that section and 2) the index in the original + * template that represents the end of that section. + */ + function nestTokens(tokens) { + var nestedTokens = []; + var collector = nestedTokens; + var sections = []; + + var token, section; + for (var i = 0, numTokens = tokens.length; i < numTokens; ++i) { + token = tokens[i]; + + switch (token[0]) { + case '#': + case '^': + collector.push(token); + sections.push(token); + collector = token[4] = []; + break; + case '/': + section = sections.pop(); + section[5] = token[2]; + collector = sections.length > 0 ? sections[sections.length - 1][4] : nestedTokens; + break; + default: + collector.push(token); + } + } + + return nestedTokens; + } + + /** + * A simple string scanner that is used by the template parser to find + * tokens in template strings. + */ + function Scanner(string) { + this.string = string; + this.tail = string; + this.pos = 0; + } + + /** + * Returns `true` if the tail is empty (end of string). + */ + Scanner.prototype.eos = function eos() { + return this.tail === ''; + }; + + /** + * Tries to match the given regular expression at the current position. + * Returns the matched text if it can match, the empty string otherwise. + */ + Scanner.prototype.scan = function scan(re) { + var match = this.tail.match(re); + + if (!match || match.index !== 0) + return ''; + + var string = match[0]; + + this.tail = this.tail.substring(string.length); + this.pos += string.length; + + return string; + }; + + /** + * Skips all text until the given regular expression can be matched. Returns + * the skipped string, which is the entire tail if no match can be made. + */ + Scanner.prototype.scanUntil = function scanUntil(re) { + var index = this.tail.search(re), match; + + switch (index) { + case -1: + match = this.tail; + this.tail = ''; + break; + case 0: + match = ''; + break; + default: + match = this.tail.substring(0, index); + this.tail = this.tail.substring(index); + } + + this.pos += match.length; + + return match; + }; + + /** + * Represents a rendering context by wrapping a view object and + * maintaining a reference to the parent context. + */ + function Context(view, parentContext) { + this.view = view; + this.cache = {'.': this.view}; + this.parent = parentContext; + } + + /** + * Creates a new context using the given view with this context + * as the parent. + */ + Context.prototype.push = function push(view) { + return new Context(view, this); + }; + + /** + * Returns the value of the given name in this context, traversing + * up the context hierarchy if the value is absent in this context's view. + */ + Context.prototype.lookup = function lookup(name) { + var cache = this.cache; + + var value; + if (cache.hasOwnProperty(name)) { + value = cache[name]; + } + else { + var context = this, names, index, lookupHit = false; + + while (context) { + if (name.indexOf('.') > 0) { + value = context.view; + names = name.split('.'); + index = 0; + + /** + * Using the dot notion path in `name`, we descend through the + * nested objects. + * + * To be certain that the lookup has been successful, we have to + * check if the last object in the path actually has the property + * we are looking for. We store the result in `lookupHit`. + * + * This is specially necessary for when the value has been set to + * `undefined` and we want to avoid looking up parent contexts. + **/ + while (value != null && index < names.length) { + if (index === names.length - 1) + lookupHit = hasProperty(value, names[index]); + + value = value[names[index++]]; + } + } + else { + value = context.view[name]; + lookupHit = hasProperty(context.view, name); + } + + if (lookupHit) + break; + + context = context.parent; + } + + cache[name] = value; + } + + if (isFunction(value)) + value = value.call(this.view); + + return value; + }; + + /** + * A Writer knows how to take a stream of tokens and render them to a + * string, given a context. It also maintains a cache of templates to + * avoid the need to parse the same template twice. + */ + function Writer() { + this.cache = {}; + } + + /** + * Clears all cached templates in this writer. + */ + Writer.prototype.clearCache = function clearCache() { + this.cache = {}; + }; + + /** + * Parses and caches the given `template` and returns the array of tokens + * that is generated from the parse. + */ + Writer.prototype.parse = function parse(template, tags) { + var cache = this.cache; + var tokens = cache[template]; + + if (tokens == null) + tokens = cache[template] = parseTemplate(template, tags); + + return tokens; + }; + + /** + * High-level method that is used to render the given `template` with + * the given `view`. + * + * The optional `partials` argument may be an object that contains the + * names and templates of partials that are used in the template. It may + * also be a function that is used to load partial templates on the fly + * that takes a single argument: the name of the partial. + */ + Writer.prototype.render = function render(template, view, partials) { + var tokens = this.parse(template); + var context = (view instanceof Context) ? view : new Context(view); + return this.renderTokens(tokens, context, partials, template); + }; + + /** + * Low-level method that renders the given array of `tokens` using + * the given `context` and `partials`. + * + * Note: The `originalTemplate` is only ever used to extract the portion + * of the original template that was contained in a higher-order section. + * If the template doesn't use higher-order sections, this argument may + * be omitted. + */ + Writer.prototype.renderTokens = function renderTokens(tokens, context, partials, originalTemplate) { + var buffer = ''; + + var token, symbol, value; + for (var i = 0, numTokens = tokens.length; i < numTokens; ++i) { + value = undefined; + token = tokens[i]; + symbol = token[0]; + + if (symbol === '#') value = this.renderSection(token, context, partials, originalTemplate); + else if (symbol === '^') value = this.renderInverted(token, context, partials, originalTemplate); + else if (symbol === '>') value = this.renderPartial(token, context, partials, originalTemplate); + else if (symbol === '&') value = this.unescapedValue(token, context); + else if (symbol === 'name') value = this.escapedValue(token, context); + else if (symbol === 'text') value = this.rawValue(token); + + if (value !== undefined) + buffer += value; + } + + return buffer; + }; + + Writer.prototype.renderSection = function renderSection(token, context, partials, originalTemplate) { + var self = this; + var buffer = ''; + + var value = context.lookup(token[1]); + + // This function is used to render an arbitrary template + // in the current context by higher-order sections. + function subRender(template) { + return self.render(template, context, partials); + } + + if (!value) return; + + if (isArray(value)) { + for (var j = 0, valueLength = value.length; j < valueLength; ++j) { + value[j].__i__ = j; + value[j].__first__ = (j === 0); + buffer += this.renderTokens(token[4], context.push(value[j]), partials, originalTemplate); + } + } + else if (typeof value === 'object' || typeof value === 'string' || typeof value === 'number') { + buffer += this.renderTokens(token[4], context.push(value), partials, originalTemplate); + } + else if (isFunction(value)) { + if (typeof originalTemplate !== 'string') + throw new Error('Cannot use higher-order sections without the original template'); + + // Extract the portion of the original template that the section contains. + value = value.call(context.view, originalTemplate.slice(token[3], token[5]), subRender); + + if (value != null) + buffer += value; + } + else { + buffer += this.renderTokens(token[4], context, partials, originalTemplate); + } + return buffer; + }; + + Writer.prototype.renderInverted = function renderInverted(token, context, partials, originalTemplate) { + var value = context.lookup(token[1]); + + // Use JavaScript's definition of falsy. Include empty arrays. + // See https://github.com/janl/mustache.js/issues/186 + if (!value || (isArray(value) && value.length === 0)) + return this.renderTokens(token[4], context, partials, originalTemplate); + }; + + Writer.prototype.renderPartial = function renderPartial(token, context, partials) { + if (!partials) return; + + var value = isFunction(partials) ? partials(token[1]) : partials[token[1]]; + if (value != null) + return this.renderTokens(this.parse(value), context, partials, value); + }; + + Writer.prototype.unescapedValue = function unescapedValue(token, context) { + var value = context.lookup(token[1]); + if (value != null) + return value; + }; + + Writer.prototype.escapedValue = function escapedValue(token, context) { + var value = context.lookup(token[1]); + if (value != null) + return mustache.escape(value); + }; + + Writer.prototype.rawValue = function rawValue(token) { + return token[1]; + }; + + mustache.name = 'mustache.js'; + mustache.version = '2.1.3'; + mustache.tags = ['{{', '}}']; + + // All high-level mustache.* functions use this writer. + var defaultWriter = new Writer(); + + /** + * Clears all cached templates in the default writer. + */ + mustache.clearCache = function clearCache() { + return defaultWriter.clearCache(); + }; + + /** + * Parses and caches the given template in the default writer and returns the + * array of tokens it contains. Doing this ahead of time avoids the need to + * parse templates on the fly as they are rendered. + */ + mustache.parse = function parse(template, tags) { + return defaultWriter.parse(template, tags); + }; + + /** + * Renders the `template` with the given `view` and `partials` using the + * default writer. + */ + mustache.render = function render(template, view, partials) { + if (typeof template !== 'string') { + throw new TypeError('Invalid template! Template should be a "string" ' + 'but "' + typeStr(template) + '" was given as the first ' + 'argument for mustache#render(template, view, partials)'); + } + + return defaultWriter.render(template, view, partials); + }; + + // This is here for backwards compatibility with 0.4.x., + /*eslint-disable */ // eslint wants camel cased function name + mustache.to_html = function to_html(template, view, partials, send) { + /*eslint-enable*/ + + var result = mustache.render(template, view, partials); + + if (isFunction(send)) { + send(result); + } + else { + return result; + } + }; + + // Export the escaping function so that the user may override it. + // See https://github.com/janl/mustache.js/issues/244 + mustache.escape = escapeHtml; + + // Export these mainly for testing, but also for advanced usage. + mustache.Scanner = Scanner; + mustache.Context = Context; + mustache.Writer = Writer; + +})); diff --git a/dist/ax5core.min.js b/dist/ax5core.min.js old mode 100755 new mode 100644 index 3b2d58a..43a780e --- a/dist/ax5core.min.js +++ b/dist/ax5core.min.js @@ -1 +1 @@ -(function(){"use strict";var e,t,r,n=this,o=window,i=document,a=(document.documentElement,/^(["'](\\.|[^"\\\n\r])*?["']|[,:{}\[\]0-9.\-+Eaeflnr-u \n\r\t])+?$/),u=/^-ms-/,l=/[\-_]([\da-z])/gi,s=/([A-Z])/g,f=/\./,c=/[-|+]?[\D]/gi,d=/\D/gi,p=new RegExp("([0-9])([0-9][0-9][0-9][,.])"),g=/&/g,h=/=/,m=/[ ]+/g,y={};y.guid=1,y.getGuid=function(){return y.guid++},y.info=e=function(){function r(e,r){return e={href:o.location.href,param:o.location.search,referrer:i.referrer,pathname:o.location.pathname,hostname:o.location.hostname,port:o.location.port},r=e.href.split(/[\?#]/),e.param=e.param.replace("?",""),e.url=r[0],e.href.search("#")>-1&&(e.hashdata=t.last(r)),r=null,e.baseUrl=t.left(e.href,"?").replace(e.pathname,""),e}function n(t,r,n){return e.errorMsg&&e.errorMsg[t]?{className:t,errorCode:r,methodName:n,msg:e.errorMsg[t][r]}:{className:t,errorCode:r,methodName:n}}var a="0.0.1",u="",l=function(){console.error(t.toArray(arguments).join(":"))},s={BACKSPACE:8,TAB:9,RETURN:13,ESC:27,LEFT:37,UP:38,RIGHT:39,DOWN:40,DELETE:46,HOME:36,END:35,PAGEUP:33,PAGEDOWN:34,INSERT:45,SPACE:32},f=[{label:"SUN"},{label:"MON"},{label:"TUE"},{label:"WED"},{label:"THU"},{label:"FRI"},{label:"SAT"}],c=function(e,t,r,n,o,i){return e=navigator.userAgent.toLowerCase(),t=-1!=e.search(/mobile/g),i,-1!=e.search(/iphone/g)?{name:"iphone",version:0,mobile:!0}:-1!=e.search(/ipad/g)?{name:"ipad",version:0,mobile:!0}:-1!=e.search(/android/g)?(n=/(android)[ \/]([\w.]+)/.exec(e)||[],i=n[2]||"0",{name:"android",version:i,mobile:t}):(r="",n=/(opr)[ \/]([\w.]+)/.exec(e)||/(chrome)[ \/]([\w.]+)/.exec(e)||/(webkit)[ \/]([\w.]+)/.exec(e)||/(msie) ([\w.]+)/.exec(e)||e.indexOf("compatible")<0&&/(mozilla)(?:.*? rv:([\w.]+)|)/.exec(e)||[],o=n[1]||"",i=n[2]||"0","msie"==o&&(o="ie"),{name:o,version:i,mobile:t})}(),d=!("undefined"==typeof window||"undefined"==typeof navigator||!o.document),p=/Firefox/i.test(navigator.userAgent)?"DOMMouseScroll":"mousewheel",g={ax5dialog:{501:"Duplicate call error"},"single-uploader":{460:"There are no files to be uploaded.",461:"There is no uploaded files."},ax5calendar:{401:"Can not find target element"}};return{errorMsg:g,version:a,baseUrl:u,onerror:l,eventKeys:s,weekNames:f,browser:c,isBrowser:d,wheelEnm:p,urlUtil:r,getError:n}}(),y.util=t=function(){function t(e,t){if(R(e))return[];var r,n=0,o=e.length,i=void 0===o||"function"==typeof e;if(i){for(r in e)if("undefined"!=typeof e[r]&&t.call(e[r],r,e[r])===!1)break}else for(;o>n&&("undefined"==typeof e[n]||t.call(e[n],n,e[n++])!==!1););return e}function b(e,t){if(R(e))return[];var r,n,o=0,i=e.length,a=[];if(S(e)){for(r in e)if("undefined"!=typeof e[r]){if(n=void 0,(n=t.call(e[r],r,e[r]))===!1)break;a.push(n)}}else for(;i>o;)if("undefined"!=typeof e[o]){if(n=void 0,(n=t.call(e[o],o,e[o++]))===!1)break;a.push(n)}return a}function v(e,t){if(R(e))return-1;var r,n=0,o=e.length;if(S(e))for(r in e){if("undefined"!=typeof e[r]&&M(t)&&t.call(e[r],r,e[r]))return r;if(e[r]==t)return r}else for(;o>n;){if("undefined"!=typeof e[n]&&M(t)&&t.call(e[n],n,e[n]))return n;if(e[n]==t)return n;n++}return-1}function w(e,t){var r,o,i;if(A(e)){for(r=0,o=e.length,i=e[r];o-1>r&&("undefined"==typeof e[r]||(i=t.call(n,i,e[++r]))!==!1););return i}if(S(e)){for(r in e)if("undefined"!=typeof e[r]&&(i=t.call(n,i,e[r]))===!1)break;return i}return console.error("argument error : ax5.util.reduce - use Array or Object"),null}function T(e,t){for(var r=e.length-1,o=e[r];r>0&&("undefined"==typeof e[r]||(o=t.call(n,o,e[--r]))!==!1););return o}function x(e,t){if(R(e))return[];var r,n,o=0,i=e.length,a=[];if(S(e))for(r in e)"undefined"!=typeof e[r]&&(n=t.call(e[r],r,e[r]))&&a.push(e[r]);else for(;i>o;)"undefined"!=typeof e[o]&&((n=t.call(e[o],o,e[o]))&&a.push(e[o]),o++);return a}function N(e){var r="";if(y.util.isArray(e)){var n=0,o=e.length;for(r+="[";o>n;n++)n>0&&(r+=","),r+=N(e[n]);r+="]"}else if(y.util.isObject(e)){r+="{";var i=[];t(e,function(e,t){i.push('"'+e+'": '+N(t))}),r+=i.join(", "),r+="}"}else y.util.isString(e)?r='"'+e+'"':y.util.isNumber(e)?r=e:y.util.isUndefined(e)?r="undefined":y.util.isFunction(e)&&(r='"{Function}"');return r}function D(e,t){if(!t&&!a.test(e))return{error:500,msg:"syntax error"};try{return new Function("","return "+e)()}catch(r){return{error:500,msg:"syntax error"}}}function E(e){var t;return null!=e&&e==e.window?t="window":e&&1==e.nodeType?t="element":e&&11==e.nodeType?t="fragment":"undefined"==typeof e?t="undefined":"[object Object]"==se.call(e)?t="object":"[object Array]"==se.call(e)?t="array":"[object String]"==se.call(e)?t="string":"[object Number]"==se.call(e)?t="number":"[object NodeList]"==se.call(e)?t="nodelist":"function"==typeof e&&(t="function"),t}function j(e){return null!=e&&e==e.window}function O(e){return!(!e||1!=e.nodeType&&11!=e.nodeType)}function S(e){return"[object Object]"==se.call(e)}function A(e){return"[object Array]"==se.call(e)}function M(e){return"function"==typeof e}function k(e){return"[object String]"==se.call(e)}function C(e){return"[object Number]"==se.call(e)}function F(e){return"[object NodeList]"==se.call(e)||e&&e[0]&&1==e[0].nodeType}function U(e){return"undefined"==typeof e}function R(e){return"undefined"==typeof e||null===e||""===e}function P(e){return e instanceof Date&&!isNaN(e.valueOf())}function Y(e){var t=!1;if(e){if(e instanceof Date&&!isNaN(e.valueOf()))t=!0;else if(e=e.replace(/\D/g,""),e.length>7){var r=e.substr(4,2),n=e.substr(6,2);e=ee(e),e.getMonth()==r-1&&e.getDate()==n&&(t=!0)}}else;return t}function $(e){if(S(e)){var t=Object.keys(e),r={};return r[t[0]]=e[t[0]],r}return A(e)?e[0]:void console.error("ax5.util.object.first","argument type error")}function z(e){if(S(e)){var t=Object.keys(e),r={};return r[t[t.length-1]]=e[t[t.length-1]],r}return A(e)?e[e.length-1]:void console.error("ax5.util.object.last","argument type error")}function B(e,t,r,n){var o;return"number"==typeof r&&(o=new Date,o.setDate(o.getDate()+r)),n=n||{},i.cookie=[escape(e),"=",escape(t),o?"; expires="+o.toUTCString():"",n.path?"; path="+n.path:"",n.domain?"; domain="+n.domain:"",n.secure?"; secure":""].join("")}function H(e){for(var t=e+"=",r=i.cookie.split(";"),n=0,o=r.length;o>n;n++){for(var a=r[n];" "==a.charAt(0);)a=a.substring(1);if(-1!=a.indexOf(t))return unescape(a.substring(t.length,a.length))}return""}function L(t,n,o){for(var a,u,l=i.head||i.getElementsByTagName("head")[0],s=e.isBrowser&&"PLAYSTATION 3"===navigator.platform?/^complete$/:/^(complete|loaded)$/,f=t.length,c=[],d={},p=!1,g=r.get("script[src]"),h=(r.get("style[href]"),function(){1>f&&0==c.length&&!p&&(n&&n({}),p=!0)}),m=function(){1>f&&c.length>0&&!p&&(console.error(c),o&&o({type:"loadFail",list:c}),p=!0)},b=0,v=t.length;v>b;b++){for(var w,T,x,N=t[b],D=_(N,"."),E=!1,j=e.baseUrl+N,O="js"===D?"src":"href",S=g.length;S--;)if(g[S].getAttribute(O)===j){E=!0;break}E?(f--,h()):(w="js"===D?r.create("script",{type:"text/javascript",src:j,"data-src":j}):r.create("link",{rel:"stylesheet",type:"text/css",href:j}),T=function(e,t){e&&("load"===e.type||s.test((e.currentTarget||e.srcElement).readyState))&&(d[t]||f--,a&&clearTimeout(a),a=setTimeout(h,1))},x=function(t){f--,c.push({src:e.baseUrl+N,error:t}),u&&clearTimeout(u),u=setTimeout(m,1)},y.xhr({url:j,contentType:"",res:function(e,t){for(var n,o=!1,i=r.get("script[src]"),a=i.length;a--;)if(i[a].getAttribute(O)===j){o=!0;break}o||l.appendChild(w),w.onload=function(e){T(e,j),n&&clearTimeout(n)},n=setTimeout(function(){T({type:"load"},j)},500)},error:function(){x(this)}}))}}function W(e){return o.alert(N(e)),e}function I(e,t){return"undefined"==typeof e||"undefined"==typeof t?"":k(t)?e.indexOf(t)>-1?e.substr(0,e.indexOf(t)):e:C(t)?e.substr(0,t):""}function _(e,t){return"undefined"==typeof e||"undefined"==typeof t?"":(e=""+e,k(t)?e.lastIndexOf(t)>-1?e.substr(e.lastIndexOf(t)+1):e:C(t)?e.substr(e.length-t):"")}function q(e){return e.replace(u,"ms-").replace(l,function(e,t){return t.toUpperCase()})}function G(e){return q(e).replace(s,function(e,t){return"-"+t.toLowerCase()})}function J(e,r){var n,o=(""+e).split(f),i=Number(o[0])<0||"-0"==o[0],a=0;return o[0]=o[0].replace(c,""),o[1]?(o[1]=o[1].replace(d,""),a=Number(o[0]+"."+o[1])||0):a=Number(o[0])||0,n=i?-a:a,t(r,function(e,t){"round"==e&&(n=C(t)?0>t?+(Math.round(n+"e-"+Math.abs(t))+"e+"+Math.abs(t)):+(Math.round(n+"e+"+t)+"e-"+t):Math.round(n)),"floor"==e&&(n=Math.floor(n)),"ceil"==e?n=Math.ceil(n):"money"==e?n=function(e){var t=""+e;if(isNaN(t)||""==t)return"";var r=t.split(".");r[0]+=".";do r[0]=r[0].replace(p,"$1,$2");while(p.test(r[0]));return r.length>1?r.join(""):r[0].split(".")[0]}(n):"abs"==e?n=Math.abs(Number(n)):"byte"==e&&(n=function(e){e=Number(n);var t="KB",r=e/1024;return r/1024>1&&(t="MB",r/=1024),r/1024>1&&(t="GB",r/=1024),J(r,{round:1})+t}(n))}),n}function K(e){return"undefined"!=typeof e.length?Array.prototype.slice.call(e):[]}function X(e,t){var r=t.length,n=e.length,o=0;if("number"==typeof r)for(;r>o;o++)e[n++]=t[o];else for(;void 0!==t[o];)e[n++]=t[o++];return e.length=n,e}function Q(e,r){var n;return k(e)&&"undefined"!=typeof r&&"param"==r?e:k(e)&&"undefined"!=typeof r&&"object"==r||k(e)&&"undefined"==typeof r?(n={},t(e.split(g),function(){var e=this.split(h);n[e[0]]=e[1]}),n):(n=[],t(e,function(e,t){n.push(e+"="+escape(t))}),n.join("&"))}function Z(){y.info.onerror.apply(this,arguments)}function V(e,t,r,n,o,i){var a,u;return u=new Date,"undefined"==typeof n&&(n=23),"undefined"==typeof o&&(o=59),a=new Date(Date.UTC(e,t,r||1,n,o,i||0)),0==t&&1==r&&a.getUTCHours()+a.getTimezoneOffset()/60<0?a.setUTCHours(0):a.setUTCHours(a.getUTCHours()+a.getTimezoneOffset()/60),a}function ee(t,r){var n,o,i,a,u,l,s,f,c,d;if(k(t))if(0==t.length)t=new Date;else if(t.length>15)l=t.split(/ /g),c=l[0].split(/\D/g),n=c[0],o=parseFloat(c[1]),i=parseFloat(c[2]),f=l[1]||"09:00",s=f.left(5).split(":"),a=parseFloat(s[0]),u=parseFloat(s[1]),("AM"===f.right(2)||"PM"===f.right(2))&&(a+=12),t=V(n,o-1,i,a,u);else if(14==t.length)d=t.replace(/\D/g,""),t=V(d.substr(0,4),d.substr(4,2)-1,J(d.substr(6,2)),J(d.substr(8,2)),J(d.substr(10,2)),J(d.substr(12,2)));else if(t.length>7)d=t.replace(/\D/g,""),t=V(d.substr(0,4),d.substr(4,2)-1,J(d.substr(6,2)));else if(t.length>4)d=t.replace(/\D/g,""),t=V(d.substr(0,4),d.substr(4,2)-1,1);else{if(t.length>2)return d=t.replace(/\D/g,""),V(d.substr(0,4),d.substr(4,2)-1,1);t=new Date}return"undefined"==typeof r?t:(r.add&&(t=function(e,t){var r,n,o,i,a=864e5;return"undefined"!=typeof t.d?e.setTime(e.getTime()+t.d*a):"undefined"!=typeof t.m?(r=e.getFullYear(),n=e.getMonth(),o=e.getDate(),r+=parseInt(t.m/12),n+=t.m%12,i=ne(r,n),o>i&&(o=i),e=new Date(r,n,o,12)):"undefined"!=typeof t.y?e.setTime(e.getTime()+365*t.y*a):e.setTime(e.getTime()+t.y*a),e}(new Date(t),r.add)),r["return"]?function(){var n,o,i,a,u,l,s,f=r["return"];n=t.getUTCFullYear(),o=oe(t.getMonth()+1,2),i=oe(t.getDate(),2),a=oe(t.getHours(),2),u=oe(t.getMinutes(),2),l=oe(t.getSeconds(),2),s=t.getDay();var c=/[^y]*(yyyy)[^y]*/gi;c.exec(f);var d=RegExp.$1,p=/[^m]*(mm)[^m]*/gi;p.exec(f);var g=RegExp.$1,h=/[^d]*(dd)[^d]*/gi;h.exec(f);var m=RegExp.$1,y=/[^h]*(hh)[^h]*/gi;y.exec(f);var b=RegExp.$1,v=/[^m]*(mi)[^i]*/gi;v.exec(f);var w=RegExp.$1,T=/[^s]*(ss)[^s]*/gi;T.exec(f);var x=RegExp.$1,N=/[^d]*(dw)[^w]*/gi;N.exec(f);var D=RegExp.$1;return"yyyy"===d&&(f=f.replace(d,_(n,d.length))),"mm"===g&&(1==g.length&&(o=t.getMonth()+1),f=f.replace(g,o)),"dd"===m&&(1==m.length&&(i=t.getDate()),f=f.replace(m,i)),"hh"===b&&(f=f.replace(b,a)),"mi"===w&&(f=f.replace(w,u)),"ss"===x&&(f=f.replace(x,l)),"dw"==D&&(f=f.replace(D,e.weekNames[s].label)),f}():t)}function te(e,t){function r(e){return Math.floor(e.getTime()/a)*a}var n,o,i=ee(e),a=864e5,u=new Date;return"undefined"==typeof t?n=J((r(i)-r(u))/a,{floor:!0}):(n=J((r(i)-r(u))/a,{floor:!0}),t.today&&(u=ee(t.today),n=J((r(i)-r(u))/a,{floor:!0})),t.thisYear&&(o=new Date(u.getFullYear(),i.getMonth(),i.getDate()),n=J((r(o)-r(u))/a,{floor:!0}),0>n&&(o=new Date(u.getFullYear()+1,i.getMonth(),i.getDate()),n=J((r(o)-r(u))/a,{floor:!0}))),t.age&&(o=new Date(u.getFullYear(),i.getMonth(),i.getDate()),n=o.getFullYear()-i.getFullYear()),n)}function re(e){var t=ee(e);return{year:t.getFullYear(),month:t.getMonth()+1,count:parseInt(t.getDate()/7+1)}}function ne(e,t){return 3==t||5==t||8==t||10==t?30:1==t?e%4==0&&e%100!=0||e%400==0?29:28:31}function oe(e,t,r,n){var o=e.toString(n||10);return ie(r||"0",t-o.length)+o}function ie(e,t){return 1>t?"":new Array(t+1).join(e)}function ae(e,t){if(e)for(;function(){var r=!0;if("undefined"==typeof t)e=e.parentNode?e.parentNode:!1;else if(M(t))r=t(e);else if(S(t))for(var n in t)if("tagname"===n){if(e.tagName.toLocaleLowerCase()!=t[n]){r=!1;break}}else if("clazz"===n||"class_name"===n){if(!("className"in e)){r=!1;break}for(var o=e.className.split(m),i=!1,a=0;aa;a++)e.call(o,r[a])&&u.push(r[a]);return u}}()),Array.prototype.forEach||(Array.prototype.forEach=function(e){if(void 0===this||null===this)throw TypeError();var t=Object(this),r=t.length>>>0;if("function"!=typeof e)throw TypeError();var n,o=arguments[1];for(n=0;r>n;n++)n in t&&e.call(o,t[n],n,t)}),Function.prototype.bind||(Function.prototype.bind=function(e){function t(){}if("function"!=typeof this)throw TypeError("function");var r=[].slice,n=r.call(arguments,1),o=this,i=function(){return o.apply(this instanceof t?this:e,n.concat(r.call(arguments)))};return t.prototype=o.prototype,i.prototype=new t,i}),function(){if(!document.querySelectorAll&&!document.querySelector&&document.createStyleSheet){var e=document.createStyleSheet(),t=function(t,r){var n,o=document.all,i=o.length,a=[];for(e.addRule(t,"foo:bar"),n=0;i>n&&!("bar"===o[n].currentStyle.foo&&(a.push(o[n]),a.length>r));n+=1);return e.removeRule(0),a};document.querySelectorAll=function(e){return t(e,1/0)},document.querySelector=function(e){return t(e,1)[0]||null}}}(),String.prototype.trim||!function(){String.prototype.trim=function(){return this.replace(t,"")}}(),window.JSON||(window.JSON={parse:function(e){return new Function("","return "+e)()},stringify:function(){var e,t=/["]/g;return e=function(r){var n,o,i;switch(n=typeof r){case"string":return'"'+r.replace(t,'\\"')+'"';case"number":case"boolean":return r.toString();case"undefined":return"undefined";case"function":return'""';case"object":if(!r)return"null";if(n="",r.splice){for(o=0,i=r.length;i>o;o++)n+=","+e(r[o]);return"["+n.substr(1)+"]"}for(o in r)r.hasOwnProperty(o)&&void 0!==r[o]&&"function"!=typeof r[o]&&(n+=',"'+o+'":'+e(r[o]));return"{"+n.substr(1)+"}"}}}()}),function(e){for(var t,r,n={},o=function(){},i="memory".split(","),a="assert,clear,count,debug,dir,dirxml,error,exception,group,groupCollapsed,groupEnd,info,log,markTimeline,profile,profiles,profileEnd,show,table,time,timeEnd,timeline,timelineEnd,timeStamp,trace,warn".split(",");t=i.pop();)e[t]=e[t]||n;for(;r=a.pop();)e[r]=e[r]||o}(e.console=e.console||{});var r=document.getElementsByTagName("html")[0];document.getElementsByTagName("body")[0];window.innerWidth||(window.innerWidth=r.clientWidth),window.innerHeight||(window.innerHeight=r.clientHeight),window.scrollX||(window.scrollX=window.pageXOffset||r.scrollLeft),window.scrollY||(window.scrollY=window.pageYOffset||r.scrollTop)}.call(this),ax5.ui=function(e){function t(){this.config={},this.name="root",this.setConfig=function(e,t){return jQuery.extend(!0,this.config,e,!0),("undefined"==typeof t||t===!0)&&this.init(),this},this.init=function(){console.log(this.config)},this.bindWindowResize=function(e){setTimeout(function(){jQuery(window).resize(function(){this.bindWindowResize__&&clearTimeout(this.bindWindowResize__),this.bindWindowResize__=setTimeout(function(){e.call(this)}.bind(this),10)}.bind(this))}.bind(this),100)},this.stopEvent=function(e){return e.preventDefault&&e.preventDefault(),e.stopPropagation&&e.stopPropagation(),e.cancelBubble=!0,!1},this.main=function(){}.apply(this,arguments)}return{root:t}}(ax5); \ No newline at end of file +(function(){"use strict";var e,t,n,r=this,o=window,i=document,a=(document.documentElement,/^(["'](\\.|[^"\\\n\r])*?["']|[,:{}\[\]0-9.\-+Eaeflnr-u \n\r\t])+?$/),u=/^-ms-/,s=/[\-_]([\da-z])/gi,l=/([A-Z])/g,c=/\./,f=/[-|+]?[\D]/gi,p=/\D/gi,d=new RegExp("([0-9])([0-9][0-9][0-9][,.])"),h=/&/g,g=/=/,m=/[ ]+/g,y={};y.guid=1,y.getGuid=function(){return y.guid++},y.info=e=function(){function n(e,n){return e={href:o.location.href,param:o.location.search,referrer:i.referrer,pathname:o.location.pathname,hostname:o.location.hostname,port:o.location.port},n=e.href.split(/[\?#]/),e.param=e.param.replace("?",""),e.url=n[0],e.href.search("#")>-1&&(e.hashdata=t.last(n)),n=null,e.baseUrl=t.left(e.href,"?").replace(e.pathname,""),e}function r(t,n,r){return e.errorMsg&&e.errorMsg[t]?{className:t,errorCode:n,methodName:r,msg:e.errorMsg[t][n]}:{className:t,errorCode:n,methodName:r}}var a="0.0.1",u="",s=function(){console.error(t.toArray(arguments).join(":"))},l={BACKSPACE:8,TAB:9,RETURN:13,ESC:27,LEFT:37,UP:38,RIGHT:39,DOWN:40,DELETE:46,HOME:36,END:35,PAGEUP:33,PAGEDOWN:34,INSERT:45,SPACE:32},c=[{label:"SUN"},{label:"MON"},{label:"TUE"},{label:"WED"},{label:"THU"},{label:"FRI"},{label:"SAT"}],f=function(e,t,n,r,o,i){return e=navigator.userAgent.toLowerCase(),t=-1!=e.search(/mobile/g),i,-1!=e.search(/iphone/g)?{name:"iphone",version:0,mobile:!0}:-1!=e.search(/ipad/g)?{name:"ipad",version:0,mobile:!0}:-1!=e.search(/android/g)?(r=/(android)[ \/]([\w.]+)/.exec(e)||[],i=r[2]||"0",{name:"android",version:i,mobile:t}):(n="",r=/(opr)[ \/]([\w.]+)/.exec(e)||/(chrome)[ \/]([\w.]+)/.exec(e)||/(webkit)[ \/]([\w.]+)/.exec(e)||/(msie) ([\w.]+)/.exec(e)||e.indexOf("compatible")<0&&/(mozilla)(?:.*? rv:([\w.]+)|)/.exec(e)||[],o=r[1]||"",i=r[2]||"0","msie"==o&&(o="ie"),{name:o,version:i,mobile:t})}(),p=!("undefined"==typeof window||"undefined"==typeof navigator||!o.document),d=/Firefox/i.test(navigator.userAgent)?"DOMMouseScroll":"mousewheel",h={ax5dialog:{501:"Duplicate call error"},"single-uploader":{460:"There are no files to be uploaded.",461:"There is no uploaded files."},ax5calendar:{401:"Can not find target element"}};return{errorMsg:h,version:a,baseUrl:u,onerror:s,eventKeys:l,weekNames:c,browser:f,isBrowser:p,wheelEnm:d,urlUtil:n,getError:r}}(),y.util=t=function(){function t(e,t){if(R(e))return[];var n,r=0,o=e.length,i=void 0===o||"function"==typeof e;if(i){for(n in e)if("undefined"!=typeof e[n]&&t.call(e[n],n,e[n])===!1)break}else for(;o>r&&("undefined"==typeof e[r]||t.call(e[r],r,e[r++])!==!1););return e}function b(e,t){if(R(e))return[];var n,r,o=0,i=e.length,a=[];if(O(e)){for(n in e)if("undefined"!=typeof e[n]){if(r=void 0,(r=t.call(e[n],n,e[n]))===!1)break;a.push(r)}}else for(;i>o;)if("undefined"!=typeof e[o]){if(r=void 0,(r=t.call(e[o],o,e[o++]))===!1)break;a.push(r)}return a}function v(e,t){if(R(e))return-1;var n,r=0,o=e.length;if(O(e))for(n in e){if("undefined"!=typeof e[n]&&A(t)&&t.call(e[n],n,e[n]))return n;if(e[n]==t)return n}else for(;o>r;){if("undefined"!=typeof e[r]&&A(t)&&t.call(e[r],r,e[r]))return r;if(e[r]==t)return r;r++}return-1}function w(e,t){var n,o,i;if(S(e)){for(n=0,o=e.length,i=e[n];o-1>n&&("undefined"==typeof e[n]||(i=t.call(r,i,e[++n]))!==!1););return i}if(O(e)){for(n in e)if("undefined"!=typeof e[n]&&(i=t.call(r,i,e[n]))===!1)break;return i}return console.error("argument error : ax5.util.reduce - use Array or Object"),null}function T(e,t){for(var n=e.length-1,o=e[n];n>0&&("undefined"==typeof e[n]||(o=t.call(r,o,e[--n]))!==!1););return o}function x(e,t){if(R(e))return[];var n,r,o=0,i=e.length,a=[];if(O(e))for(n in e)"undefined"!=typeof e[n]&&(r=t.call(e[n],n,e[n]))&&a.push(e[n]);else for(;i>o;)"undefined"!=typeof e[o]&&((r=t.call(e[o],o,e[o]))&&a.push(e[o]),o++);return a}function E(e){var n="";if(y.util.isArray(e)){var r=0,o=e.length;for(n+="[";o>r;r++)r>0&&(n+=","),n+=E(e[r]);n+="]"}else if(y.util.isObject(e)){n+="{";var i=[];t(e,function(e,t){i.push('"'+e+'": '+E(t))}),n+=i.join(", "),n+="}"}else y.util.isString(e)?n='"'+e+'"':y.util.isNumber(e)?n=e:y.util.isUndefined(e)?n="undefined":y.util.isFunction(e)&&(n='"{Function}"');return n}function N(e,t){if(!t&&!a.test(e))return{error:500,msg:"syntax error"};try{return new Function("","return "+e)()}catch(n){return{error:500,msg:"syntax error"}}}function D(e){var t;return null!=e&&e==e.window?t="window":e&&1==e.nodeType?t="element":e&&11==e.nodeType?t="fragment":"undefined"==typeof e?t="undefined":"[object Object]"==le.call(e)?t="object":"[object Array]"==le.call(e)?t="array":"[object String]"==le.call(e)?t="string":"[object Number]"==le.call(e)?t="number":"[object NodeList]"==le.call(e)?t="nodelist":"function"==typeof e&&(t="function"),t}function j(e){return null!=e&&e==e.window}function k(e){return!(!e||1!=e.nodeType&&11!=e.nodeType)}function O(e){return"[object Object]"==le.call(e)}function S(e){return"[object Array]"==le.call(e)}function A(e){return"function"==typeof e}function U(e){return"[object String]"==le.call(e)}function M(e){return"[object Number]"==le.call(e)}function C(e){return"[object NodeList]"==le.call(e)||e&&e[0]&&1==e[0].nodeType}function F(e){return"undefined"==typeof e}function R(e){return"undefined"==typeof e||null===e||""===e}function P(e){return e instanceof Date&&!isNaN(e.valueOf())}function _(e){var t=!1;if(e){if(e instanceof Date&&!isNaN(e.valueOf()))t=!0;else if(e=e.replace(/\D/g,""),e.length>7){var n=e.substr(4,2),r=e.substr(6,2);e=ee(e),e.getMonth()==n-1&&e.getDate()==r&&(t=!0)}}else;return t}function $(e){if(O(e)){var t=Object.keys(e),n={};return n[t[0]]=e[t[0]],n}return S(e)?e[0]:void console.error("ax5.util.object.first","argument type error")}function I(e){if(O(e)){var t=Object.keys(e),n={};return n[t[t.length-1]]=e[t[t.length-1]],n}return S(e)?e[e.length-1]:void console.error("ax5.util.object.last","argument type error")}function Y(e,t,n,r){var o;return"number"==typeof n&&(o=new Date,o.setDate(o.getDate()+n)),r=r||{},i.cookie=[escape(e),"=",escape(t),o?"; expires="+o.toUTCString():"",r.path?"; path="+r.path:"",r.domain?"; domain="+r.domain:"",r.secure?"; secure":""].join("")}function z(e){for(var t=e+"=",n=i.cookie.split(";"),r=0,o=n.length;o>r;r++){for(var a=n[r];" "==a.charAt(0);)a=a.substring(1);if(-1!=a.indexOf(t))return unescape(a.substring(t.length,a.length))}return""}function W(t,r,o){for(var a,u,s=i.head||i.getElementsByTagName("head")[0],l=e.isBrowser&&"PLAYSTATION 3"===navigator.platform?/^complete$/:/^(complete|loaded)$/,c=t.length,f=[],p={},d=!1,h=n.get("script[src]"),g=(n.get("style[href]"),function(){1>c&&0==f.length&&!d&&(r&&r({}),d=!0)}),m=function(){1>c&&f.length>0&&!d&&(console.error(f),o&&o({type:"loadFail",list:f}),d=!0)},b=0,v=t.length;v>b;b++){for(var w,T,x,E=t[b],N=L(E,"."),D=!1,j=e.baseUrl+E,k="js"===N?"src":"href",O=h.length;O--;)if(h[O].getAttribute(k)===j){D=!0;break}D?(c--,g()):(w="js"===N?n.create("script",{type:"text/javascript",src:j,"data-src":j}):n.create("link",{rel:"stylesheet",type:"text/css",href:j}),T=function(e,t){e&&("load"===e.type||l.test((e.currentTarget||e.srcElement).readyState))&&(p[t]||c--,a&&clearTimeout(a),a=setTimeout(g,1))},x=function(t){c--,f.push({src:e.baseUrl+E,error:t}),u&&clearTimeout(u),u=setTimeout(m,1)},y.xhr({url:j,contentType:"",res:function(e,t){for(var r,o=!1,i=n.get("script[src]"),a=i.length;a--;)if(i[a].getAttribute(k)===j){o=!0;break}o||s.appendChild(w),w.onload=function(e){T(e,j),r&&clearTimeout(r)},r=setTimeout(function(){T({type:"load"},j)},500)},error:function(){x(this)}}))}}function B(e){return o.alert(E(e)),e}function H(e,t){return"undefined"==typeof e||"undefined"==typeof t?"":U(t)?e.indexOf(t)>-1?e.substr(0,e.indexOf(t)):e:M(t)?e.substr(0,t):""}function L(e,t){return"undefined"==typeof e||"undefined"==typeof t?"":(e=""+e,U(t)?e.lastIndexOf(t)>-1?e.substr(e.lastIndexOf(t)+1):e:M(t)?e.substr(e.length-t):"")}function q(e){return e.replace(u,"ms-").replace(s,function(e,t){return t.toUpperCase()})}function V(e){return q(e).replace(l,function(e,t){return"-"+t.toLowerCase()})}function G(e,n){var r,o=(""+e).split(c),i=Number(o[0])<0||"-0"==o[0],a=0;return o[0]=o[0].replace(f,""),o[1]?(o[1]=o[1].replace(p,""),a=Number(o[0]+"."+o[1])||0):a=Number(o[0])||0,r=i?-a:a,t(n,function(e,t){"round"==e&&(r=M(t)?0>t?+(Math.round(r+"e-"+Math.abs(t))+"e+"+Math.abs(t)):+(Math.round(r+"e+"+t)+"e-"+t):Math.round(r)),"floor"==e&&(r=Math.floor(r)),"ceil"==e?r=Math.ceil(r):"money"==e?r=function(e){var t=""+e;if(isNaN(t)||""==t)return"";var n=t.split(".");n[0]+=".";do n[0]=n[0].replace(d,"$1,$2");while(d.test(n[0]));return n.length>1?n.join(""):n[0].split(".")[0]}(r):"abs"==e?r=Math.abs(Number(r)):"byte"==e&&(r=function(e){e=Number(r);var t="KB",n=e/1024;return n/1024>1&&(t="MB",n/=1024),n/1024>1&&(t="GB",n/=1024),G(n,{round:1})+t}(r))}),r}function J(e){return"undefined"!=typeof e.length?Array.prototype.slice.call(e):[]}function K(e,t){var n=t.length,r=e.length,o=0;if("number"==typeof n)for(;n>o;o++)e[r++]=t[o];else for(;void 0!==t[o];)e[r++]=t[o++];return e.length=r,e}function X(e,n){var r;return U(e)&&"undefined"!=typeof n&&"param"==n?e:U(e)&&"undefined"!=typeof n&&"object"==n||U(e)&&"undefined"==typeof n?(r={},t(e.split(h),function(){var e=this.split(g);r[e[0]]=e[1]}),r):(r=[],t(e,function(e,t){r.push(e+"="+escape(t))}),r.join("&"))}function Q(){y.info.onerror.apply(this,arguments)}function Z(e,t,n,r,o,i){var a,u;return u=new Date,"undefined"==typeof r&&(r=23),"undefined"==typeof o&&(o=59),a=new Date(Date.UTC(e,t,n||1,r,o,i||0)),0==t&&1==n&&a.getUTCHours()+a.getTimezoneOffset()/60<0?a.setUTCHours(0):a.setUTCHours(a.getUTCHours()+a.getTimezoneOffset()/60),a}function ee(t,n){var r,o,i,a,u,s,l,c,f,p;if(U(t))if(0==t.length)t=new Date;else if(t.length>15)s=t.split(/ /g),f=s[0].split(/\D/g),r=f[0],o=parseFloat(f[1]),i=parseFloat(f[2]),c=s[1]||"09:00",l=c.left(5).split(":"),a=parseFloat(l[0]),u=parseFloat(l[1]),("AM"===c.right(2)||"PM"===c.right(2))&&(a+=12),t=Z(r,o-1,i,a,u);else if(14==t.length)p=t.replace(/\D/g,""),t=Z(p.substr(0,4),p.substr(4,2)-1,G(p.substr(6,2)),G(p.substr(8,2)),G(p.substr(10,2)),G(p.substr(12,2)));else if(t.length>7)p=t.replace(/\D/g,""),t=Z(p.substr(0,4),p.substr(4,2)-1,G(p.substr(6,2)));else if(t.length>4)p=t.replace(/\D/g,""),t=Z(p.substr(0,4),p.substr(4,2)-1,1);else{if(t.length>2)return p=t.replace(/\D/g,""),Z(p.substr(0,4),p.substr(4,2)-1,1);t=new Date}return"undefined"==typeof n?t:(n.add&&(t=function(e,t){var n,r,o,i,a=864e5;return"undefined"!=typeof t.d?e.setTime(e.getTime()+t.d*a):"undefined"!=typeof t.m?(n=e.getFullYear(),r=e.getMonth(),o=e.getDate(),n+=parseInt(t.m/12),r+=t.m%12,i=re(n,r),o>i&&(o=i),e=new Date(n,r,o,12)):"undefined"!=typeof t.y?e.setTime(e.getTime()+365*t.y*a):e.setTime(e.getTime()+t.y*a),e}(new Date(t),n.add)),n["return"]?function(){var r,o,i,a,u,s,l,c=n["return"];r=t.getUTCFullYear(),o=oe(t.getMonth()+1,2),i=oe(t.getDate(),2),a=oe(t.getHours(),2),u=oe(t.getMinutes(),2),s=oe(t.getSeconds(),2),l=t.getDay();var f=/[^y]*(yyyy)[^y]*/gi;f.exec(c);var p=RegExp.$1,d=/[^m]*(mm)[^m]*/gi;d.exec(c);var h=RegExp.$1,g=/[^d]*(dd)[^d]*/gi;g.exec(c);var m=RegExp.$1,y=/[^h]*(hh)[^h]*/gi;y.exec(c);var b=RegExp.$1,v=/[^m]*(mi)[^i]*/gi;v.exec(c);var w=RegExp.$1,T=/[^s]*(ss)[^s]*/gi;T.exec(c);var x=RegExp.$1,E=/[^d]*(dw)[^w]*/gi;E.exec(c);var N=RegExp.$1;return"yyyy"===p&&(c=c.replace(p,L(r,p.length))),"mm"===h&&(1==h.length&&(o=t.getMonth()+1),c=c.replace(h,o)),"dd"===m&&(1==m.length&&(i=t.getDate()),c=c.replace(m,i)),"hh"===b&&(c=c.replace(b,a)),"mi"===w&&(c=c.replace(w,u)),"ss"===x&&(c=c.replace(x,s)),"dw"==N&&(c=c.replace(N,e.weekNames[l].label)),c}():t)}function te(e,t){function n(e){return Math.floor(e.getTime()/a)*a}var r,o,i=ee(e),a=864e5,u=new Date;return"undefined"==typeof t?r=G((n(i)-n(u))/a,{floor:!0}):(r=G((n(i)-n(u))/a,{floor:!0}),t.today&&(u=ee(t.today),r=G((n(i)-n(u))/a,{floor:!0})),t.thisYear&&(o=new Date(u.getFullYear(),i.getMonth(),i.getDate()),r=G((n(o)-n(u))/a,{floor:!0}),0>r&&(o=new Date(u.getFullYear()+1,i.getMonth(),i.getDate()),r=G((n(o)-n(u))/a,{floor:!0}))),t.age&&(o=new Date(u.getFullYear(),i.getMonth(),i.getDate()),r=o.getFullYear()-i.getFullYear()),r)}function ne(e){var t=ee(e);return{year:t.getFullYear(),month:t.getMonth()+1,count:parseInt(t.getDate()/7+1)}}function re(e,t){return 3==t||5==t||8==t||10==t?30:1==t?e%4==0&&e%100!=0||e%400==0?29:28:31}function oe(e,t,n,r){var o=e.toString(r||10);return ie(n||"0",t-o.length)+o}function ie(e,t){return 1>t?"":new Array(t+1).join(e)}function ae(e,t){if(e)for(;function(){var n=!0;if("undefined"==typeof t)e=e.parentNode?e.parentNode:!1;else if(A(t))n=t(e);else if(O(t))for(var r in t)if("tagname"===r){if(e.tagName.toLocaleLowerCase()!=t[r]){n=!1;break}}else if("clazz"===r||"class_name"===r){if(!("className"in e)){n=!1;break}for(var o=e.className.split(m),i=!1,a=0;aa;a++)e.call(o,n[a])&&u.push(n[a]);return u}}()),Array.prototype.forEach||(Array.prototype.forEach=function(e){if(void 0===this||null===this)throw TypeError();var t=Object(this),n=t.length>>>0;if("function"!=typeof e)throw TypeError();var r,o=arguments[1];for(r=0;n>r;r++)r in t&&e.call(o,t[r],r,t)}),Function.prototype.bind||(Function.prototype.bind=function(e){function t(){}if("function"!=typeof this)throw TypeError("function");var n=[].slice,r=n.call(arguments,1),o=this,i=function(){return o.apply(this instanceof t?this:e,r.concat(n.call(arguments)))};return t.prototype=o.prototype,i.prototype=new t,i}),function(){if(!document.querySelectorAll&&!document.querySelector&&document.createStyleSheet){var e=document.createStyleSheet(),t=function(t,n){var r,o=document.all,i=o.length,a=[];for(e.addRule(t,"foo:bar"),r=0;i>r&&!("bar"===o[r].currentStyle.foo&&(a.push(o[r]),a.length>n));r+=1);return e.removeRule(0),a};document.querySelectorAll=function(e){return t(e,1/0)},document.querySelector=function(e){return t(e,1)[0]||null}}}(),String.prototype.trim||!function(){String.prototype.trim=function(){return this.replace(t,"")}}(),window.JSON||(window.JSON={parse:function(e){return new Function("","return "+e)()},stringify:function(){var e,t=/["]/g;return e=function(n){var r,o,i;switch(r=typeof n){case"string":return'"'+n.replace(t,'\\"')+'"';case"number":case"boolean":return n.toString();case"undefined":return"undefined";case"function":return'""';case"object":if(!n)return"null";if(r="",n.splice){for(o=0,i=n.length;i>o;o++)r+=","+e(n[o]);return"["+r.substr(1)+"]"}for(o in n)n.hasOwnProperty(o)&&void 0!==n[o]&&"function"!=typeof n[o]&&(r+=',"'+o+'":'+e(n[o]));return"{"+r.substr(1)+"}"}}}()}),function(e){for(var t,n,r={},o=function(){},i="memory".split(","),a="assert,clear,count,debug,dir,dirxml,error,exception,group,groupCollapsed,groupEnd,info,log,markTimeline,profile,profiles,profileEnd,show,table,time,timeEnd,timeline,timelineEnd,timeStamp,trace,warn".split(",");t=i.pop();)e[t]=e[t]||r;for(;n=a.pop();)e[n]=e[n]||o}(e.console=e.console||{});var n=document.getElementsByTagName("html")[0];document.getElementsByTagName("body")[0];window.innerWidth||(window.innerWidth=n.clientWidth),window.innerHeight||(window.innerHeight=n.clientHeight),window.scrollX||(window.scrollX=window.pageXOffset||n.scrollLeft),window.scrollY||(window.scrollY=window.pageYOffset||n.scrollTop)}.call(this),ax5.ui=function(e){function t(){this.config={},this.name="root",this.setConfig=function(e,t){return jQuery.extend(!0,this.config,e,!0),("undefined"==typeof t||t===!0)&&this.init(),this},this.init=function(){console.log(this.config)},this.bindWindowResize=function(e){setTimeout(function(){jQuery(window).resize(function(){this.bindWindowResize__&&clearTimeout(this.bindWindowResize__),this.bindWindowResize__=setTimeout(function(){e.call(this)}.bind(this),10)}.bind(this))}.bind(this),100)},this.stopEvent=function(e){return e.preventDefault&&e.preventDefault(),e.stopPropagation&&e.stopPropagation(),e.cancelBubble=!0,!1},this.main=function(){}.apply(this,arguments)}return{root:t}}(ax5),function(e,t){t(e.mustache={})}(window.ax5,function(e){function t(e){return"function"==typeof e}function n(e){return g(e)?"array":typeof e}function r(e){return e.replace(/[\-\[\]{}()*+?.,\\\^$|#\s]/g,"\\$&")}function o(e,t){return null!=e&&"object"==typeof e&&t in e}function i(e,t){return m.call(e,t)}function a(e){return!i(y,e)}function u(e){return String(e).replace(/[&<>"'\/]/g,function(e){return b[e]})}function s(t,n){function o(){if(y&&!b)for(;m.length;)delete h[m.pop()];else m=[];y=!1,b=!1}function i(e){if("string"==typeof e&&(e=e.split(w,2)),!g(e)||2!==e.length)throw new Error("Invalid tags: "+e);u=new RegExp(r(e[0])+"\\s*"),s=new RegExp("\\s*"+r(e[1])),p=new RegExp("\\s*"+r("}"+e[1]))}if(!t)return[];var u,s,p,d=[],h=[],m=[],y=!1,b=!1;i(n||e.tags);for(var N,D,j,k,O,S,A=new f(t);!A.eos();){if(N=A.pos,j=A.scanUntil(u))for(var U=0,M=j.length;M>U;++U)k=j.charAt(U),a(k)?m.push(h.length):b=!0,h.push(["text",k,N,N+1]),N+=1,"\n"===k&&o();if(!A.scan(u))break;if(y=!0,D=A.scan(E)||"name",A.scan(v),"="===D?(j=A.scanUntil(T),A.scan(T),A.scanUntil(s)):"{"===D?(j=A.scanUntil(p),A.scan(x),A.scanUntil(s),D="&"):j=A.scanUntil(s),!A.scan(s))throw new Error("Unclosed tag at "+A.pos);if(O=[D,j,N,A.pos],h.push(O),"#"===D||"^"===D)d.push(O);else if("/"===D){if(S=d.pop(),!S)throw new Error('Unopened section "'+j+'" at '+N);if(S[1]!==j)throw new Error('Unclosed section "'+S[1]+'" at '+N)}else"name"===D||"{"===D||"&"===D?b=!0:"="===D&&i(j)}if(S=d.pop())throw new Error('Unclosed section "'+S[1]+'" at '+A.pos);return c(l(h))}function l(e){for(var t,n,r=[],o=0,i=e.length;i>o;++o)t=e[o],t&&("text"===t[0]&&n&&"text"===n[0]?(n[1]+=t[1],n[3]=t[3]):(r.push(t),n=t));return r}function c(e){for(var t,n,r=[],o=r,i=[],a=0,u=e.length;u>a;++a)switch(t=e[a],t[0]){case"#":case"^":o.push(t),i.push(t),o=t[4]=[];break;case"/":n=i.pop(),n[5]=t[2],o=i.length>0?i[i.length-1][4]:r;break;default:o.push(t)}return r}function f(e){this.string=e,this.tail=e,this.pos=0}function p(e,t){this.view=e,this.cache={".":this.view},this.parent=t}function d(){this.cache={}}var h=Object.prototype.toString,g=Array.isArray||function(e){return"[object Array]"===h.call(e)},m=RegExp.prototype.test,y=/\S/,b={"&":"&","<":"<",">":">",'"':""","'":"'","/":"/"},v=/\s*/,w=/\s+/,T=/\s*=/,x=/\s*\}/,E=/#|\^|\/|>|\{|&|=|!/;f.prototype.eos=function(){return""===this.tail},f.prototype.scan=function(e){var t=this.tail.match(e);if(!t||0!==t.index)return"";var n=t[0];return this.tail=this.tail.substring(n.length),this.pos+=n.length,n},f.prototype.scanUntil=function(e){var t,n=this.tail.search(e);switch(n){case-1:t=this.tail,this.tail="";break;case 0:t="";break;default:t=this.tail.substring(0,n),this.tail=this.tail.substring(n)}return this.pos+=t.length,t},p.prototype.push=function(e){return new p(e,this)},p.prototype.lookup=function(e){var n,r=this.cache;if(r.hasOwnProperty(e))n=r[e];else{for(var i,a,u=this,s=!1;u;){if(e.indexOf(".")>0)for(n=u.view,i=e.split("."),a=0;null!=n&&as;++s)a=void 0,o=e[s],i=o[0],"#"===i?a=this.renderSection(o,t,n,r):"^"===i?a=this.renderInverted(o,t,n,r):">"===i?a=this.renderPartial(o,t,n,r):"&"===i?a=this.unescapedValue(o,t):"name"===i?a=this.escapedValue(o,t):"text"===i&&(a=this.rawValue(o)),void 0!==a&&(u+=a);return u},d.prototype.renderSection=function(e,n,r,o){function i(e){return a.render(e,n,r)}var a=this,u="",s=n.lookup(e[1]);if(s){if(g(s))for(var l=0,c=s.length;c>l;++l)s[l].__i__=l,s[l].__first__=0===l,u+=this.renderTokens(e[4],n.push(s[l]),r,o);else if("object"==typeof s||"string"==typeof s||"number"==typeof s)u+=this.renderTokens(e[4],n.push(s),r,o);else if(t(s)){if("string"!=typeof o)throw new Error("Cannot use higher-order sections without the original template");s=s.call(n.view,o.slice(e[3],e[5]),i),null!=s&&(u+=s)}else u+=this.renderTokens(e[4],n,r,o);return u}},d.prototype.renderInverted=function(e,t,n,r){var o=t.lookup(e[1]);return!o||g(o)&&0===o.length?this.renderTokens(e[4],t,n,r):void 0},d.prototype.renderPartial=function(e,n,r){if(r){var o=t(r)?r(e[1]):r[e[1]];return null!=o?this.renderTokens(this.parse(o),n,r,o):void 0}},d.prototype.unescapedValue=function(e,t){var n=t.lookup(e[1]);return null!=n?n:void 0},d.prototype.escapedValue=function(t,n){var r=n.lookup(t[1]);return null!=r?e.escape(r):void 0},d.prototype.rawValue=function(e){return e[1]},e.name="mustache.js",e.version="2.1.3",e.tags=["{{","}}"];var N=new d;e.clearCache=function(){return N.clearCache()},e.parse=function(e,t){return N.parse(e,t)},e.render=function(e,t,r){if("string"!=typeof e)throw new TypeError('Invalid template! Template should be a "string" but "'+n(e)+'" was given as the first argument for mustache#render(template, view, partials)');return N.render(e,t,r)},e.to_html=function(n,r,o,i){var a=e.render(n,r,o);return t(i)?void i(a):a},e.escape=u,e.Scanner=f,e.Context=p,e.Writer=d}); \ No newline at end of file diff --git a/package.json b/package.json index 11ea82c..e8bbe24 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "ax5core", - "version": "0.7.5", + "version": "0.8.0", "description": "`ax5core` is a collection of utility functions that have been designed for use in ax5ui", "license": "MIT", "repository": { diff --git a/src/mustache.js b/src/mustache.js new file mode 100644 index 0000000..9f651e7 --- /dev/null +++ b/src/mustache.js @@ -0,0 +1,634 @@ +/*! + * mustache.js - Logic-less {{mustache}} templates with JavaScript + * http://github.com/janl/mustache.js + * https://github.com/thomasJang/mustache.js -- imporove some variables + */ + +(function defineMustache(global, factory) { + + factory(global.mustache = {}); + +}(window.ax5, function mustacheFactory(mustache) { + + var objectToString = Object.prototype.toString; + var isArray = Array.isArray || function isArrayPolyfill(object) { + return objectToString.call(object) === '[object Array]'; + }; + + function isFunction(object) { + return typeof object === 'function'; + } + + /** + * More correct typeof string handling array + * which normally returns typeof 'object' + */ + function typeStr(obj) { + return isArray(obj) ? 'array' : typeof obj; + } + + function escapeRegExp(string) { + return string.replace(/[\-\[\]{}()*+?.,\\\^$|#\s]/g, '\\$&'); + } + + /** + * Null safe way of checking whether or not an object, + * including its prototype, has a given property + */ + function hasProperty(obj, propName) { + return obj != null && typeof obj === 'object' && (propName in obj); + } + + // Workaround for https://issues.apache.org/jira/browse/COUCHDB-577 + // See https://github.com/janl/mustache.js/issues/189 + var regExpTest = RegExp.prototype.test; + + function testRegExp(re, string) { + return regExpTest.call(re, string); + } + + var nonSpaceRe = /\S/; + + function isWhitespace(string) { + return !testRegExp(nonSpaceRe, string); + } + + var entityMap = { + '&': '&', '<': '<', '>': '>', '"': '"', "'": ''', '/': '/' + }; + + function escapeHtml(string) { + return String(string).replace(/[&<>"'\/]/g, function fromEntityMap(s) { + return entityMap[s]; + }); + } + + var whiteRe = /\s*/; + var spaceRe = /\s+/; + var equalsRe = /\s*=/; + var curlyRe = /\s*\}/; + var tagRe = /#|\^|\/|>|\{|&|=|!/; + + /** + * Breaks up the given `template` string into a tree of tokens. If the `tags` + * argument is given here it must be an array with two string values: the + * opening and closing tags used in the template (e.g. [ "<%", "%>" ]). Of + * course, the default is to use mustaches (i.e. mustache.tags). + * + * A token is an array with at least 4 elements. The first element is the + * mustache symbol that was used inside the tag, e.g. "#" or "&". If the tag + * did not contain a symbol (i.e. {{myValue}}) this element is "name". For + * all text that appears outside a symbol this element is "text". + * + * The second element of a token is its "value". For mustache tags this is + * whatever else was inside the tag besides the opening symbol. For text tokens + * this is the text itself. + * + * The third and fourth elements of the token are the start and end indices, + * respectively, of the token in the original template. + * + * Tokens that are the root node of a subtree contain two more elements: 1) an + * array of tokens in the subtree and 2) the index in the original template at + * which the closing tag for that section begins. + */ + function parseTemplate(template, tags) { + if (!template) + return []; + + var sections = []; // Stack to hold section tokens + var tokens = []; // Buffer to hold the tokens + var spaces = []; // Indices of whitespace tokens on the current line + var hasTag = false; // Is there a {{tag}} on the current line? + var nonSpace = false; // Is there a non-space char on the current line? + + // Strips all whitespace tokens array for the current line + // if there was a {{#tag}} on it and otherwise only space. + function stripSpace() { + if (hasTag && !nonSpace) { + while (spaces.length) + delete tokens[spaces.pop()]; + } + else { + spaces = []; + } + + hasTag = false; + nonSpace = false; + } + + var openingTagRe, closingTagRe, closingCurlyRe; + + function compileTags(tagsToCompile) { + if (typeof tagsToCompile === 'string') + tagsToCompile = tagsToCompile.split(spaceRe, 2); + + if (!isArray(tagsToCompile) || tagsToCompile.length !== 2) + throw new Error('Invalid tags: ' + tagsToCompile); + + openingTagRe = new RegExp(escapeRegExp(tagsToCompile[0]) + '\\s*'); + closingTagRe = new RegExp('\\s*' + escapeRegExp(tagsToCompile[1])); + closingCurlyRe = new RegExp('\\s*' + escapeRegExp('}' + tagsToCompile[1])); + } + + compileTags(tags || mustache.tags); + + var scanner = new Scanner(template); + + var start, type, value, chr, token, openSection; + while (!scanner.eos()) { + start = scanner.pos; + + // Match any text between tags. + value = scanner.scanUntil(openingTagRe); + + if (value) { + for (var i = 0, valueLength = value.length; i < valueLength; ++i) { + chr = value.charAt(i); + + if (isWhitespace(chr)) { + spaces.push(tokens.length); + } + else { + nonSpace = true; + } + + tokens.push(['text', chr, start, start + 1]); + start += 1; + + // Check for whitespace on the current line. + if (chr === '\n') + stripSpace(); + } + } + + // Match the opening tag. + if (!scanner.scan(openingTagRe)) + break; + + hasTag = true; + + // Get the tag type. + type = scanner.scan(tagRe) || 'name'; + scanner.scan(whiteRe); + + // Get the tag value. + if (type === '=') { + value = scanner.scanUntil(equalsRe); + scanner.scan(equalsRe); + scanner.scanUntil(closingTagRe); + } + else if (type === '{') { + value = scanner.scanUntil(closingCurlyRe); + scanner.scan(curlyRe); + scanner.scanUntil(closingTagRe); + type = '&'; + } + else { + value = scanner.scanUntil(closingTagRe); + } + + // Match the closing tag. + if (!scanner.scan(closingTagRe)) + throw new Error('Unclosed tag at ' + scanner.pos); + + token = [type, value, start, scanner.pos]; + tokens.push(token); + + if (type === '#' || type === '^') { + sections.push(token); + } + else if (type === '/') { + // Check section nesting. + openSection = sections.pop(); + + if (!openSection) + throw new Error('Unopened section "' + value + '" at ' + start); + + if (openSection[1] !== value) + throw new Error('Unclosed section "' + openSection[1] + '" at ' + start); + } + else if (type === 'name' || type === '{' || type === '&') { + nonSpace = true; + } + else if (type === '=') { + // Set the tags for the next time around. + compileTags(value); + } + } + + // Make sure there are no open sections when we're done. + openSection = sections.pop(); + + if (openSection) + throw new Error('Unclosed section "' + openSection[1] + '" at ' + scanner.pos); + + return nestTokens(squashTokens(tokens)); + } + + /** + * Combines the values of consecutive text tokens in the given `tokens` array + * to a single token. + */ + function squashTokens(tokens) { + var squashedTokens = []; + + var token, lastToken; + for (var i = 0, numTokens = tokens.length; i < numTokens; ++i) { + token = tokens[i]; + + if (token) { + if (token[0] === 'text' && lastToken && lastToken[0] === 'text') { + lastToken[1] += token[1]; + lastToken[3] = token[3]; + } + else { + squashedTokens.push(token); + lastToken = token; + } + } + } + + return squashedTokens; + } + + /** + * Forms the given array of `tokens` into a nested tree structure where + * tokens that represent a section have two additional items: 1) an array of + * all tokens that appear in that section and 2) the index in the original + * template that represents the end of that section. + */ + function nestTokens(tokens) { + var nestedTokens = []; + var collector = nestedTokens; + var sections = []; + + var token, section; + for (var i = 0, numTokens = tokens.length; i < numTokens; ++i) { + token = tokens[i]; + + switch (token[0]) { + case '#': + case '^': + collector.push(token); + sections.push(token); + collector = token[4] = []; + break; + case '/': + section = sections.pop(); + section[5] = token[2]; + collector = sections.length > 0 ? sections[sections.length - 1][4] : nestedTokens; + break; + default: + collector.push(token); + } + } + + return nestedTokens; + } + + /** + * A simple string scanner that is used by the template parser to find + * tokens in template strings. + */ + function Scanner(string) { + this.string = string; + this.tail = string; + this.pos = 0; + } + + /** + * Returns `true` if the tail is empty (end of string). + */ + Scanner.prototype.eos = function eos() { + return this.tail === ''; + }; + + /** + * Tries to match the given regular expression at the current position. + * Returns the matched text if it can match, the empty string otherwise. + */ + Scanner.prototype.scan = function scan(re) { + var match = this.tail.match(re); + + if (!match || match.index !== 0) + return ''; + + var string = match[0]; + + this.tail = this.tail.substring(string.length); + this.pos += string.length; + + return string; + }; + + /** + * Skips all text until the given regular expression can be matched. Returns + * the skipped string, which is the entire tail if no match can be made. + */ + Scanner.prototype.scanUntil = function scanUntil(re) { + var index = this.tail.search(re), match; + + switch (index) { + case -1: + match = this.tail; + this.tail = ''; + break; + case 0: + match = ''; + break; + default: + match = this.tail.substring(0, index); + this.tail = this.tail.substring(index); + } + + this.pos += match.length; + + return match; + }; + + /** + * Represents a rendering context by wrapping a view object and + * maintaining a reference to the parent context. + */ + function Context(view, parentContext) { + this.view = view; + this.cache = {'.': this.view}; + this.parent = parentContext; + } + + /** + * Creates a new context using the given view with this context + * as the parent. + */ + Context.prototype.push = function push(view) { + return new Context(view, this); + }; + + /** + * Returns the value of the given name in this context, traversing + * up the context hierarchy if the value is absent in this context's view. + */ + Context.prototype.lookup = function lookup(name) { + var cache = this.cache; + + var value; + if (cache.hasOwnProperty(name)) { + value = cache[name]; + } + else { + var context = this, names, index, lookupHit = false; + + while (context) { + if (name.indexOf('.') > 0) { + value = context.view; + names = name.split('.'); + index = 0; + + /** + * Using the dot notion path in `name`, we descend through the + * nested objects. + * + * To be certain that the lookup has been successful, we have to + * check if the last object in the path actually has the property + * we are looking for. We store the result in `lookupHit`. + * + * This is specially necessary for when the value has been set to + * `undefined` and we want to avoid looking up parent contexts. + **/ + while (value != null && index < names.length) { + if (index === names.length - 1) + lookupHit = hasProperty(value, names[index]); + + value = value[names[index++]]; + } + } + else { + value = context.view[name]; + lookupHit = hasProperty(context.view, name); + } + + if (lookupHit) + break; + + context = context.parent; + } + + cache[name] = value; + } + + if (isFunction(value)) + value = value.call(this.view); + + return value; + }; + + /** + * A Writer knows how to take a stream of tokens and render them to a + * string, given a context. It also maintains a cache of templates to + * avoid the need to parse the same template twice. + */ + function Writer() { + this.cache = {}; + } + + /** + * Clears all cached templates in this writer. + */ + Writer.prototype.clearCache = function clearCache() { + this.cache = {}; + }; + + /** + * Parses and caches the given `template` and returns the array of tokens + * that is generated from the parse. + */ + Writer.prototype.parse = function parse(template, tags) { + var cache = this.cache; + var tokens = cache[template]; + + if (tokens == null) + tokens = cache[template] = parseTemplate(template, tags); + + return tokens; + }; + + /** + * High-level method that is used to render the given `template` with + * the given `view`. + * + * The optional `partials` argument may be an object that contains the + * names and templates of partials that are used in the template. It may + * also be a function that is used to load partial templates on the fly + * that takes a single argument: the name of the partial. + */ + Writer.prototype.render = function render(template, view, partials) { + var tokens = this.parse(template); + var context = (view instanceof Context) ? view : new Context(view); + return this.renderTokens(tokens, context, partials, template); + }; + + /** + * Low-level method that renders the given array of `tokens` using + * the given `context` and `partials`. + * + * Note: The `originalTemplate` is only ever used to extract the portion + * of the original template that was contained in a higher-order section. + * If the template doesn't use higher-order sections, this argument may + * be omitted. + */ + Writer.prototype.renderTokens = function renderTokens(tokens, context, partials, originalTemplate) { + var buffer = ''; + + var token, symbol, value; + for (var i = 0, numTokens = tokens.length; i < numTokens; ++i) { + value = undefined; + token = tokens[i]; + symbol = token[0]; + + if (symbol === '#') value = this.renderSection(token, context, partials, originalTemplate); + else if (symbol === '^') value = this.renderInverted(token, context, partials, originalTemplate); + else if (symbol === '>') value = this.renderPartial(token, context, partials, originalTemplate); + else if (symbol === '&') value = this.unescapedValue(token, context); + else if (symbol === 'name') value = this.escapedValue(token, context); + else if (symbol === 'text') value = this.rawValue(token); + + if (value !== undefined) + buffer += value; + } + + return buffer; + }; + + Writer.prototype.renderSection = function renderSection(token, context, partials, originalTemplate) { + var self = this; + var buffer = ''; + + var value = context.lookup(token[1]); + + // This function is used to render an arbitrary template + // in the current context by higher-order sections. + function subRender(template) { + return self.render(template, context, partials); + } + + if (!value) return; + + if (isArray(value)) { + for (var j = 0, valueLength = value.length; j < valueLength; ++j) { + value[j].__i__ = j; + value[j].__first__ = (j === 0); + buffer += this.renderTokens(token[4], context.push(value[j]), partials, originalTemplate); + } + } + else if (typeof value === 'object' || typeof value === 'string' || typeof value === 'number') { + buffer += this.renderTokens(token[4], context.push(value), partials, originalTemplate); + } + else if (isFunction(value)) { + if (typeof originalTemplate !== 'string') + throw new Error('Cannot use higher-order sections without the original template'); + + // Extract the portion of the original template that the section contains. + value = value.call(context.view, originalTemplate.slice(token[3], token[5]), subRender); + + if (value != null) + buffer += value; + } + else { + buffer += this.renderTokens(token[4], context, partials, originalTemplate); + } + return buffer; + }; + + Writer.prototype.renderInverted = function renderInverted(token, context, partials, originalTemplate) { + var value = context.lookup(token[1]); + + // Use JavaScript's definition of falsy. Include empty arrays. + // See https://github.com/janl/mustache.js/issues/186 + if (!value || (isArray(value) && value.length === 0)) + return this.renderTokens(token[4], context, partials, originalTemplate); + }; + + Writer.prototype.renderPartial = function renderPartial(token, context, partials) { + if (!partials) return; + + var value = isFunction(partials) ? partials(token[1]) : partials[token[1]]; + if (value != null) + return this.renderTokens(this.parse(value), context, partials, value); + }; + + Writer.prototype.unescapedValue = function unescapedValue(token, context) { + var value = context.lookup(token[1]); + if (value != null) + return value; + }; + + Writer.prototype.escapedValue = function escapedValue(token, context) { + var value = context.lookup(token[1]); + if (value != null) + return mustache.escape(value); + }; + + Writer.prototype.rawValue = function rawValue(token) { + return token[1]; + }; + + mustache.name = 'mustache.js'; + mustache.version = '2.1.3'; + mustache.tags = ['{{', '}}']; + + // All high-level mustache.* functions use this writer. + var defaultWriter = new Writer(); + + /** + * Clears all cached templates in the default writer. + */ + mustache.clearCache = function clearCache() { + return defaultWriter.clearCache(); + }; + + /** + * Parses and caches the given template in the default writer and returns the + * array of tokens it contains. Doing this ahead of time avoids the need to + * parse templates on the fly as they are rendered. + */ + mustache.parse = function parse(template, tags) { + return defaultWriter.parse(template, tags); + }; + + /** + * Renders the `template` with the given `view` and `partials` using the + * default writer. + */ + mustache.render = function render(template, view, partials) { + if (typeof template !== 'string') { + throw new TypeError('Invalid template! Template should be a "string" ' + 'but "' + typeStr(template) + '" was given as the first ' + 'argument for mustache#render(template, view, partials)'); + } + + return defaultWriter.render(template, view, partials); + }; + + // This is here for backwards compatibility with 0.4.x., + /*eslint-disable */ // eslint wants camel cased function name + mustache.to_html = function to_html(template, view, partials, send) { + /*eslint-enable*/ + + var result = mustache.render(template, view, partials); + + if (isFunction(send)) { + send(result); + } + else { + return result; + } + }; + + // Export the escaping function so that the user may override it. + // See https://github.com/janl/mustache.js/issues/244 + mustache.escape = escapeHtml; + + // Export these mainly for testing, but also for advanced usage. + mustache.Scanner = Scanner; + mustache.Context = Context; + mustache.Writer = Writer; + +})); \ No newline at end of file