var prefData = window.performance.timing; !(function (root, window, document, pref_data, undefined) { /* (immediately-invoked function expression), for Private Scope. ! means an expression */ var tts = function (arg, doc) { doc = doc && doc.first || doc || document; if (typeof arg == 'function') { /* $(function() {...}) */ if (doc.readyState == 'loading') { doc.addEventListener('DOMContentLoaded', arg); } else { arg(); } } else { var ret = Object.create(tts.fn), match; /* $([domObject]) or $(ttsObject) */ if (typeof arg == 'object') { if ('length' in arg) { ret.length = arg.length; for (var o = 0; o < arg.length; o++) { ret[o] = arg[o]; } } else { /* $(domObject) */ ret[0] = arg; ret.length = 1; } } else if (!arg) { /* $() */ ret[0] = doc.createDocumentFragment(); ret.length = 1; } else if ((match = arg.match(/<(.+)>/))) { /* $('
') */ ret[0] = doc.createElement(match[1]); ret.length = 1; } else { /* $('div.widget') */ var els = doc.querySelectorAll(arg); ret.length = els.length; for (var w = 0; w < els.length; w++) { ret[w] = els[w]; } } return ret; } }; tts.version = "1.0"; tts.performanceData = pref_data; tts.pageLoadTime = function () { return pref_data.loadEventEnd - pref_data.navigationStart; }; tts.connectTime = function () { return pref_data.responseEnd - pref_data.requestStart; }; tts.renderTime = function () { return pref_data.domComplete - pref_data.domLoading; }; tts.isNotSet = function (check) { return (check === null || typeof check === "undefined" || check.length === 0) ? true : false; }; tts.getValue = function (input, defaults) { return (tts.isNotSet(input) === true) ? defaults : input; }; tts.matches = ['matches', 'webkitMatchesSelector', 'mozMatchesSelector', 'msMatchesSelector'].filter(function (sel) { return sel in document.documentElement; })[0]; tts.fn = Object.create(Array.prototype, { each: {value: function (callback) { if ( ! tts.isFunction(callback) ) { /*throw new Error("Callback should be a function");*/ } var $this = {}; for (var index = 0; index < this.length; index++) { $this = this[index]; $this.callback = callback; $this.callback(index); } return this; }}, first: {get: function () { return this[0]; }}, eq: {value: function (i) { return tts(this[i || 0]); }}, on: {value: function (evt, fn) { if (!tts.isFunction(fn)) tts.logger('Callback should be a function', 'warn'); var hasit = this[0].addEventListener; for (var i = 0; i < this.length; i++) { if (hasit) { this[i].addEventListener(evt, fn); } else { this[i].attachEvent("on" + evt, fn); } } return this; }}, off: {value: function (evt, fn) { if (!tts.isFunction(fn)) tts.logger('Callback should be a function', 'warn'); var hasit = this[0].removeEventListener; for (var i = 0; i < this.length; i++) { if (hasit) { this[i].removeEventListener(evt, fn); } else { this[i].detachEvent("on" + evt, fn); } } return this; }}, trigger: {value: function (eventName) { for (var i = 0; i < this.length; i++) { var event = document.createEvent('Event'); event.initEvent(eventName, true, true); this[i].dispatchEvent(event); } return this; }}, toggleClass: {value: function (cls) { for (var i = 0; i < this.length; i++) { if (this[i].classList) { this[i].classList.toggle(cls); } else { var classes = this[i].className.split(' '); var existingIndex = classes.indexOf(cls); if (existingIndex >= 0) { classes.splice(existingIndex, 1); } else { classes.push(cls); } this[i].className = classes.join(' '); } } return this; }}, addClass: {value: function (cls) { for (var i = 0; i < this.length; i++) { if (!tts.fn.hasClass.call({first: this[i]}, cls)) { this[i].className += ' ' + cls; } } return this; }}, removeClass: {value: function (cls) { for (var i = 0; i < this.length; i++) { this[i].className = this[i].className.replace(cls, ''); } return this; }}, hasClass: {value: function (cls) { return this.first.className != '' && new RegExp('\\b' + cls + '\\b').test(this.first.className); }}, prop: {value: function (property, value) { if (typeof value == 'undefined') { return this.first[property]; } else { for (var i = 0; i < this.length; i++) { this[i][property] = value; } return this; } }}, attr: {value: function (property, value) { if (typeof value == 'undefined') { return this.first.getAttribute(property); } else { for (var i = 0; i < this.length; i++) { this[i].setAttribute(property, value); } return this; } }}, removeAttr: {value: function (property) { for (var i = 0; i < this.length; i++) { this[i].removeAttribute(property); } return this; }}, val: {value: function (value) { var el = this.first, prop = 'value'; switch (el.tagName) { case 'SELECT': prop = 'selectedIndex'; break; case 'OPTION': prop = 'selected'; break; case 'INPUT': if (el.type == 'checkbox' || el.type == 'radio') { prop = 'checked'; } break; } return this.prop(prop, value); }}, append: {value: function (value) { var t = this, v = tts(value), len = v.length; for (var i = 0; i < len; i++) { t.first.appendChild(v[i].first || v[i]); } return this; }}, before: {value: function (value) { this.first.parentElement.insertBefore(tts().append(value).first, this.first); return this; }}, parent: {value: function () { return tts(this.first.parentNode); }}, clone: {value: function () { return tts(this.first.cloneNode(true)); }}, remove: {value: function () { for (var i = 0; i < this.length; i++) { this[i].parentNode.removeChild(this[i]); } return this; }}, find: {value: function (value) { return tts(value, this.first); }}, closest: {value: function (selector) { var el = this.first; do { if (el[tts.matches](selector)) { return tts(el); } } while (el = el.parentElement); return null; }}, is: {value: function (selector) { return tts(this.filter(function (el) { return el[tts.matches](selector); })); }}, css: {value: function (property, value) { if (typeof value == 'undefined') { return this.first.style[property]; } else { for (var i = 0; i < this.length; i++) { this[i].style[property] = value; } return this; } }}, html: {value: function (value) { return this.prop('innerHTML', value); }}, text: {value: function (value) { return this.prop('textContent', value); }}, empty: {value: function () { return this.prop('innerHTML', ''); }}, hide: {value: function () { for (var i = 0; i < this.length; i++) { this[i].style.display = 'none'; } return this; }}, show: {value: function (type) { var display_type = (type) ? type : ''; for (var i = 0; i < this.length; i++) { this[i].style.display = display_type; } return this; }}, invisible: {value: function () { for (var i = 0; i < this.length; i++) { this[i].style.visibility = 'hidden'; } return this; }}, visible: {value: function (type) { for (var i = 0; i < this.length; i++) { this[i].style.visibility = "visible"; } return this; }}, fadeStop: {value: function () { for (var i = 0; i < this.length; i++) { this[i].style.opacity = 1; this[i].style.filter = "alpha(opacity=1)"; this[i].style.display = "inline-block"; this[i].style.visibility = "visible"; } }}, fadeIn: {value: function (ms, display) { var tms = (typeof ms == 'undefined') ? 600 : ms, display_as = (typeof display == 'undefined') ? "inline-block" : display; for (var i = 0; i < this.length; i++) { var elem = this[i].style, opacity = {}, timer = {}; elem.opacity = 0; elem.filter = "alpha(opacity=0)"; elem.display = display_as; elem.visibility = "visible"; opacity.i = 0; timer.i = setInterval(function () { opacity.i += 50 / tms; if (opacity.i >= 1) { clearInterval(timer.i); opacity.i = 1; } elem.opacity = opacity.i; elem.filter = "alpha(opacity=" + opacity.i * 100 + ")"; }, 50); } }}, fadeOut: {value: function (ms) { var tms = (typeof ms == 'undefined') ? 600 : ms; for (var i = 0; i < this.length; i++) { var opacity = {}, timer = {}, elem = this[i].style; opacity.i = 1; timer.i = setInterval(function () { opacity.i -= 50 / tms; if (opacity.i <= 0) { clearInterval(timer.i); opacity.i = 0; elem.display = "none"; elem.visibility = "hidden"; } elem.opacity = opacity.i; elem.filter = "alpha(opacity=" + opacity.i * 100 + ")"; }, 50); } }} }); tts.now = function () { return Date.now(); }; tts.parse = function (string) { return JSON.parse(string); }; tts.map = function (array, callback, arg) { return array.map(callback, arg); }; tts.random = function (min, max) { return Math.floor((Math.random() * max) + min); }; tts.trim = function (string) { return string.trim(); }; tts.inArray = function (item, array) { return (array.indexOf(item) !== -1) ? true : false; }; tts.isFunction = function (item) { if (typeof item === 'function') { return true; } var type = Object.prototype.toString.call(item); return type === '[object Function]' || type === '[object GeneratorFunction]'; }; var arrayOfCalls = []; tts.once = function (callback, id, parms) { var fn = window[callback], found = (!tts.inArray(id, arrayOfCalls) && tts.isFunction(fn)) ? fn(parms) : false; if (found !== false) { arrayOfCalls.push(id); } return found; }; tts.isEmptyObject = function (obj) { return Object.keys(obj).length === 0; }; tts.isEmpty = function (str) { return (!str || 0 === str.length); }; tts.isNumeric = function (n) { return !isNaN(parseFloat(n)) && isFinite(n); }; tts.extend = function (object1, object2) { return Object.assign({}, object1, object2); }; tts.when = function (arrayOfPromises) { return new Promise(function (resolve, reject) { Promise.all(arrayOfPromises).then(values => { resolve(values); }).catch(errors => { reject(errors); }); }); }; /* * Begin Logger */ tts.time = function () { var now = new Date(), hours = now.getHours() % 12 || 12, minutes = now.getMinutes(), seconds = now.getSeconds(), XM = (now.getHours() < 12) ? "AM" : "PM", formmated = hours + ":" + minutes + ":" + seconds + " " + XM; return formmated; }; tts.debugMode = true; tts.doTrace = false; var startTimer = [], endTimer = [], time = [], beginCodeTimer = 0, loggerData = [{message: navigator.userAgent, kind: "userAgent", option: ""}]; tts.allowedElapsedTime = 4000; tts.completedCodeTimer = 0; tts.startCodeTimer = function () { beginCodeTimer = Date.now(); }; tts.endCodeTimer = function () { tts.completedCodeTimer = Date.now() - beginCodeTimer; loggerData.push({message: "Toal Code Time Elapsed", kind: "MainTimer", option: tts.completedCodeTimer}); if (tts.completedCodeTimer > tts.allowedElapsedTime) { tts.sendReport(); } }; tts.getLoggerData = loggerData; tts.logger = function (message, level, option) { if (typeof level === "undefined") { level = "info"; } if (typeof option === "undefined") { option = ""; } if (tts.debugMode === false || !window.console) { return false; } if (typeof message === "object") { message = `[ ${tts.time()} ] ` + JSON.stringify(message); } else { message = `[ ${tts.time()} ] ${message}`; } if (level === "microStart" || level === "start") { console.group(message, option); } else if (level === "microStop" || level === "stop") { console.groupEnd(message, option); } else { loggerData.push({message: message, kind: level, option: option}); } if (tts.doTrace && (level === "warn" || level === "error")) { console.trace(); } if (level === "info" && console.info) { console.info(message); } else if (level === "microStart" && performance.now) { startTimer[option] = performance.now(); } else if (level === "microStop" && performance.now) { endTimer[option] = performance.now(); var data = endTimer[option] - startTimer[option]; console.info(data); loggerData.push({message: message, kind: level, option: data}); } else if (level === "warn" && console.warn) { console.warn(message); } else if (level === "error" && console.error) { console.error(message); } else if (level === "table" && console.table) { console.table(message, option); /* option = Table Column */ } else if (level === "group" && console.group) { console.group(message, option); /* option = Group Label */ } else if (level === "end" && console.groupEnd) { console.groupEnd(message, option); /* option = Group Label */ } else if (level === "trace" && console.trace) { console.trace(); } else if (level === "start" && console.time) { console.time(option); time[option] = Date.now(); } else if (level === "stop" && console.timeEnd) { console.timeEnd(option); var data = Date.now() - time[option]; loggerData.push({message: message, kind: level, option: data}); } else if (console.log) { console.log(message); /* for Chorme Console is enabled */ } }; tts.ReportsURL = ""; tts.sendReport = function (markComplete) { return new Promise((resolve, reject) => { if (tts.ReportsURL === "") { reject(); } else { var strValues = "&logs=" + encodeURI(JSON.stringify(loggerData)); if (sent_errors_yet === false) { if (typeof markComplete === 'undefined') { markComplete = false; } if (markComplete === true) { sent_errors_yet = true; } tts.Post(tts.ReportsURL, strValues).then(values => { resolve(values); }).catch(errors => { reject(errors); }); } } }); }; var sent_errors_yet = false; function errorReports(errorMsg, url, lineNumber, column, errorObj) { if (tts.ReportsURL === "") { return false; } if (errorMsg.indexOf('Script error.') > -1 || typeof errorMsg === "null") { return; /* At the moment, we filter out the exceptions for iOS Safari and older Androids by checking if the error message is equal to “Script error.”. */ } var strValues = "errMessage=" + encodeURI(errorMsg); strValues += "&errLine=" + encodeURI(lineNumber); if (typeof column !== "undeinfed" && typeof column !== "null") { strValues += "&errColumn=" + encodeURI(column); } if (typeof errorObj !== "undeinfed" && typeof errorObj !== "null") { strValues += "&errObject=" + encodeURI(errorObj); } strValues += "&queryString=" + encodeURI(location.search); strValues += "&Url=" + encodeURI(url); strValues += "&Path=" + encodeURI(location.pathname); strValues += "&Hash=" + encodeURI(location.hash); strValues += "&HTTPRef=" + encodeURI(document.referrer); strValues += "&logs=" + encodeURI(JSON.stringify(loggerData)); if (sent_errors_yet === false) { tts.Post(tts.ReportsURL, strValues); } sent_errors_yet = true; } try { window.onerror = errorReports; } catch (er) { } /* * End of Logger */ /* * Local Storage */ function store(temp) { if (typeof temp === "undefined") { this.temp = false; } else { this.temp = temp; } if (typeof (Storage) !== "undefined") { return true; } else { return false; } } store.prototype.set = function (name, data) { try { if (typeof (Storage) !== "undefined") { var d = JSON.stringify(data); if (this.temp === false) { localStorage.setItem(name, d); } else { sessionStorage.setItem(name, d); } return true; } else { return false; } } catch (er) { return false; } }; store.prototype.get = function (name) { if (typeof (Storage) !== "undefined") { if (this.temp === false) { return JSON.parse(localStorage.getItem(name)); } else { return JSON.parse(sessionStorage.getItem(name)); } } else { return false; } }; store.prototype.remove = function (name) { if (typeof (Storage) !== "undefined") { if (this.temp === false) { localStorage.removeItem(name); } else { sessionStorage.removeItem(name); } return true; } else { return false; } }; store.prototype.clear = function () { if (typeof (Storage) !== "undefined") { if (this.temp === false) { localStorage.clear(); } else { sessionStorage.clear(); } return true; } else { return false; } }; tts.store = store; /* End of Local Storage */ /* * Router */ class MyRouter { constructor(opts) { var self = this; /* Scope reference */ this.events = {}; /* Event Listeners */ this.state = null; /* Router state object */ this.options = opts || {}; /* Options */ this.options.env = this.options.env || (!!(Object.keys(root).length === 0 && process && process.browser !== true) ? 'server' : 'client'); this.options.mode = this.options.mode || (!!(this.options.env !== 'server' && this.options.pushState && root.history && root.history.pushState) ? 'pushState' : 'hashchange'); if ('function' === typeof root.addEventListener) { root.addEventListener('hashchange', function () { self.trigger('hashchange'); }); root.addEventListener('popstate', function (e) { /* Make sure popstate doesn't run on init -- this is a common issue with Safari and old versions of Chrome */ if (self.state && self.state.previousState === null) { return false; } self.trigger('navigate'); }); } return this; } } /** * Create a RegExp Route from a string * This is the heart of the router and I've made it as small as possible! * @param {String} path - Path of route * @param {Array} keys - Array of keys to fill * @param {Bool} sensitive - Case sensitive comparison * @param {Bool} strict - Strict mode */ MyRouter.regexRoute = function (path, keys, sensitive, strict) { if (path instanceof RegExp) { return path; } if (path instanceof Array) { path = '(' + path.join('|') + ')'; } /* Build route RegExp */ path = path.concat(strict ? '' : '/?') .replace(/\/\(/g, '(?:/') .replace(/\+/g, '__plus__') .replace(/(\/)?(\.)?:(\w+)(?:(\(.*?\)))?(\?)?/g, function (_, slash, format, key, capture, optional) { keys.push({name: key, optional: !!optional}); slash = slash || ''; return '' + (optional ? '' : slash) + '(?:' + (optional ? slash : '') + (format || '') + (capture || (format && '([^/.]+?)' || '([^/]+?)')) + ')' + (optional || ''); }) .replace(/([\/.])/g, '\\$1') .replace(/__plus__/g, '(.+)') .replace(/\*/g, '(.*)'); return new RegExp('^' + path + '$', sensitive ? '' : 'i'); }; /** * ForEach workaround utility * @param {Array} a - to iterate * @param {Function} callback */ MyRouter._forEach = function (a, callback) { if (typeof Array.prototype.forEach === 'function') { return Array.prototype.forEach.call(a, callback); } /* Replicate forEach() */ return function (c, next) { for (var i = 0, n = this.length; i < n; ++i) { c.call(next, this[i], i, this); } }.call(a, callback); }; /** * Add an route and handler * @param {String|RegExp} route name * @return {self} Router */ MyRouter.prototype.get = MyRouter.prototype.add = function (route) { var self = this, middleware = Array.prototype.slice.call(arguments, 1, -1), handler = Array.prototype.slice.call(arguments, -1)[0], request = new Request(route); var invoke = function RouteHandler() { /* Build request parameters */ var req = request.parse(self.path()); /* Check if matches are found */ if (req.match) { /* Match found */ var extra = {route: route, params: req.params, req: req, regex: req.match}; /* Create call stack -- add middleware first, then handler */ var stack = new CallStack(self, extra).enqueue(middleware.concat(handler)); /* Trigger main event */ self.trigger('match', stack, req); /* Continue */ if (!stack.runCallback) { return self; } /* Previous state becomes current state */ stack.previousState = self.state; /* Save new state */ self.state = stack; /* Prevent this handler from being called if parent handler in stack has instructed not to propagate any more events */ if (stack.parent() && stack.parent().propagateEvent === false) { stack.propagateEvent = false; return self; } /* Call handler */ stack.callback(); } /* Returns self */ return self; }; /* Event name */ var eventName = (self.options.mode !== 'pushState' && self.options.env !== 'server') ? 'hashchange' : 'navigate'; /* Invoke when route is defined, and once again when app navigates */ return invoke().on(eventName, invoke); }; /** * Fire an event listener * @param {String} event name * @param {Mixed} [attributes] Parameters that will be applied to event handler * @return {self} Router */ MyRouter.prototype.trigger = function (event) { var self = this, params = Array.prototype.slice.call(arguments, 1); /* Call matching events */ if (this.events[event]) { MyRouter._forEach(this.events[event], function (fn) { fn.apply(self, params); }); } return this; }; /** * Add an event listener * @param {String} event name (multiple events can be called when separated by a space " ") * @param {Function} handler - callback * @return {self} Router */ MyRouter.prototype.on = MyRouter.prototype.bind = function (event, handler) { var self = this, events = event.split(' '); MyRouter._forEach(events, function (event) { if (self.events[event]) { self.events[event].push(handler); } else { self.events[event] = [handler]; } }); return this; }; /** * Allow event to be called only once * @param {String} event name(s) * @param {Function} handler - callback * @return {self} Router */ MyRouter.prototype.once = function (event, handler) { var ran = false; return this.on(event, function () { if (ran) { return false; } ran = true; handler.apply(this, arguments); handler = null; return true; }); }; /** * @param {String} context - Route context (without trailing slash) * param {[Function]} Middleware (optional) * @return {Function} Adds route to context */ MyRouter.prototype.context = function (context) { var self = this, middleware = Array.prototype.slice.call(arguments, 1); return function () { var value = arguments[0], submiddleware = (arguments.length > 2) ? Array.prototype.slice.call(arguments, 1, -1) : [], handler = Array.prototype.slice.call(arguments, -1)[0], prefix = (context.slice(-1) !== '/' && value !== '/' && value !== '') ? context + '/' : context, path = (value.substr(0, 1) !== '/') ? value : value.substr(1), pattern = prefix + path; return self.add.apply(self, [pattern].concat(middleware).concat(submiddleware).concat([handler])); }; }; /** * Navigate through history API * @param {String} path - Pathname * @return {self} Router */ MyRouter.prototype.navigate = function (path) { return this.path(path).trigger('navigate'); }; MyRouter.prototype.path = function (pathname) { var self = this, frag; if ('string' === typeof pathname) { /* Set path */ if (self.options.mode === 'pushState') { frag = (self.options.root) ? (self.options.root + pathname) : pathname; root.history.pushState({}, null, frag); } else if (root.location) { root.location.hash = (self.options.hashBang ? '!' : '') + pathname; } else { root._pathname = pathname || ''; } return this; } else if ('undefined' === typeof pathname) { /* Get path */ if (self.options.mode === 'pushState') { frag = root.location.pathname.replace(self.options.root, ''); } else if (self.options.mode !== 'pushState' && root.location) { frag = (root.location.hash) ? root.location.hash.split((self.options.hashBang ? '#!' : '#'))[1] : ''; } else { frag = root._pathname || ''; } return frag; } else if (pathname === false) { /* Clear path */ if (self.options.mode === 'pushState') { root.history.pushState({}, null, self.options.root || '/'); } else if (root.location) { root.location.hash = (self.options.hashBang) ? '!' : ''; } return self; } }; /** * Create routes based on an object * @param {Object} [Options, Routes] * @param {Object Routes} * @return {self} Router */ MyRouter.listen = function () { var opts, routes; if (arguments[0] && arguments[1]) { opts = arguments[0]; routes = arguments[1]; } else { routes = arguments[0]; } /* Return a new MyRouter instance */ return (function () { /* TODO: Accept multi-level routes */ for (var key in routes) { this.add.call(this, key, routes[key]); } return this; }).call(new MyRouter(opts || {})); }; /** * Create a call stack that can be enqueued by handlers and middleware * @param {Object} router - Router * @param {Object} extendObj - Extend * @return {self} CallStack */ class CallStack { constructor(router, extendObj) { this.stack = CallStack.global.slice(0); this.router = router; this.runCallback = true; this.callbackRan = false; this.propagateEvent = true; this.value = router.path(); for (var key in extendObj) { this[key] = extendObj[key]; } return this; } } /** * Build request parameters and allow them to be checked against a string (usually the current path) * @param {String} route - Route * @return {self} Request */ function Request(route) { this.route = route; this.keys = []; this.regex = MyRouter.regexRoute(route, this.keys); } ; /* This allows global middleware */ CallStack.global = []; /** * Prevent a callback from being called * @return {self} CallStack */ CallStack.prototype.preventDefault = function () { this.runCallback = false; }; /** * Prevent any future callbacks from being called * @return {self} CallStack */ CallStack.prototype.stopPropagation = function () { this.propagateEvent = false; }; /** * Get parent state * @return {Object} Previous state */ CallStack.prototype.parent = function () { var hasParentEvents = !!(this.previousState && this.previousState.value && this.previousState.value == this.value); return (hasParentEvents) ? this.previousState : false; }; /** * Run a callback (calls to next) * @return {self} CallStack */ CallStack.prototype.callback = function () { this.callbackRan = true; this.timeStamp = Date.now(); this.next(); }; /** * Add handler or middleware to the stack * @param {Function|Array} handler - Handler or a array of handlers * @param {Int} atIndex - Index to start inserting * @return {self} CallStack */ CallStack.prototype.enqueue = function (handler, atIndex) { var handlers = (!Array.isArray(handler)) ? [handler] : ((atIndex < handler.length) ? handler.reverse() : handler); while (handlers.length) { this.stack.splice(atIndex || this.stack.length + 1, 0, handlers.shift()); } return this; }; /** * Call to next item in stack -- this adds the `req`, `event`, and `next()` arguments to all middleware * @return {self} CallStack */ CallStack.prototype.next = function () { var self = this; return this.stack.shift().call(this.router, this.req, this, function next() { self.next.call(self); }); }; /** * Match a path string -- returns a request object if there is a match -- returns false otherwise * @param {String} path * @return {Object} req */ Request.prototype.parse = function (path) { var match = path.match(this.regex), self = this; var req = {params: {}, keys: this.keys, matches: (match || []).slice(1), match: match}; /* Build parameters */ MyRouter._forEach(req.matches, function (value, i) { var key = (self.keys[i] && self.keys[i].name) ? self.keys[i].name : i; /* Parameter key will be its key or the iteration index. This is useful if a wildcard (*) is matched */ req.params[key] = (value) ? decodeURIComponent(value) : undefined; }); return req; }; MyRouter.CallStack = CallStack; MyRouter.Request = Request; tts.Router = new MyRouter(); /* * End of MyRouter Router */ /* * AJAX */ tts.grab_form = function (form_id) { try { let myForm = document.getElementById(form_id); let arr = {}; for (var i = 0; i < myForm.elements.length; i++) { let id = myForm.elements[i].id; let value = myForm.elements[i].value; let node = myForm.elements[i].nodeName; if ((node == "INPUT" || node == "TEXTAREA" || node == "SELECT") && (typeof id !== "undefined" && id !== "")) { arr[id] = value; } } return arr; } catch (e) { tts.logger(e); return false; } }; function json_parse(json) { try { var obj = JSON.parse(json); var unfetched = obj.unfetched; if (typeof unfetched !== "undefined") { console.warn(`You have some unFetched JSON Vars: ${unfetched}`); } var err = obj.error; if (typeof err === "undefined") { return obj; } else if (err !== null) { throw err; } } catch (e) { return e; } } tts.send_json = function (php_script, args) { let myPromise = new Promise(function (myResolve, myReject) { if (args === false) { let nodata = "No Data from Form!"; throw nodata; } var xmlhttp = new XMLHttpRequest(); // new HttpRequest instance xmlhttp.open("POST", php_script); xmlhttp.setRequestHeader("Content-Type", "application/json;charset=UTF-8"); xmlhttp.onreadystatechange = function () { if (this.readyState == 4) { if (this.status == 200) { myResolve(json_parse(this.response)); } else { myReject(json_parse(this.response)); } } }; xmlhttp.send(JSON.stringify(args)); }); return myPromise; }; tts.Post = function (url, data) { return new Promise((resolve, reject) => { var request = new XMLHttpRequest(); request.open("POST", url, true); request.setRequestHeader("Content-Type", "application/x-www-form-urlencoded"); request.onload = function (d) { resolve(d.currentTarget.responseText); }; try { request.send(data); } catch (err) { reject(err); } }); }; function doProgress(eventName, evt) { if (eventName !== false && evt.lengthComputable) { var percentComplete = (evt.loaded / evt.total) * 100; var pc = Math.round(percentComplete); var event = new CustomEvent(eventName, {detail: {progress: pc}}); var el = document.getElementsByTagName('body')[0]; el.dispatchEvent(event); } } function setHTML(elementID, html) { try { return document.getElementById(elementID).innerHTML = html; } catch (e) { tts.logger("ID of " + elementID + " not found...!", "warn"); } } tts.lastAjax = false; /* So you can use the xmlHttp Request later on... if not cached... */ let ajaxCallback = function (url, resolve, reject, options) { var doCache = tts.getValue(options.useCache, false), eventName = tts.getValue(options.eventName, false); var elementID = tts.getValue(options.elementID, false), ts = tts.getValue(options.ts, ""); if (doCache) { var myCache = new tts.store(); if (myCache) { let stored_data = myCache.get(url + ts); /* timestamp cache buster */ let done = tts.getValue(stored_data, false); if (!tts.isEmpty(done)) { tts.logger('Used cache, on ' + url + ' !'); tts.lastAjax = false; doProgress(eventName, {lengthComputable: true, loaded: 100, total: 100}); if (elementID) { setHTML(elementID, stored_data); } return resolve(stored_data); } else { tts.logger('Adding to cache, for ' + url + ' !'); } } else { tts.logger('No Cache Engine enabled, for ' + url + ' !'); } } else { tts.logger('No Caching, for ' + url); } var xmlHttp = new XMLHttpRequest(); tts.lastAjax = xmlHttp; xmlHttp.upload.addEventListener("progress", function (evt) { doProgress(eventName, evt); }); xmlHttp.addEventListener("progress", function (evt) { doProgress(eventName, evt); }); xmlHttp.onreadystatechange = function () { var result; if (xmlHttp.readyState == 4) { if (xmlHttp.status == 200) { switch (options.dataType) { case 'xml': result = xmlHttp.responseXML; break; case 'json': result = JSON.parse(xmlHttp.responseText); break; default: result = xmlHttp.responseText; break; } if (myCache && doCache) { myCache.set(url + ts, result); } if (elementID) { setHTML(elementID, result); } resolve(result); } else if (reject) { reject('Ajax error: ' + xmlHttp.status + ' url: ' + url); } } }; xmlHttp.open(options.method || 'GET', url, true); if (options.headers) { for (var key in options.headers) { xmlHttp.setRequestHeader(key, options.headers[key]); } } xmlHttp.send(options.data || ''); }; tts.ajax = function (url, options) { if (typeof options === "undefined") { options = {}; } return new Promise(function (resolve, reject) { ajaxCallback(url, resolve, reject, options); }); }; /* * End of AJAX */ /* * Load Assets */ var assets_loaded_once = []; tts.AddAssetCachedFile = function (full_file) { assets_loaded_once.push(full_file); }; /** * Get an StyleSheet/Script * @param {Object} source - CSS/JavaScript File with Options * @param {Object} options - element to use, etc... * @returns {Promise} */ tts.getAsset = (source, options) => { if (typeof options === "undefined") { options = {}; } return new Promise((resolve, reject) => { var defaults_caching = tts.getValue(DO_CACHE_ON_ASSETS, true); var file = source.name, kind = file.split('.').pop(), doCache = tts.getValue(source.useCache, defaults_caching); var full_file = tts.getValue(source.path, "") + file; var ts = tts.getValue(source.ts, ""); var has_loaded = (assets_loaded_once.indexOf(full_file) === -1) ? false : true; if (has_loaded) { resolve("Already Loaded..." + full_file); } else { assets_loaded_once.push(full_file); switch (kind) { case 'css': var dataType = tts.getValue(source.dataType, "text/css"), style = document.createElement('style'); var elm = tts.getValue(options.element, document.getElementsByTagName('style')[0] || document.getElementsByTagName('head')[0]); var loaded = tts.ajax(full_file, {dataType: "text/css", useCache: doCache, ts: ts}); loaded.then(function (code) { style.type = dataType; style.innerText = code; elm.parentNode.insertBefore(style, elm.nextSibling); setTimeout(function () { resolve(); }, 12); }); loaded.catch(function (e) { reject(e); }); break; default: var dataType = tts.getValue(source.dataType, "text/javascript"); var script = document.createElement('script'); var elm = tts.getValue(options.element, document.getElementsByTagName('script')[0] || document.getElementsByTagName('head')[0]); var loaded = tts.ajax(full_file, {dataType: "text/javascript", useCache: doCache, ts: ts}); loaded.then(function (code) { script.type = dataType; script.text = code; elm.parentNode.insertBefore(script, elm); setTimeout(function () { resolve(); }, 12); }); loaded.catch(function (e) { reject(e); }); break; } } }); }; /** Useage: to combine options on each Asset for use with getMultiAssets. * Updates the sources Array/Objects with new data from Options.....as it is passed by Reference!!! * @param {Array of Objects} sources - CSS/JavaScript File with Options * @param {Array of Objects} options - path, useCache, dataType... */ tts.mergeOptions = function (sources, options) { let keys = Object.keys(options); for (let key of keys) { for (var x = 0; x < sources.length; x++) { if (typeof sources[x][key] === 'undefined') { sources[x][key] = options[key]; } } } }; /** * * @param {Array of Objects} sources - CSS/JavaScript File with Options * @param {Object} options - element to apply to, etc... * @returns {Promise} - All done will all Files. */ tts.getMultiAssets = (sources, options) => { if (typeof options === "undefined") { options = {}; } var prArr = []; sources.forEach(function (source) { (function (source) { prArr.push(new Promise(function (resolve, reject) { tts.getAsset(source, options).then(function () { resolve(); }).catch(function (e) { reject(e); }); })); })(source); }); return Promise.all(prArr, function () { return true; }); }; /* * End of Assets */ /* * Cookies */ var pluses = /\+/g; function encode(s) { return config.raw ? s : encodeURIComponent(s); } function decode(s) { return config.raw ? s : decodeURIComponent(s); } function stringifyCookieValue(value) { return encode(config.json ? JSON.stringify(value) : String(value)); } function parseCookieValue(s) { if (s.indexOf('"') === 0) { /* This is a quoted cookie as according to RFC2068, unescape... */ s = s.slice(1, -1).replace(/\\"/g, '"').replace(/\\\\/g, '\\'); } try { /* Replace server-side written pluses with spaces. */ /* If we can't decode the cookie, ignore it, it's unusable. */ /* If we can't parse the cookie, ignore it, it's unusable. */ s = decodeURIComponent(s.replace(pluses, ' ')); return config.json ? JSON.parse(s) : s; } catch (e) { } } function read(s, converter) { var value = config.raw ? s : parseCookieValue(s); return tts.isFunction(converter) ? converter(value) : value; } var config = tts.cookie = function (key, value, options) { if (arguments.length > 1 && !tts.isFunction(value)) { /* Write */ options = tts.extend(config.defaults, options); if (typeof options.expires === 'number') { var days = options.expires, t = options.expires = new Date(); t.setMilliseconds(t.getMilliseconds() + days * 864e+5); } return (document.cookie = [ encode(key), '=', stringifyCookieValue(value), options.expires ? '; expires=' + options.expires.toUTCString() : '', /* use expires attribute, max-age is not supported by IE */ options.path ? '; path=' + options.path : '', options.domain ? '; domain=' + options.domain : '', options.secure ? '; secure' : '' ].join('')); } var result = key ? undefined : {}, /* Read */ /* To prevent the for loop in the first place assign an empty array * in case there are no cookies at all. Also prevents odd result when * calling $.cookie(). */ cookies = document.cookie ? document.cookie.split('; ') : [], l = cookies.length; for (let i = 0; i < l; i++) { var parts = cookies[i].split('='), name = decode(parts.shift()), cookie = parts.join('='); /* If second argument (value) is a function it's a converter... */ if (key === name) { result = read(cookie, value); break; } /* Prevent storing a cookie that we couldn't decode. */ if (!key && (cookie = read(cookie)) !== undefined) { result[name] = cookie; } } return result; }; config.defaults = {}; tts.removeCookie = function (key, options) { /* Must not alter options, thus extending a fresh object... */ tts.cookie(key, '', $.extend({}, options, {expires: -1})); return !$.cookie(key); }; /* * End of Cookies */ /* * Printer Support */ /* Printer Framed Window */ var array_of_frames = []; /* Needed to track open iFrames */ var printFrameID = 0; function donePrintFrame() { var frm = document.getElementById(printFrameID).contentWindow; frm.focus(); frm.print(); /* set focus on contentWindow is needed on some ie versions */ } /* id is the id of the iframe */ tts.printFrame = function (id, src) { try { for (var i = 0; i < array_of_frames.length; i++) { document.body.removeChild(array_of_frames[i]); /* Delete old page when done, for new data */ array_of_frames.pop(); } var newIframe = document.createElement('iframe'); newIframe.width = '0'; newIframe.height = '0'; newIframe.name = id; newIframe.id = id; newIframe.src = src; printFrameID = id; document.body.appendChild(newIframe); array_of_frames.push(newIframe); /* Add frame to list to be removed next time */ newIframe.onload = donePrintFrame; } catch (err) { tts.logger(err.message); } return false; }; /* * End of Printer Support */ if (typeof module === 'object' && module.exports) { module.exports = tts; } else { window.tts = tts; } }).call({}, ('object' === typeof window) ? window : this, window, document, prefData); /* These get passed into the Local Scope, in the top of this Script function */