commit
4e1e04e526
@ -0,0 +1,4 @@ |
||||
node_modules/ |
||||
assets/dist/ |
||||
package-lock.json |
||||
nbproject/ |
||||
@ -0,0 +1,22 @@ |
||||
The MIT License |
||||
|
||||
Copyright (c) 2021 Robert Strutts |
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining |
||||
a copy of this software and associated documentation files (the |
||||
"Software"), to deal in the Software without restriction, including |
||||
without limitation the rights to use, copy, modify, merge, publish, |
||||
distribute, sublicense, and/or sell copies of the Software, and to |
||||
permit persons to whom the Software is furnished to do so, subject to |
||||
the following conditions: |
||||
|
||||
The above copyright notice and this permission notice shall be |
||||
included in all copies or substantial portions of the Software. |
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, |
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF |
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND |
||||
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE |
||||
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION |
||||
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION |
||||
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. |
||||
@ -0,0 +1,15 @@ |
||||
# tts_js |
||||
|
||||
TTS Framework - JavaScript assets. |
||||
|
||||
Install node, npm, then GulpJS. |
||||
Google how to install node & npm for your OS. |
||||
|
||||
GulpJS here: |
||||
$ sudo npm install --global gulp-cli |
||||
|
||||
Goto this Repo where the package.json file exists, then run: |
||||
$ npm install |
||||
|
||||
Now, Compile all JavaScript assets into the assets/dist folders: |
||||
$ gulp |
||||
@ -0,0 +1,3 @@ |
||||
For instance, jQuery is about 250kb (90kb if minified). |
||||
Not that bad, huh? |
||||
But, if you have 50,000 monthly visitors, jQuery will consume 4Gb! |
||||
@ -0,0 +1,181 @@ |
||||
/* |
||||
* @author Robert Strutts |
||||
* @copyright 2019 |
||||
* @license MIT |
||||
* 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
|
||||
*/ |
||||
@ -0,0 +1,76 @@ |
||||
/* |
||||
* 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 |
||||
*/ |
||||
@ -0,0 +1,361 @@ |
||||
/* |
||||
* Grapnel Router |
||||
* @author Greg Sabia Tucker <greg@narrowlabs.com> |
||||
* @copyright 2019 Greg Sabia Tucker |
||||
* @link https://github.com/baseprime/grapnel
|
||||
* Released under MIT License. See http://opensource.org/licenses/MIT
|
||||
*/ |
||||
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
|
||||
*/ |
||||
@ -0,0 +1,115 @@ |
||||
/* |
||||
* Load Assets |
||||
* @author Robert Strutts |
||||
* @copyright 2019 |
||||
* @license MIT |
||||
*/ |
||||
|
||||
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 |
||||
*/ |
||||
@ -0,0 +1,69 @@ |
||||
/* |
||||
* 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 */ |
||||
@ -0,0 +1,143 @@ |
||||
/* |
||||
* Begin Logger
|
||||
* @author Robert Strutts |
||||
* @copyright 2019 |
||||
* @license MIT |
||||
*/ |
||||
|
||||
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
|
||||
*/ |
||||
@ -0,0 +1,41 @@ |
||||
/* |
||||
* Printer Support |
||||
* @author Robert Strutts |
||||
* @copyright 2019 |
||||
* @license MIT |
||||
*/ |
||||
|
||||
/* 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 |
||||
*/ |
||||
@ -0,0 +1,2 @@ |
||||
var prefData = window.performance.timing; |
||||
!(function (root, window, document, pref_data, undefined) { // (immediately-invoked function expression), for Private Scope. ! means an expression
|
||||
@ -0,0 +1,381 @@ |
||||
/* |
||||
* Miq |
||||
@copyright 2019 Edwin Martin |
||||
@link https://github.com/edwinm/miq/blob/master/miq.js
|
||||
@license MIT |
||||
* |
||||
* Miq, the micro jQuery library |
||||
*/ |
||||
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(/<(.+)>/))) { /* $('<div>') */ |
||||
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); |
||||
}); |
||||
}); |
||||
}; |
||||
@ -0,0 +1,7 @@ |
||||
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 */ |
||||
@ -0,0 +1,11 @@ |
||||
combine = function (source, dest) { |
||||
|
||||
for (var i = 0; i < source.length; i++) { |
||||
dest.push(source[i]); |
||||
} |
||||
|
||||
return dest; |
||||
|
||||
}; |
||||
|
||||
module.exports = combine; |
||||
@ -0,0 +1,39 @@ |
||||
var extend = function () { |
||||
|
||||
// Variables
|
||||
var extended = {}; |
||||
var deep = false; |
||||
var i = 0; |
||||
var length = arguments.length; |
||||
|
||||
// Check if a deep merge
|
||||
if (Object.prototype.toString.call(arguments[0]) === '[object Boolean]') { |
||||
deep = arguments[0]; |
||||
i++; |
||||
} |
||||
|
||||
// Merge the object into the extended object
|
||||
var merge = function (obj) { |
||||
for (var prop in obj) { |
||||
if (Object.prototype.hasOwnProperty.call(obj, prop)) { |
||||
// If deep merge and property is an object, merge properties
|
||||
if (deep && Object.prototype.toString.call(obj[prop]) === '[object Object]') { |
||||
extended[prop] = extend(true, extended[prop], obj[prop]); |
||||
} else { |
||||
extended[prop] = obj[prop]; |
||||
} |
||||
} |
||||
} |
||||
}; |
||||
|
||||
// Loop through each object and conduct a merge
|
||||
for (; i < length; i++) { |
||||
var obj = arguments[i]; |
||||
merge(obj); |
||||
} |
||||
|
||||
return extended; |
||||
|
||||
}; |
||||
|
||||
module.exports = extend; |
||||
@ -0,0 +1,11 @@ |
||||
when = function (arrayOfPromises) { |
||||
return new Promise(function (resolve, reject) { |
||||
Promise.all(arrayOfPromises).then(values => { |
||||
resolve(values); |
||||
}).catch(errors => { |
||||
reject(errors); |
||||
}); |
||||
}); |
||||
}; |
||||
|
||||
module.exports = when; |
||||
@ -0,0 +1,58 @@ |
||||
/* My Plug-Ins */ |
||||
const extend = require('./gulp_deps/gulp-extend'); |
||||
const when = require('./gulp_deps/gulp-when'); |
||||
const combine = require('./gulp_deps/gulp-combine'); |
||||
/* Terser Ugilfy Settings */ |
||||
const ecma_latest = 8; |
||||
const warn_level = { warnings: true }; |
||||
const compress = { compress: { dead_code: true, drop_debugger: false, arrows: false, properties: false } }; |
||||
const mangle = { mangle: false }; // { properties: { keep_quoted: true } }
|
||||
const output = { output: {comments: false} }; // Destroy Commment Blocks!
|
||||
const options = { module: false, keep_classnames: true, keep_fnames: true, toplevel: false, safari10: false }; |
||||
const common = extend( warn_level, compress, mangle, options, output ); |
||||
const uglify_latest_e = { ecma: ecma_latest, ie8: false }; |
||||
const uglify_latest = extend( uglify_latest_e, common ); |
||||
/* Gulp Add-Ons */ |
||||
const { src, dest, series, parallel, watch } = require('gulp'); |
||||
const uglify = require('gulp-terser'); |
||||
const concat = require('gulp-concat'); |
||||
const rename = require('gulp-rename'); |
||||
const sourcemaps = require("gulp-sourcemaps"); |
||||
/* Core TTS JS */ |
||||
const tts_js_files = [
|
||||
'core/begin.js',
|
||||
'core/core.js',
|
||||
'core/addons/*.js', |
||||
'core/end.js'
|
||||
]; |
||||
/* Destination Folders for JS */ |
||||
const js_dest = 'assets/dist/'; |
||||
/* Use Map instead of .js.map */ |
||||
const map = { mapFile: function(mapFilePath) { return mapFilePath.replace('.js.map', '.map'); } }; |
||||
|
||||
function tts_js() { |
||||
return when([ |
||||
new Promise(function(resolve, reject) {
|
||||
src( tts_js_files ) |
||||
.pipe(sourcemaps.init({ loadMaps: true })) |
||||
.pipe(concat( 'tts.js' )) |
||||
.pipe(dest( js_dest )) |
||||
.pipe(rename( { extname: '.min.js' } )) |
||||
.pipe(uglify( uglify_latest ) ) |
||||
.pipe(sourcemaps.write(".", map )) |
||||
.pipe(dest( js_dest )) |
||||
.on('end', resolve); |
||||
}) |
||||
]);
|
||||
} |
||||
|
||||
function watch_js() { |
||||
watch(tts_js_files, tts_js); |
||||
} |
||||
|
||||
exports.js = parallel(tts_js); |
||||
exports.all = parallel(tts_js); |
||||
exports.watcher = series( parallel(tts_js), watch_js ); |
||||
//exports.css = css;
|
||||
//exports.html = html;
|
||||
exports.default = parallel(tts_js); |
||||
@ -0,0 +1,301 @@ |
||||
/* Robs Router Loader */ |
||||
tts.RouteObject = {}; /* This is the main Object to use for AJAX Pages */ |
||||
var include_once_files = []; /* Was this Asset loaded yet, and did the PHP Footer file find this Asset */ |
||||
|
||||
tts.AddRouterCachedFile = function(filename) { |
||||
include_once_files.push(filename); |
||||
};
|
||||
|
||||
function doesAssetExists(filename) { |
||||
// console.log(filename);
|
||||
return new Promise((resolve, reject) => { |
||||
if (hasLoaded(filename) === false) { |
||||
var exists = false; |
||||
for (var i = 0; i < assets_files.length; i++) { |
||||
if (filename == assets_files[i].filename) { |
||||
tts.logger('Loading: ' + filename) |
||||
include_once_files.push(filename); |
||||
exists = true; |
||||
break; |
||||
} |
||||
} |
||||
if (exists === false) { |
||||
reject("skipped: " + filename); |
||||
} else { |
||||
resolve(assets_files[i].ts); |
||||
} |
||||
} else { |
||||
resolve("loaded"); |
||||
} |
||||
}); |
||||
} |
||||
function getClassName(obj) { |
||||
if (typeof obj.constructor.name === "undefined") { |
||||
return obj.constructor.toString().match(/^function\s(.+)\(/)[1]; |
||||
} else { |
||||
return obj.constructor.name; |
||||
} |
||||
} |
||||
function hasLoaded(file) { |
||||
return tts.inArray(file, include_once_files); |
||||
} /* Just checks if file has been loaded once yet */ |
||||
function apply_css(css_file, version) { |
||||
return new Promise((resolve, reject) => { |
||||
tts.getAsset({name: css_file, path: AJAX_Folder, version: version}).then(function () { |
||||
resolve(); |
||||
}).catch(function () { |
||||
reject(); |
||||
}); |
||||
}); |
||||
} |
||||
function hasPromise(obj, fn, text) { // tts.logger("promise"+fn, "trace");
|
||||
if (typeof text === "undefined") { |
||||
text = ""; |
||||
} |
||||
return new Promise((resolve, reject) => { |
||||
var usePromise = tts.getValue(obj.Promise, true); |
||||
if (typeof fn === "undefined" && typeof fn !== "function") { |
||||
reject(text + " Function does not exist"); |
||||
} else { |
||||
if (usePromise === true) { |
||||
tts.logger("Promise exec of " + text); |
||||
fn().then(function (out) { |
||||
resolve(out); |
||||
}).catch(function (e) { |
||||
reject(e); |
||||
}); |
||||
} else { |
||||
tts.logger("Exec of " + text); |
||||
fn(); |
||||
resolve(); |
||||
} |
||||
} |
||||
}); |
||||
} |
||||
/* Run Main method on Class File */ |
||||
function do_run_main(obj) { |
||||
var className = getClassName(obj); |
||||
return new Promise((resolve, reject) => { |
||||
hasPromise(obj, obj['Main'], className).then(function () { |
||||
resolve(); |
||||
}).catch(function (e) { |
||||
reject(e); |
||||
}); |
||||
}); |
||||
} |
||||
; |
||||
/* This will Run JS code for Tabs! */ |
||||
function do_run(obj) { |
||||
var className = getClassName(obj); |
||||
return new Promise((resolve, reject) => { |
||||
hasPromise(obj, obj[obj.tab], className + " " + obj.tab).then(function () { |
||||
resolve(); |
||||
}).catch(function (e) { |
||||
reject(e); |
||||
}); |
||||
}); |
||||
} |
||||
; |
||||
function is_unknown(obj) { |
||||
if (is_404(obj.tab)) { |
||||
var className = getClassName(obj); |
||||
tts.logger(className + " " + obj.tab + " tab FN not found!"); |
||||
do_404_page(); |
||||
return true; |
||||
} |
||||
return false; |
||||
} |
||||
function loadJS(scriptFile, version, obj, fn) { |
||||
var stuff = { name: scriptFile, path: AJAX_Folder, ts: version }; |
||||
// console.log(stuff);
|
||||
return new Promise((resolve, reject) => { |
||||
tts.getAsset(stuff) |
||||
.then(function () { |
||||
switch (fn) { |
||||
case 'ErrorMain': |
||||
hasPromise(obj, obj.Main, "404").then(function () { |
||||
resolve(); |
||||
}).catch(function () { |
||||
reject(); |
||||
}); |
||||
break; |
||||
case 'do_run_main': |
||||
do_run_main(obj).then(function () { |
||||
resolve("js_complete"); |
||||
}).catch(function (e) { |
||||
reject(e); |
||||
}); |
||||
break; |
||||
case 'do_run': |
||||
do_run(obj).then(function () { |
||||
resolve("js_complete"); |
||||
}).catch(function (e) { |
||||
reject(e); |
||||
}); |
||||
break; |
||||
default: |
||||
window[fn](obj).then(function () { |
||||
resolve("js_complete"); |
||||
}).catch(function (e) { |
||||
reject(e); |
||||
}); |
||||
break; |
||||
} |
||||
}).catch(function (exception) { |
||||
switch (fn) { |
||||
case 'ErrorMain': |
||||
tts.logger("404 Page - does not exist", "error"); |
||||
break; |
||||
case 'do_run_main': |
||||
do_run_main(obj).catch(function () { |
||||
reject(e); |
||||
}); |
||||
break; |
||||
case 'do_run': |
||||
do_run(obj).catch(function () { |
||||
reject(e); |
||||
}); |
||||
break; |
||||
default: |
||||
window[fn](obj).catch(function () { }); |
||||
break; |
||||
} |
||||
if (fn !== 'ErrorMain') { |
||||
tts.logger("Something went wrong: " + exception, "warn"); |
||||
} |
||||
reject('Something went wrong'); |
||||
}); |
||||
}); |
||||
} |
||||
tts.JS_EXT = ".js"; |
||||
tts.CSS_EXT = ".css"; |
||||
/* Does Class StartUp, CSS, and JS - After Main JS has completed loading... */ |
||||
function do_other_FN(obj) { |
||||
return new Promise((resolve, reject) => { |
||||
var className = getClassName(obj); |
||||
var tab = tts.getValue(obj.tab, false); |
||||
hasPromise(obj, obj['StartUp'], "Start Up").catch(function () { }); |
||||
if (tab === false) { |
||||
resolve(); |
||||
} else { |
||||
var Script_File = className + "_" + tab + tts.JS_EXT; |
||||
var CSS_File = className + "_" + tab + tts.CSS_EXT; |
||||
var MainCSS_File = className + "_Main" + tts.CSS_EXT; |
||||
doesAssetExists(Script_File).then(function (versionNumber) { |
||||
if (versionNumber === 'loaded') { |
||||
do_run(obj).then(function (ok) { |
||||
resolve(ok); |
||||
}).catch(function (e) { |
||||
reject(e); |
||||
}); |
||||
} else { |
||||
loadJS(Script_File, versionNumber, obj, 'do_run').then(function (ok) { |
||||
resolve(ok); |
||||
}).catch(function (e) { |
||||
reject(e); |
||||
}); |
||||
} |
||||
}).catch(function (err) { |
||||
do_run(obj).then(function (ok) { |
||||
resolve(ok); |
||||
}).catch(function (e) { |
||||
is_unknown(obj); |
||||
reject(e); |
||||
}); |
||||
}); |
||||
doesAssetExists(MainCSS_File).then(function (versionNumber) { |
||||
if (versionNumber !== 'loaded') { |
||||
apply_css(MainCSS_File, versionNumber); |
||||
} |
||||
}).catch(function (e) { }); |
||||
doesAssetExists(CSS_File).then(function (versionNumber) { |
||||
if (versionNumber !== 'loaded') { |
||||
apply_css(CSS_File, versionNumber); |
||||
} |
||||
}).catch(function (e) { }); |
||||
} |
||||
}); |
||||
} |
||||
function mainRouting(obj) { |
||||
return new Promise((resolve, reject) => { |
||||
tts.RouteObject = obj; |
||||
var className = getClassName(obj); |
||||
var MainScript_File = className + "_Main" + tts.JS_EXT; |
||||
doesAssetExists(MainScript_File).then(function (versionNumber) { |
||||
if (versionNumber === 'loaded') { |
||||
do_run_main(obj).then(function () { |
||||
do_other_FN(obj).then(function (ok) { |
||||
resolve(ok); |
||||
}).catch(function (e) { |
||||
reject(e); |
||||
}); |
||||
}).catch(function (e) { |
||||
reject(e); |
||||
}); |
||||
} else { |
||||
loadJS(MainScript_File, versionNumber, obj, 'do_run_main').then(function () { |
||||
do_other_FN(obj).then(function (ok) { |
||||
resolve(ok); |
||||
}).catch(function (e) { |
||||
reject(e); |
||||
}); |
||||
}).catch(function (e) { |
||||
reject(e); |
||||
}); |
||||
} |
||||
}).catch(function (err) { |
||||
do_run_main(obj).then(function () { |
||||
do_other_FN(obj).then(function (ok) { |
||||
resolve(ok); |
||||
}).catch(function (e) { |
||||
reject(e); |
||||
}); |
||||
}).catch(function (e) { |
||||
reject(e); |
||||
}); |
||||
}); |
||||
}); |
||||
} |
||||
|
||||
tts.Route = function (obj) { /* This is the core loader for Tabs and Main Route */ |
||||
tts.startCodeTimer(); |
||||
return new Promise((resolve, reject) => { |
||||
mainRouting(obj).then(function (r) { |
||||
tts.endCodeTimer(); |
||||
$_.logger(r + " - Resolved Took " + tts.completedCodeTimer); |
||||
resolve(r); |
||||
}).catch(function (e) { |
||||
tts.endCodeTimer(); |
||||
$_.logger(e + " - Rejected Took " + tts.completedCodeTimer); |
||||
reject(e); |
||||
}); |
||||
}); |
||||
}; |
||||
/* Load 404 JS for doing 404 Page */ |
||||
function do_404_page() { |
||||
var ErrorScript_File = "PageNotFound_Main" + tts.JS_EXT; |
||||
var err_page = new PageNotFound(false); |
||||
doesAssetExists(ErrorScript_File).then(function (versionNumber) { |
||||
if (versionNumber === 'loaded') { |
||||
err_page.Main(); |
||||
} else { |
||||
loadJS(ErrorScript_File, versionNumber, err_page, "ErrorMain").catch(function (e) { }); |
||||
} |
||||
}).catch(function (err) { |
||||
tts.logger("404 Page - does not exist", "error"); |
||||
}); |
||||
} |
||||
/* Is 404 on, if so does Tab Method/File exists, if not was an exception made */ |
||||
tts.do_404_page_on_bad_Route = true; |
||||
tts.empty_Route_pages = []; |
||||
function is_404(tab_name) { |
||||
if (tts.do_404_page_on_bad_Route === false) |
||||
return false; /* Is 404 off?? */ |
||||
for (var i = 0; i < tts.empty_Route_pages.length; i++) { |
||||
if (tts.empty_Route_pages[i] == tab_name) { |
||||
return false; /* Found allowed empty tab page */ |
||||
} |
||||
} |
||||
return true; /* Unable to find tab page hash in allowed list */ |
||||
} |
||||
/* End of Robs Router Loader */ |
||||
@ -0,0 +1,18 @@ |
||||
{ |
||||
"name": "tts_js", |
||||
"version": "1.0.0", |
||||
"description": "TTS Framework JavaScript Assets.", |
||||
"main": "gulpfile.js", |
||||
"scripts": { |
||||
"test": "echo \"Error: no test specified\" && exit 1" |
||||
}, |
||||
"author": "Robert Strutts", |
||||
"license": "MIT", |
||||
"devDependencies": { |
||||
"gulp": "^4.0.2", |
||||
"gulp-concat": "^2.6.1", |
||||
"gulp-rename": "^2.0.0", |
||||
"gulp-sourcemaps": "^3.0.0", |
||||
"gulp-terser": "^2.1.0" |
||||
} |
||||
} |
||||
Loading…
Reference in new issue