UNPKG

adhara

Version:

foundation for any kind of website: microframework

1,300 lines (1,192 loc) 307 kB
"use strict"; var _set = function set(object, property, value, receiver) { var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent !== null) { set(parent, property, value, receiver); } } else if ("value" in desc && desc.writable) { desc.value = value; } else { var setter = desc.set; if (setter !== undefined) { setter.call(receiver, value); } } return value; }; var _AdharaListView$DEFAU; var _get = function get(object, property, receiver) { if (object === null) object = Function.prototype; var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { return get(parent, property, receiver); } } else if ("value" in desc) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } }; var _slicedToArray = function () { function sliceIterator(arr, i) { var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"]) _i["return"](); } finally { if (_d) throw _e; } } return _arr; } return function (arr, i) { if (Array.isArray(arr)) { return arr; } else if (Symbol.iterator in Object(arr)) { return sliceIterator(arr, i); } else { throw new TypeError("Invalid attempt to destructure non-iterable instance"); } }; }(); var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); function _toConsumableArray(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } else { return Array.from(arr); } } var _marked = /*#__PURE__*/regeneratorRuntime.mark(range); function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } function _asyncToGenerator(fn) { return function () { var gen = fn.apply(this, arguments); return new Promise(function (resolve, reject) { function step(key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { return Promise.resolve(value).then(function (value) { step("next", value); }, function (err) { step("throw", err); }); } } return step("next"); }); }; } function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; } function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } /** * @typedef {Object} ElementAttributes * @description attributes that can be set in a element using `addAttr` helper for Handlebar files. * */ var TemplateEngineHelpers = function () { function TemplateEngineHelpers() { _classCallCheck(this, TemplateEngineHelpers); } _createClass(TemplateEngineHelpers, null, [{ key: "getHelpers", /** * @namespace * @description * Helpers written for handlebars. Can also be used by static references. * */ value: function getHelpers(currentHelpers) { var if_helper = currentHelpers.if; return { /** * @function * @static * @param {ElementAttributes} attributes - html element attributes. * @param {String|Object} default_attributes - html element default attributes. * @description * attributes override default_attributes * create attribute string and return which can be used to append * @example * let options = { * attributes : { id : 'element-id', className : 'css-class' } * } * TemplateUtils.execute( * '<a {{addAttr attributes "{"href":"javascript:void(0)", "route":"true"}"}}></a>', * options * ) * //returns <a href="javascript:void(0)" route:"true" id="element-id" class:"css-class></a> * */ 'addAttr': function addAttr(attributes, default_attributes) { if (attributes || default_attributes) { var attrData = []; default_attributes = default_attributes && typeof default_attributes === "string" ? JSON.parse(default_attributes) : {}; var class_names = attributes ? attributes.className || attributes["class"] || "" : ""; class_names += default_attributes.hasOwnProperty("class") ? " " + default_attributes['class'] : ""; attributes = Object.assign(default_attributes, attributes); if (class_names) attributes['class'] = class_names; loop(attributes, function (key, value) { if (key && value !== undefined) { if (key === "style") { var css_values = []; loop(value, function (css_prop, css_value) { css_values.push(css_prop + ":" + css_value + ";"); }); value = css_values.join(''); } if (typeof value === "string") { value = '"' + value.replace(/"/g, '\\"') + '"'; } attrData.push(key + '=' + value); } }); return new window.Handlebars.SafeString(attrData.join(' ')); } }, 'addProps': function addProps() { var properties = Array.prototype.slice.call(arguments); return properties.splice(0, properties.length - 1).join(' '); }, 'selectedClass': function selectedClass(selected, selectedClassName) { if (selected === true) { return selectedClassName; } else { return ''; } }, /** * @function * @static * @param {String} template_name - precompiled handlebar template name. * @param {Object} context - context with which the `template_name` hbs template to be called * @return {String} `template_name` handlebar template contents after execution with provided context. * @description * includes one hbs template in another. * @example * //child HBS file - child-template.hbs * `<div id="child"> * {{name}} * </div>` * * // main HBS file - main-template.hbs * `<div id="main"> * {{name}} * {{include 'child-template' child_context}} * </div>` * * Handlebars.templates['main-template']({name:"MAIN", child_context:{name:"CHILD"}}) * // returns * //<div id="main"> * // MAIN * // <div id="child"> * // CHILD * // </div> * //</div> * */ 'include': function include(template_name, context) { return new window.Handlebars.SafeString(TemplateUtils.execute(template_name, context)); }, /** * @function * @static * @param {Number} param1 - left operand / lvalue * @param {String} operation - can be one among "+", "-", "*", "/" and "%" * @param {Number} param2 - right operand / rvalue * @returns {Number} - result after operation between param1 and param2 with operation * */ 'math': function math(param1, operation, param2) { var lvalue = parseFloat(String(param1)); var rvalue = parseFloat(String(param2)); return { "+": lvalue + rvalue, "-": lvalue - rvalue, "*": lvalue * rvalue, "/": lvalue / rvalue, "%": lvalue % rvalue }[operation]; }, /** * @function * @static * @param {String} i18nKey - application key that needs to be internationalized. * @returns {String} internationalized application key's value * @example * // app.key.name = "APP Key" * {{i18N 'app.key.name'}} //returns "APP Key" * * // app.key.operation = "App Operation {0} by {1}" * {{i18N 'app.key.operation' 'operationName' 'operatedBy'}} //returns "App Operation operationName by operatedBy" * */ 'i18n': function i18n(i18nKey) { //~ (i18nKey, ...subs) var subs = Array.prototype.slice.call(arguments); subs = subs.splice(1, subs.length - 2); return Adhara.i18n.get(i18nKey, subs); }, /** * @function * @static * @param {Object} object - object in which to lookup. * @param {String} path - dot separated keys to be looked up for in depth. * @description * Wrapper for {@link getValueFromJSON} * @returns {String|Number|Boolean|Object|Array} - Value for the key. * */ 'get': function get(object, path) { return getValueFromJSON(object, path); }, /** * @function * @static * @description * Wrapper for {@link evaluateLogic} * @returns * handlebar block based on logic. * */ 'if': function _if(param1, operator, param2, options) { if ((typeof operator === "undefined" ? "undefined" : _typeof(operator)) === "object") { return if_helper.call(this, param1, operator); } if (evaluateLogic(param1, operator, param2)) { return options.fn(this); } else { return options.inverse(this); } }, /** * @function * @static * @description * If condition with multiple equations to evaluate. * Takes numerous arguments which will be executed in pairs. * @returns * handlebar block based on logic. * */ 'mIf': function mIf() { var arr = [true, 'and', true]; var args_len = arguments.length - 1; var options = arguments[args_len]; for (var i = 0; i < args_len; i++) { if (i === 0) { arr[0] = arguments[i]; } else if (i % 2 === 1) { arr[1] = arguments[i]; } else { arr[2] = arguments[i]; arr[0] = evaluateLogic(arr[0], arr[1], arr[2]); } } if (arr[0]) { return options.fn(this); } else { return options.inverse(this); } }, /** * @function * @static * @description * If condition with multiple equations to evaluate. * Takes numerous arguments which will be executed in pairs. * @returns {Boolean} result of equation created by provided params. * @see evaluateLogic * */ 'eIf': function eIf(param1, operator, param2) { return evaluateLogic(param1, operator, param2); }, /** * @function * @static * @returns {String|Number|Boolean|Object|Array} - Value of the global letiable. * */ 'global': function global(global_letiable) { if (global_letiable.indexOf("Adhara.") === 0) { return getValueFromJSON(Adhara, global_letiable.substring("Adhara.".length)); } return getValueFromJSON(window, global_letiable); }, 'loop': function loop(looper, options) { var structure = ''; for (var i = 0; i < looper.length; i++) { structure += options.fn(looper[i]); } return structure; }, /** * @function * @static * @description Takes numerous {String} arguments and appends all those strings. * @returns {String} arguments joined by ''. * */ 'append': function append() { var args = Array.prototype.slice.call(arguments); args.pop(); return args.map(function (arg) { if ((typeof arg === "undefined" ? "undefined" : _typeof(arg)) === "object") { return JSON.stringify(arg); } return arg; }).join(''); }, /** * @function * @static * @description Takes a {String} and converts it to JSON object. * @returns {Object} * */ 'make_json': function make_json(str) { return JSON.parse(str); }, /** * @function * @static * @description Takes a {String} and converts it to JSON object. * @returns {Object} * */ 'make_context': function make_context() { var context = {}; for (var i = 0; i < arguments.length - 1; i += 2) { context[arguments[i]] = arguments[i + 1]; } return context; }, /** * @function * @static * @param {Function} fn * @description Takes numerous and calls the fn with arguments from 2nd position since 1st argument is fn itself. * @returns {String|Number|Boolean|Object|Array} content returned by fn * */ 'fn_call': function fn_call(fn) { return call_fn.apply(this, Array.prototype.slice.call(arguments).slice(0, -1)); }, /** * @function * @static * @param {Object} looper * @param {Object} options - Handlebars options that has access to blocks. * @returns {String} Block string. * @description blocks will be called with a context ~ {"key":k, "value":v} * where `k` is key in the looper object and `v` is value corresponding to `k`. * */ 'loopObject': function loopObject(looper, options) { var structure = ''; loop(looper, function (key, value) { structure += options.fn({ key: key, value: value }); }); return structure; }, /** * @function * @static * @param {Number} start * @param {Number} step * @param {Number} end * @param {Object} options - Handlebars options that has access to blocks. * @returns {String} Block string appended n times where n is the number of times step-looped. * @description Block will be called with just a number {Number} as context which keeps increasing in steps, where the step height is equal to step param. * */ 'iterate_range': function iterate_range(start, step, end, options) { var str_buf = ''; for (var i = start; i <= end; i += step) { str_buf += options.fn(i); } return str_buf; }, 'route': function route(url) { return new Handlebars.SafeString("href=\"" + Adhara.router.transformURL(url) + "\" route"); } /* TODO handle better! 'generate': function(context, options){ let generatorInstance = context(), ret = '', done = false, index = 0, data = {}; function execIteration(field, index, last) { if (data) { data.key = field; data.index = index; data.first = index === 0; data.last = !!last; } ret = ret + options.fn(context[field], { data: data, // blockParams: _utils.blockParams([context[field], field], [contextPath + field, null]) }); } do{ let yi = generatorInstance.next(); done = yi.done; execIteration(yi.value, ++index, done===true); }while(done===false); console.log(context, options); return ret; }*/ }; } }, { key: "registerHelpers", value: function registerHelpers() { window.Handlebars.registerHelper(TemplateEngineHelpers.getHelpers(window.Handlebars.helpers)); } }]); return TemplateEngineHelpers; }(); /**------------------------------------------------------------------------------------------------------------------**/ var TAB = 9; var ENTER = 13; var UP_ARROW = 38; var DOWN_ARROW = 40; var BACKSPACE = 8; var ESCAPE = 27; var SHIFT = 16; var SPACE = 32; /**------------------------------------------------------------------------------------------------------------------**/ function handleForm(form) { if (form.submitting) { return; } else { form.submitting = true; } var hasFiles = !!form.querySelector('input[type="file"]'); var apiData = void 0; if (hasFiles) { apiData = new FormData(form); } else { var formData = jQuery(form).serializeArray(); apiData = {}; jQuery.each(formData, function (i, fieldData) { apiData[fieldData.name] = fieldData.value; }); } var format_fn = form.getAttribute('format-data'); if (format_fn) { apiData = call_fn(format_fn, apiData); } if (apiData === false) { return; } RestAPI[form.getAttribute('api-method')]({ url: form.action.split(window.location.host)[1], data: apiData, successMessage: form.getAttribute('success-message'), handleError: form.getAttribute('handle-error') !== "false", success: function success(data) { if (form.getAttribute('form-clear') === "true") { form.reset(); } jQuery(form).trigger('success', data); }, failure: function failure(message) { jQuery(form).trigger('failure', message); } }); } function registerAdharaUtils() { //Register templateEngine helpers Adhara.templateEngine.helpersHandler.registerHelpers(); //Form listeners jQuery(document).on('submit', 'form.api-form', function (event) { event.preventDefault(); handleForm(this); }); //Form listeners jQuery(document).on('success', 'form.dialog-form', function () /*e, d*/{ this.close.click(); }); } /** * @function * @global * @param {String|Number|Boolean} param1 * @param {String} operator - Operator can be one among these. * "in", "not_in", "contains", "not_contains", "has", "||", "&&", "|", "&", "==", "===", "!=", "!==", ">", "<", ">=", "<=", "equals", "and", "or". * @param {String|Number|Boolean} param2 * @Returns {Boolean} * * "in" - param2 must be an {Array}. Whether param1's existence in that array will be checked for * * "not_in" - param2 must be an {Array} and param1's non-existence in that array will be checked for * * "contains" - param1 must be an {Array} and param2's existence in that array will be checked for * * "not_contains" - param1 must be an {Array} and param2's non-existence in that array will be checked for * * "has" - param1 must be an {Object}. Whether param2 is a key of param1 * * All other operations will be applied as javaScript evaluates them. * `"equals" is equivalent to "=="`, * `"and" is equivalent to "&&"` * and `"or" is equivalent to "||"`. * * */ function evaluateLogic(param1, operator, param2) { if (operator === "in") { return param2 && param2.indexOf(param1) !== -1; } else if (operator === "not_in") { return param2 && param2.indexOf(param1) === -1; } else if (operator === "contains") { return param1 && param1.indexOf(param2) !== -1; } else if (operator === "not_contains") { return param1 && param1.indexOf(param2) === -1; } else if (operator === "has") { return param1 && param1.hasOwnProperty(param2); } else { return { "||": param1 || param2, "&&": param1 && param2, "|": param1 | param2, "&": param1 & param2, "==": param1 == param2, "===": param1 === param2, "!=": param1 != param2, "!==": param1 !== param2, ">": param1 > param2, "<": param1 < param2, ">=": param1 >= param2, "<=": param1 <= param2, "equals": param1 == param2, "and": param1 && param2, "or": param1 || param2 }[operator]; } } /** * @function * @global * @param {Object} object - object in which to lookup. * @param {String} path - dot separated keys to be looked up for in depth. * @param {String} [identifier=null] - token that helps to lookup inside arrays. * @returns {String|Number|Boolean|Object|Array} - Value for the key. * @description * Looks up a JSON object in depth and returns the value for the key provided. * @example * let obj = { * task: { * id: "12341234", * status: { * color: "#fff" * } * } * }; * getValueFromJSON(obj, "task.status.color"); //returns "#fff" * * let objX = { * tasks: [ * { * id: "12341234", * status: { * color: "#fff" * } * }, * { * id: "55424", * status: { * color: "#f5f5f5" * } * }, * { * id: "90898080", * status: { * color: "#eee" * } * }, * ] * }; * getValueFromJSON(objX, "task[1].status.color"); //returns "#f5f5f5" * getValueFromJSON(objX, "task[$, ].status.color", "$"); //returns "#fff, #f5f5f5, #eee" * // Elaborately, * // In `[$, ]` --split into identifier and separator * // '$'=identifier(from params). * // Remaining part inside [] is the separator i.e., `', '` will be used to join the results from the array * */ function getValueFromJSON(object, path, identifier) { try { if (!path) { return object; } var keys = path.split('.'); for (var i = 0; i < keys.length; i++) { var key_in = keys[i]; if (key_in.indexOf('[') !== -1) { var arr = key_in.split('['); var arrName = arr[0]; var index = arr[1].split(']')[0]; if (isNaN(index)) { var rite = object[arrName]; var separator = index.substring(identifier.length, index.length); var formattedVal = ''; for (var j = 0; j < rite.length; j++) { if (j > 0) { formattedVal += separator; } formattedVal += getValueFromJSON(rite[j], path.split('.').splice(i + 1).join('.'), identifier); } object = formattedVal; } else { object = object[arrName][index]; } break; } else { object = object[key_in]; } } return object; } catch (e) { return undefined; } } /** * @function * @global * @param {Object} object - object to set value to * @param {String} path - dot separated path. * @param {String|Number|Boolean|Object|Array} value - value to be set fot the given key * @description * Sets value to provided object at specified depth in the path be using dot separators. * Creates objects at depths if no object already exists at specified path. * @example * let kit = {'has_bat': true} * setValueToJson(kit, 'has_ball', true); //let kit = {'has_bat': true, 'has_ball': true} * setValueToJson(kit, 'has_bat', false); //let kit = {'has_bat': false, 'has_ball': true} * * let aeroplane = {'name': 'B747'} * setValueToJson(aeroplane, 'tank.capacity', '4000'); //aeroplane = {'name': 'B747', 'tank': { 'capacity': '4000' }} * setValueToJson(aeroplane, 'tank.shape', 'amoeba'); //aeroplane = {'name': 'B747', 'tank': { 'capacity': '4000', 'shape': 'amoeba' }} * */ function setValueToJson(object, path, value) { var keys = path.split('.'); loop(keys, function (i, key) { if (i + 1 < keys.length) { if (!object.hasOwnProperty(key) || !object[key] || _typeof(object[key]) !== "object") { object[key] = {}; } object = object[key]; } else { object[key] = value; } }); } /** * @typedef {Object|Array|String|Boolean|Number|null|undefined} _MultiParams - numerous arguments of any kind * @description * A function if accepts multiple params, can use this as param type. * @example * //def * function mpFn({String} param1, {_MultiParams} m_params){} * //call * mpFn("Str_param1", "p1", "p2", 1, {'key':'val'}, ['m1', 'm2', ...], ...); * //def2 * function mp2Fn({String} param1, {_MultiParams} m_params, {String} param2){} * //call2 * mp2Fn("Str_param1", "p1", "p2", 1, {'key':'val'}, ['m1', 'm2', ...], ..., "StrX_param2"); * * */ /** * @function * @global * @param {Function|String} fn - function to be called or global path to a function * @param {_MultiParams} params - any params that to be passed to function * @description * calls the function with params passed * @example * let gv = {}; //global_letiable * gv.sample_fn = function(param1, param2, param3){ * //Do Something... * return "Hello from SampleFN" * }; * call_fn('gv.sample_fn', param1, param2, param3); //returns "Hello from SampleFN" * */ function call_fn(fn) { if (!fn) { return; } var args = Array.prototype.slice.call(arguments); args.splice(0, 1); if (typeof fn === "function") { return fn.apply(fn, args); } else { try { fn = getValueFromJSON(window, fn); if (fn && fn !== window) { return fn.apply(window[fn], args); } } catch (e) { if (e.name === "TypeError" && e.message.indexOf("is not a function") !== -1) { throw new Error("error executing function : " + fn); } else { throw e; } } } } /** * Can be used if required to call a function, and if it is unavailable, call a default fn * Usage : call_fn_or_def(fn, arg1, arg2, arg3, def_fn) * Result : fn(arg1, arg2, arg3) if fn is not undefined else def_fn(arg1, arg2, arg3) * */ /** * @function * @global * @param {Function|String} fn - function to be called or global path to a function * @param {_MultiParams} params - any params that to be passed to function * @param {Function|String} fn - function to be called or global path to a function * @description * calls the function with params passed * @example * let gv = {}; //global_letiable * gv.sample_fn = function(param1, param2, param3){ * //Do Something... * return "Hello from SampleFN" * }; * call_fn('gv.sample_fn', param1, param2, param3, defaultFunction); //returns "Hello from SampleFN" * */ function call_fn_or_def(fn) { var args = Array.prototype.slice.call(arguments); var def_fn = args.pop(); if (!(typeof def_fn === "function" || typeof window[def_fn] === "function")) { args.push(def_fn); def_fn = undefined; } if (fn) { return call_fn.apply(call_fn, args); } else if (def_fn) { args[0] = def_fn; return call_fn.apply(call_fn, args); } } /** * Loop - looper iterator function * @callback LoopIteratorCallback * @param {String|Number|RegExp} key - key will be string in case of an object and Number will be an Array while looping through an Array. * @param {*} value - Value of iterable for key. * @returns {Boolean} * return `false` to stop iteration. * */ /** * @function * @global * @param {Object|Array} object - Iterable. * @param {LoopIteratorCallback} cbk - callback for each value in iterable. * @param {Boolean} [reverseIterate=false] - iterate in reverse if it is an array. * */ function loop(object, cbk, reverseIterate) { var i = void 0, loop_size = void 0; if (object instanceof Array) { loop_size = object.length; if (reverseIterate) { for (i = loop_size - 1; i >= 0; i--) { if (cbk(i, object[i]) === false) { break; } } } else { for (i = 0; i < loop_size; i++) { if (cbk(i, object[i]) === false) { break; } } } } else { var keys = Object.keys(object); loop_size = keys.length; for (i = 0; i < loop_size; i++) { if (cbk(keys[i], object[keys[i]]) === false) { break; } } } } /** * @typedef {String} HandlebarTemplate * @description handlebar template can be an inline template or a pre compiled template that is created in a HBS file. * */ /** * @namespace * @description * TemplateUtils is a set of utilities related to handlebars * */ var TemplateUtils = {}; (function () { var preCompiledCache = {}; /** * @function * @static * @param {HandlebarTemplate} template_or_template_string - Handlebar template name or template string. * @param {Object} context - content to be passed t provided handlebar template/string. * @param {Boolean} [cache=true] - whether to cache if the provided template is a Handlebar string template. * @returns {String} compiled adn executed handlebar template * @example * //using template * TemplateUtils.execute('template-file-name', {context_key1: "value1", ...}); * * //using template string * TemplateUtils.execute('Hello {{name}}', {name: "Adhara"}); //returns "Hello Adhara" * */ TemplateUtils.execute = function (template_or_template_string, context, cache) { //Check if it is a pre compiled hbs template var template = window.Handlebars.templates[template_or_template_string]; if (!template && window.Handlebars.hasOwnProperty("compile")) { //If template not found in precompiled hbs list => template is a handlebar string template // check if cacheable if (cache !== false) { //check if the template is already cached. template = preCompiledCache[template_or_template_string]; if (!template) { //else compile, store it in cache and proceed to execution template = preCompiledCache[template_or_template_string] = window.Handlebars.compile(template_or_template_string); } } else { //else compile and proceed to execution template = window.Handlebars.compile(template_or_template_string); } } //execute with the provided context and return the output content... return template(context); }; })(); var Internationalize = function () { /** * @constructor * @param {Object<String, String>} key_map - i18n key map * */ function Internationalize(key_map) { _classCallCheck(this, Internationalize); this.key_map = key_map; } /** * @instance * @function * @param {String} key - key * @param {Array<String>} subs - substitutes * @param {String} default_value - will be returned if key is not availalbe in the keymap * */ _createClass(Internationalize, [{ key: "getValue", value: function getValue(key, subs, default_value) { if (!key) { return; } var value = this.key_map[key]; if (value === undefined) { value = getValueFromJSON(this.key_map, key); } if (value === undefined) { return default_value; } subs = subs || []; var placeholders = value.match(/{[0-9]+}/g) || []; for (var i = 0; i < placeholders.length; i++) { var sub = subs[i] || ""; try { if (sub.indexOf('.') !== -1) { sub = this.get(sub); } } catch (e) {/*Do Nothing*/} value = value.replace(new RegExp("\\{" + i + "\\}", "g"), sub); } return value.trim(); } /** * @instance * @function * @param {String} key - key * @param {Array<String>|String} [subs=[]] - substitutes * @param {String} [default_value=null] - substitutes * */ }, { key: "get", value: function get(key, subs) { var default_value = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : null; if (typeof subs === "string") { default_value = subs; } return this.getValue(key, subs, default_value || key); } }]); return Internationalize; }(); // Enable multi extend functionality https://stackoverflow.com/a/45332959 function MutateViews(baseClass) { for (var _len = arguments.length, mixins = Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) { mixins[_key - 1] = arguments[_key]; } function copyProps(target, source) { // this function copies all properties and symbols, filtering out some special ones //TODO "Object.getOwnPropertyNames" and "Object.getOwnPropertySymbols" Doesn't work in IE even after transpilation to ES5... Object.getOwnPropertyNames(source).concat(Object.getOwnPropertySymbols(source)).forEach(function (prop) { if (!prop.match(/^(?:constructor|prototype|arguments|caller|name|bind|call|apply|toString|length|context)$/)) Object.defineProperty(target, prop, Object.getOwnPropertyDescriptor(source, prop)); }); } var base = function (_baseClass) { _inherits(base, _baseClass); function base() { var _ref; for (var _len2 = arguments.length, args = Array(_len2), _key2 = 0; _key2 < _len2; _key2++) { args[_key2] = arguments[_key2]; } _classCallCheck(this, base); var _this = _possibleConstructorReturn(this, (_ref = base.__proto__ || Object.getPrototypeOf(base)).call.apply(_ref, [this].concat(args))); mixins.forEach(function (mixin) { copyProps(_this, new (Function.prototype.bind.apply(mixin, [null].concat(args)))()); }); return _this; } return base; }(baseClass); mixins.forEach(function (mixin) { // outside constructor() to allow aggregation(A,B,C).staticFunction() to be called etc. copyProps(base.prototype, mixin.prototype); copyProps(base, mixin); }); return base; } function cloneObject(obj) { var clone = obj instanceof Array ? [] : {}; for (var i in obj) { if (obj[i] != null && _typeof(obj[i]) === "object" && (obj[i].constructor.name === "Object" || obj[i].constructor.name === "Array")) { clone[i] = cloneObject(obj[i]); } else { clone[i] = obj[i]; } } return clone; } var Time = function () { function Time() { _classCallCheck(this, Time); } _createClass(Time, null, [{ key: "sleep", value: function () { var _ref2 = _asyncToGenerator( /*#__PURE__*/regeneratorRuntime.mark(function _callee(millis) { return regeneratorRuntime.wrap(function _callee$(_context) { while (1) { switch (_context.prev = _context.next) { case 0: return _context.abrupt("return", new Promise(function (resolve, reject) { setTimeout(resolve, millis); })); case 1: case "end": return _context.stop(); } } }, _callee, this); })); function sleep(_x2) { return _ref2.apply(this, arguments); } return sleep; }() }]); return Time; }(); /**------------------------------------------------------------------------------------------------------------------**/ /** * @class * @classdesc Ticker class that handles repetitive, time based queueing * @param {Number} [interval=2000] - polling interval * @param {Number} [exponential_factor=1] - factor by which polling interval should be multiplied * @param {Number} [min_interval=0] - minimum value configured for Poller's timer to work * */ var AdharaTicker = function () { function AdharaTicker(interval, exponential_factor, min_interval) { _classCallCheck(this, AdharaTicker); this.interval = interval === 0 ? interval : interval || 2000; this.exponential_factor = exponential_factor || 1; this.min_interval = min_interval || 0; this.initial_interval = interval; this.timeoutId = null; } _createClass(AdharaTicker, [{ key: "scheduleNextTick", value: function scheduleNextTick() { var _this2 = this; this.pause(); if (!(this.interval <= this.min_interval)) { this.timeoutId = window.setTimeout(function () { _this2.onExecute(); }, this.interval); } } }, { key: "next", value: function next() { this.scheduleNextTick(); } }, { key: "onExecute", value: function onExecute() { this.interval *= this.exponential_factor; this.on_execute(this.next); } /** * @function * @description * Starts polling * */ }, { key: "start", value: function start(execute) { this.on_execute = execute; this.scheduleNextTick(); } /** * @function * @description * stops current timeout * doesn't call next or on-execute function * */ }, { key: "pause", value: function pause() { window.clearTimeout(this.timeoutId); } }, { key: "resume", /** * @function * @description * stops current timeout * doesn't call next or on-execute function * start new timeout * */ value: function resume() { this.scheduleNextTick(); } }, { key: "stop", /** * @function * @description * stops current timeout * doesn't call next or on-execute function * reset's interval to initial interval * */ value: function stop() { this.pause(); this.interval = this.initial_interval; } }, { key: "restart", /** * @function * @description * stops current timeout * doesn't call next or on-execute function * reset's interval to initial interval * start new timeout * */ value: function restart() { this.stop(); this.scheduleNextTick(); } }]); return AdharaTicker; }(); /**------------------------------------------------------------------------------------------------------------------**/ var CoalesceTasker = function () { function CoalesceTasker() { var wait_for = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 0; _classCallCheck(this, CoalesceTasker); this.wait_for = wait_for; this.timer_idx = 0; } _createClass(CoalesceTasker, [{ key: "execute", value: function () { var _ref3 = _asyncToGenerator( /*#__PURE__*/regeneratorRuntime.mark(function _callee2(executor, terminator) { var _this3 = this; return regeneratorRuntime.wrap(function _callee2$(_context2) { while (1) { switch (_context2.prev = _context2.next) { case 0: if (this.terminator) this.terminator(); this.executor = executor; this.terminator = terminator; clearTimeout(this.timer_idx); return _context2.abrupt("return", new Promise(function (resolve, reject) { _this3.timer_idx = setTimeout(function () { _this3.executor(); resolve(); }, _this3.wait_for); })); case 5: case "end": return _context2.stop(); } } }, _callee2, this); })); function execute(_x4, _x5) { return _ref3.apply(this, arguments); } return execute; }() }]); return CoalesceTasker; }(); /**------------------------------------------------------------------------------------------------------------------**/ /** * @namespace * @description * Client routing logic. * All the client URL pattern's should be registered with the router. * * On visiting a URL, if called {@link AdharaRouter.route}, it calls the registered view function, * which takes care of rendering the page. * * Any HTML element can be used as a router. For this purpose, * * * > Add this attribute `href="/url/to/be/navigated/to"` and this property `route` to any html element to make behave as a router. * * > By default routing happening this way will execute the view function even if the current URL is same as provided href. * * > In order to disable this behaviour, provide the attribute `data-force="false"` * * > In order to use {@link AdharaRouter.goBack} functionality provide `data-force="true"`. See example below. * * @example * //Registering * AdharaRouter.register("^/adhara/{{instance_id}}([0-9]+)/{{tab}}(details|tokens|history)$", function(instance_id, tab){ * console.log(instance_id, tab); * AdharaRouter.getPathParam("instance_id"); //Returns same as instance_id * AdharaRouter.getPathParam("tab"); //Returns same as tab * }); * * //Navigating * AdharaRouter.navigateTo("/adhara/123412341234/details"); * * //Routing - In case if URL is already set in address bar and not via Router, call this function to execute the registered view funciton. * this.route(); * * //HTML Example * * <a href="/adhara/123412341234/tokens" /> * * <button href="/adhara/123412341234/tokens" data-force="false">tokens</button> * * <div href="/adhara/123412341234/details" data-back="true"></div> * * */ var AdharaRouter = null; (function () { "use strict"; /** * @private * @member {Object<String, Object>} * @description * Stores all the registered URL's along with other view parameters. * */ var registeredUrlPatterns = {}; /** * @private * @member {String} * @description * Stores base URI for regex matches * */ var baseURI = ""; var defaultTitle = document.title; /** * @private * @member {String} * @description * App Name to be used as first half of document title * */ var appName = ""; /** * @private * @member {Object<String, String>} * @description * Stores the current URL's search query parameters. * */ var queryParams = {}; /** * @private * @member {Object<String, String>} * @description * Stores the current URL's path variables. * */ var pathParams = {}; /** * @private * @member {Array<String>} * @description * Stores list of visited URL's * */ var historyStack = []; /** * @private * @member {String|undefined} * @description * Stores current page URL. * */ var currentUrl = undefined; /** * @private * @member {RouterURLConf} * @description * Stores route which matches with the current URL against registered URL patterns. * */ var currentRoute = undefined; /** * @private * @member {Object<String, Function|undefined>} * @description * Stores listeners that will be called on routing. * */ var listeners = {}; /** * @typedef {Function} AdharaRouterMiddleware * @param {Object} params - url parameters * @param {String } params.view_name - name of the page that is being routed to * @param {String} params.path - path that is being routed to * @param {Object} params.query_params - url query parameters * @param {Object} params.path_params - url path parameters * @param {Function} route - Proceed with routing after making necessary checks in middleware * */ /** * @private * @member {Array<AdharaRouterMiddleware>} * @description * Stores middlewares that will be called on routing. * */ var middlewares = []; /** * @function * @private * @returns {Str