export class V{ constructor(data){ // start time this.time = +new Date(); // properties change this.prop = { console: true, page: 'index', tablet: 1199, mobile: 760 }; for(let value in data){ this.prop[value] = data[value]; } this.prefix = `v-`; this.name = 'V'; this.eventListenerAttribute = `v_eventListeners`; } }; Number.isInteger = Number.isInteger || function(value) { return typeof value === 'number' && Number.isFinite(value) && !(value % 1); }; Number.isFinite = Number.isFinite || function(value) { return typeof value === 'number' && isFinite(value); } if (![].includes) { Array.prototype.includes = function(searchElement /*, fromIndex*/ ) { 'use strict'; var O = Object(this); var len = parseInt(O.length) || 0; if (len === 0) { return false; } var n = parseInt(arguments[1]) || 0; var k; if (n >= 0) { k = n; } else { k = len + n; if (k < 0) { k = 0; } } while (k < len) { var currentElement = O[k]; if (searchElement === currentElement || (searchElement !== searchElement && currentElement !== currentElement) ) { return true; } k++; } return false; }; } if (!String.prototype.includes) { String.prototype.includes = function() { 'use strict'; return String.prototype.indexOf.apply(this, arguments) !== -1; }; } if (typeof Object.assign != 'function') { // Must be writable: true, enumerable: false, configurable: true Object.defineProperty(Object, "assign", { value: function assign(target, varArgs) { // .length of function is 2 'use strict'; if (target == null) { // TypeError if undefined or null throw new TypeError('Cannot convert undefined or null to object'); } var to = Object(target); for (var index = 1; index < arguments.length; index++) { var nextSource = arguments[index]; if (nextSource != null) { // Skip over if undefined or null for (var nextKey in nextSource) { // Avoid bugs when hasOwnProperty is shadowed if (Object.prototype.hasOwnProperty.call(nextSource, nextKey)) { to[nextKey] = nextSource[nextKey]; } } } } return to; }, writable: true, configurable: true }); } if (!('remove' in Element.prototype)) { Element.prototype.remove = function() { if (this.parentNode) { this.parentNode.removeChild(this); } }; }; V.prototype.loaded = false; V.prototype.page = []; V.prototype.doc = document; V.prototype.document = document.documentElement; V.prototype.body = document.body; V.prototype.vw = []; V.prototype.vh = []; V.prototype.resize = []; V.prototype.timeMin = 25; V.prototype.ajaxTimeMax = 5000;; V.prototype.console = function(string = '', obj = null, type = '', bool = this.prop.console){ if(bool !== true){ return false; } if(string.length > 0){ let styles = { 'title': 'font: 2.5em/1 Arial; color: #298DA4;', 'info': 'font: 1.25em/1 Arial; color: dodgerblue;', 'error': 'font: 1.25em/1 Arial; color: crimson;', 'warn': 'font: 1.25em/1 Arial; color: orange;', 'log': 'font: 1.25em/1 Arial; color: darkgray;' }; switch(type){ case 'title': console.log('%c' + string, styles['title']); break; case 'info': console.info('%c' + string, styles['info']); break; case 'error': console.error('%c' + string, styles['error']); break; case 'warn': console.warn('%c' + string, styles['warn']); break; default: console.log('%c' + string, styles['log']); } } if(obj !== null){ console.dir(obj); } return true; };; V.prototype.checkType = function(type = 'function', data = false, prop = {}){ if(type === 'function'){ let getType = {}; return data && getType.toString.call(data) === '[object Function]'; } if(type === 'dom'){ let el = this.doc.querySelector(data); if(el === null){ return false; } return true; } if(type === 'htmlElement'){ if(!(data instanceof HTMLElement)){ return false; } return true; } if(type === 'object'){ if(typeof data !== 'object'){ return false; } return true; } if(type === 'string'){ if(typeof data !== 'string'){ return false; } return true; } if(type === 'number'){ if(typeof data !== 'number'){ return false; } return true; } if(type === 'integer'){ if(!Number.isInteger(data)){ return false; } return true; } if(type === 'boolean'){ if(typeof data !== 'boolean'){ return false; } return true; } if(type === 'array'){ if(!Array.isArray(data)){ return false; } return true; } else if(type === 'bezier'){ let further = true; if(!data){ return false; } if(typeof data.on !== "undefined"){ if(typeof data.on !== 'boolean'){ further = false; } } else{ further = false; } if(typeof data.name !== 'string'){ if(data.values){ if(!Array.isArray(data.values)){ further = false; } else{ if(data.values.length < 4){ further = false; } else{ for(let i = 0; i < data.values.length; i++){ if(typeof data.values[i] !== 'number'){ further = false; } } } } } else{ further = false; } } return further; } else if(type === 'numberArray'){ if(!Array.isArray(data)){ return false; } if(data.length < prop.count){ return false; } for(let i = 0; i < data.length; i++){ if(typeof data[i] !== 'number'){ return false; } } return true; } else if(type === 'functionArray'){ if(!Array.isArray(data)){ return false; } if(data.length < prop.count){ return false; } for(let i = 0; i < data.length; i++){ if(typeof data[i] !== 'function'){ return false; } } return true; } else if(type === 'stringArray'){ if(!Array.isArray(data)){ return false; } if(data.length < prop.count){ return false; } for(let i = 0; i < data.length; i++){ if(typeof data[i] !== 'string'){ return false; } } return true; } else if(type === 'callback'){ if(typeof data.target !== "undefined"){ if(typeof data.target !== 'number'){ return false; } } else{ return false; } if(typeof data.do !== "undefined"){ if(!this.checkType("function", data.do)){ return false; } } else{ return false; } return true; } else if(type === 'callbacks'){ if(!Array.isArray(data)){ return false; } for(let i = 0; i < data.length; i++){ if(!this.checkType("callback", data[i])){ return false; } } return true; } else if(type === 'styleCallback'){ if(typeof data.scope !== "undefined"){ if(!this.checkType("numberArray", data.scope, {count: 2})){ return false; } } else{ return false; } if(typeof data.property !== "undefined"){ if(typeof data.property !== 'string'){ return false; } } else{ return false; } if(typeof data.value !== "undefined"){ if(!this.checkType("function", data.value)){ return false; } } else{ return false; } return true; } else if(type === 'styleCallbacks'){ if(!Array.isArray(data)){ return false; } for(let i = 0; i < data.length; i++){ if(!this.checkType("styleCallback", data[i])){ return false; } } return true; } else{ return false; } }; V.prototype.checkTypes = function({ obj = {}, name = 'Name', console = true, vars = [] } = { obj: {}, name: 'Name', console: true, vars: [] }){ // check arguments if(!this.checkType("object", obj)){ return false; } if(!this.checkType("string", name)){ return false; } if(!this.checkType("boolean", console)){ return false; } if(!this.checkType("array", vars)){ return false; } else{ /*for(let i = 0; i < vars.length; i++){ if(!this.checkType("stringArray", vars[i], {count: 2})){ return false; } }*/ } // check obj let errors = []; for(let i = 0; i < vars.length; i++){ if(typeof obj[vars[i][0]] === "undefined"){ errors.push(`${name}. ${vars[i][0]} doesn't exist in`); } else{ if(!this.checkType(vars[i][1], obj[vars[i][0]], vars[i][2])){ errors.push(`${name}. ${vars[i][0]} must be a ${vars[i][1]}`); } } } if(errors.length === 0){ return true; } else{ for(let i = 0; i < errors.length; i++){ this.console(errors[i], obj, 'error', console); } return false; } }; V.prototype.childOf = function(element = null, parent = null){ if(element === null || parent === null){ return false; } function checkChildOf(element = null, parent = null){ if(element === null || parent === null){ return false; } let contains = false; if(element === parent){ contains = true; } if(contains !== true){ if(element !== null){ return checkChildOf(element.parentNode, parent); } else{ return false; } } else{ return true; } return false; } return checkChildOf(element, parent); }; V.prototype.removeChildren = function(parent = null){ // check if(!this.checkType("htmlElement", parent)){ return false; } while(parent.firstChild){ parent.removeChild(parent.firstChild); } return true; }; V.prototype.insertAfter = function(refEl = null, el = null, outer = null){ if(refEl == null || el == null){ return false; } let parent = outer == null ? refEl.parentNode : outer, next = refEl.nextSibling; if(next){ parent.insertBefore(el, next); } else{ parent.appendChild(el); } return true; }; V.prototype.bindEventListener = function(data = {}){ // check let prop = { el: null, target: '', do: () => {} }; for(let value in data){ prop[value] = data[value]; } if(!this.checkType('htmlElement', prop.el) & prop.el != window){ return false; } if(!this.checkType('string', prop.target)){ return false; } if(!this.checkType('function', prop.do)){ return false; } let returnObj = {}; // add events object to the element if(!this.checkType("object", prop.el[this.eventListenerAttribute])){ prop.el[this.eventListenerAttribute] = {}; } // bind event let id = `${prop.target}__${Math.random()}`; prop.el.addEventListener(prop.target, prop.do, false); prop.el[this.eventListenerAttribute][id] = prop.do; return { el: prop.el, id: id }; } V.prototype.getEventListener = function(data){ // check let prop = { el: null, id: '' }; for(let value in data){ prop[value] = data[value]; } if(!this.checkType('htmlElement', prop.el) & prop.el != window){ return false; } if(!this.checkType('string', prop.id)){ return false; } // add events object to the element if(!this.checkType("object", prop.el[this.eventListenerAttribute])){ return false; } // search event by id for(let p in prop.el[this.eventListenerAttribute]){ if(p === prop.id){ return { el: prop.el, id: prop.id, do: prop.el[this.eventListenerAttribute][p] } } } return false; } V.prototype.unbindEventListener = function(data){ // get event let event = this.getEventListener(data); if(!event){ return false; } // delete event let target = event.id; target = target.split("__"); event.el.removeEventListener(target[0], event.do, false); delete event.el[this.eventListenerAttribute][event.id]; return true; }; V.prototype.loadEvent = function(){ this.load = []; window.addEventListener("load", function(){ this.loaded = true; for(let i = 0; i < this.load.length; i++){ let array = this.load[i][1]; if(this.checkType("function", array)){ array(); } } this.body.classList.remove("v-loading"); this.time = +new Date() - this.time; this.console(`The page has been loaded for ${this.time/1000}s`); }.bind(this)); return true; };; V.prototype.addLoad = function(data){ let id = 'load-' + (+new Date() / Math.random() * Math.random()); this.load.push([id, data]); return id; };; V.prototype.deleteLoad = function(id = ''){ let exists = false; for(let i = 0; i < this.load.length; i++){ let currentId = this.load[i][0]; if(currentId === id){ this.load[i][1] = []; exists = true; } } return exists; };; V.prototype.setPage = function(){ let page = this.prop.page.split(" "); for(let i = 0; i < page.length; i++){ this.page.push(page[i]); this.document.classList.add(`${this.prefix}page_${page[i]}`); } this.console(`Page:`, this.page); return this.page; };; V.prototype.checkPage = function(string = 'index'){ for(let i = 0; i < this.page.length; i++){ if(string === this.page[i]){ return true; } } return false; }; V.prototype.setOS = function(){ let a = 0; switch (navigator.userAgent.indexOf("Windows") != -1 && (a = 1), navigator.userAgent.indexOf("Linux") != -1 && (a = 2), navigator.userAgent.indexOf("Mac") != -1 && (a = 3), navigator.userAgent.indexOf("FreeBSD") != -1 && (a = 4), a) { case 1: return "windows"; case 2: return "linux"; case 3: return "macos"; case 4: return "freebsd"; default: return "unknown"; } };; V.prototype.setBrowser = function(){ // Opera 8.0+ let isOpera = (!!window.opr && !!opr.addons) || !!window.opera || navigator.userAgent.indexOf(' OPR/') >= 0; // Firefox 1.0+ let isFirefox = typeof InstallTrigger !== 'undefined'; // Safari 3.0+ "[object HTMLElementConstructor]" let isSafari = /constructor/i.test(window.HTMLElement) || (function (p) { return p.toString() === "[object SafariRemoteNotification]"; })(!window['safari'] || safari.pushNotification); // Internet Explorer 6-11 let isIE = /*@cc_on!@*/false || !!document.documentMode; // Edge 20+ let isEdge = !isIE && !!window.StyleMedia; // Chrome 1+ let isChrome = /Chrome/.test(navigator.userAgent) && /Google Inc/.test(navigator.vendor); // Blink engine detection //let isBlink = (isChrome || isOpera) && !!window.CSS; if(isOpera){ return 'opera'; } if(isFirefox){ return 'firefox'; } if(isSafari){ return 'safari'; } if(isIE){ return 'ie'; } if(isEdge){ return 'edge'; } if(isChrome){ return 'chrome'; } return 'unknown'; };; V.prototype.mobileCheck = function(){ let check = false; (function(a){if(/(android|bb\d+|meego).+mobile|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge |maemo|midp|mmp|mobile.+firefox|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\.(browser|link)|vodafone|wap|windows ce|xda|xiino|android|ipad|playbook|silk/i.test(a)||/1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s\-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|\-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw\-(n|u)|c55\/|capi|ccwa|cdm\-|cell|chtm|cldc|cmd\-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc\-s|devi|dica|dmob|do(c|p)o|ds(12|\-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(\-|_)|g1 u|g560|gene|gf\-5|g\-mo|go(\.w|od)|gr(ad|un)|haie|hcit|hd\-(m|p|t)|hei\-|hi(pt|ta)|hp( i|ip)|hs\-c|ht(c(\-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i\-(20|go|ma)|i230|iac( |\-|\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\/)|klon|kpt |kwc\-|kyo(c|k)|le(no|xi)|lg( g|\/(k|l|u)|50|54|\-[a-w])|libw|lynx|m1\-w|m3ga|m50\/|ma(te|ui|xo)|mc(01|21|ca)|m\-cr|me(rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(\-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)\-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|\-([1-8]|c))|phil|pire|pl(ay|uc)|pn\-2|po(ck|rt|se)|prox|psio|pt\-g|qa\-a|qc(07|12|21|32|60|\-[2-7]|i\-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h\-|oo|p\-)|sdk\/|se(c(\-|0|1)|47|mc|nd|ri)|sgh\-|shar|sie(\-|m)|sk\-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h\-|v\-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl\-|tdg\-|tel(i|m)|tim\-|t\-mo|to(pl|sh)|ts(70|m\-|m3|m5)|tx\-9|up(\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|\-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(\-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|yas\-|your|zeto|zte\-/i.test(a.substr(0,4))) check = true;})(navigator.userAgent||navigator.vendor||window.opera); return check; }; V.prototype.Event = class Event extends V{ constructor(data = {}){ super(); this.prop = { console: this.prop.console }; for (let value in data) { this.prop[value] = data[value]; } this.name = 'Event'; this.events = []; this.targets = []; this.setEvent(); } init(){ return { add: this.add.bind(this), delete: this.delete.bind(this), turn: this.turn.bind(this), get: this.getEvent.bind(this), events: () => this.events, }; } target(target = ''){ let exists = false; for(let i = 0; i < this.targets.length; i++){ if(target === this.targets[i]){ exists = true; } } if(this.targets.length === 0){ exists = true; } return exists; } do(data){ if(!this.checkType("function", data)){ return false; } return true; } checkEvent(data = {}){ // do if(!this.do(data.do)){ return false; } return true; } add(data = {}, bool = true, console = this.prop.console){ let checked = this.checkEvent(data); if(checked){ let id = `${this.name}-${+new Date()}-${Math.random()}`, array = { id: id, on: bool, data: data }; this.events.push(array); this.console(`${this.name}. Event "${id}" added`, array, 'info', console); this.addCallback(id); return id; } return false; } delete(id = '', console = this.prop.console){ let exists = false, array = []; for(let i = 0; i < this.events.length; i++){ if(this.events[i] === null){ continue; } let currentId = this.events[i].id; if(currentId === id){ this.deleteCallback(id); this.events[i] = null; exists = true; this.console(`${this.name}. Event "${id}" deleted`, null, 'info', console); } else{ array.push(this.events[i]); } } this.events = array; return exists; } deleteAll(console = this.prop.console){ for(let i = 0; i < this.events.length; i++){ if(this.events[i] === null){ continue; } let id = this.events[i].id; this.deleteCallback(id); this.events[i] = null; this.console(`${this.name}. Event "${id}" deleted`, null, 'info', console); } this.events = []; return true; } turn(id = '', bool = true, console = this.prop.console){ let exists = false; for(let i = 0; i < this.events.length; i++){ if(this.events[i] === null){ continue; } let currentId = this.events[i].id; if(currentId === id){ this.events[i].on = bool; exists = true; this.console(`${this.name}. Event "${id}" turned to ${bool}`, null, 'info', console); } } this.turnCallback(id); return exists; } setEvent(){ return true; } addCallback(id = ''){ return true; } turnCallback(id = ''){ return true; } deleteCallback(id = ''){ return true; } getEvent(id = ''){ for(let i = 0; i < this.events.length; i++){ if(this.events[i] === null){ continue; } if(this.events[i].id === id){ return this.events[i]; } } return false; } launchEvent(data = null, func = function(){}){ let timeout = 0; if(data.data.timeout){ timeout = data.data.timeout; } if(timeout === 0){ func(); } else{ setTimeout(func.bind(this), timeout); } return true; } launchEvents(){ for(let i = 0; i < this.events.length; i++){ if(this.events[i] === null){ continue; } if(this.events[i].on){ this.launchEvent(this.events[i], this.events[i].data.do.bind(this)); } } return true; } launchEventsByTarget(currentTarget = '', argumentsData = {}){ for(let i = 0; i < this.events.length; i++){ if(this.events[i] === null){ continue; } if(typeof this.events[i].data.target !== undefined){ if(this.events[i].data.target === currentTarget & this.events[i].on){ this.launchEvent(this.events[i], this.events[i].data.do.bind(this, argumentsData)); } } } return true; } }; V.prototype.Viewport = class Viewport extends V.prototype.Event{ constructor(data = {}){ super(data); this.name = 'Viewport'; this.targets = [ 'w', 'h', 'wh', 'hw' ]; } init(){ return { add: this.add.bind(this), delete: this.delete.bind(this), turn: this.turn.bind(this), get: this.getEvent.bind(this), events: () => this.events, vw: () => this.vw, vh: () => this.vh, dpr: () => this.dpr, desktop: () => this.desktop, tablet: () => this.tablet, mobile: () => this.mobile, }; } checkEvent(data = {}){ if(!super.checkEvent(data)){ return false; } // target if(!this.target(data.target)){ return false; } // timeout if(data.timeout){ if(!Number.isInteger(data.timeout)){ return false; } } return true; } setEvent(){ window.addEventListener("resize", this.implement.bind(this)); return this.setViewport(); } implement(){ // update viewport values this.vw[1] = this.document.clientWidth; this.vh[1] = this.document.clientHeight; // go through callbacks for(let i = 0; i < this.events.length; i++){ if(this.events[i] === null){ continue; } if(typeof this.events[i].data.target !== undefined & this.events[i].on){ // w if(this.events[i].data.target === 'w' & (this.vw[0] !== this.vw[1])){ this.launchEvent(this.events[i], this.events[i].data.do.bind(this)); } // h if(this.events[i].data.target === 'h' & (this.vh[0] !== this.vh[1])){ this.launchEvent(this.events[i], this.events[i].data.do.bind(this)); } // wh & hw if(this.events[i].data.target === 'wh' || this.events[i].data.target === 'hw'){ this.launchEvent(this.events[i], this.events[i].data.do.bind(this)); } } } // set viewport this.setViewport(); return true; } setViewport(){ // get sizes this.vw = [ this.document.clientWidth, this.document.clientWidth ]; this.vh = [ this.document.clientHeight, this.document.clientHeight ]; // get device pixel ratio this.dpr = this.getDPR(); // print to console this.console(`Viewport width: ${this.vw[1]}. Viewport height: ${this.vh[1]}`); // add breakpoint classes this.setViewportClass(); // breakpoints this.setViewportBreakpoints(); // mobile this.setViewportMobile(); return { vw: this.vw, vh: this.vh, dpr: this.dpr }; } getDPR(){ let dpr = 1; if(typeof window.devicePixelRatio != "undefined"){ dpr = window.devicePixelRatio; } return dpr; } setViewportClass(){ if(this.vw[1] <= this.prop.tablet){ this.document.classList.add(`${this.prefix}tablet`); } else{ this.document.classList.remove(`${this.prefix}tablet`); } if(this.vw[1] <= this.prop.mobile){ this.document.classList.add(`${this.prefix}mobile`); } else{ this.document.classList.remove(`${this.prefix}mobile`); } if(this.vw[1] > this.vh[1]){ this.document.classList.add(`${this.prefix}landscape`); this.document.classList.remove(`${this.prefix}protrait`); } else if(this.vw[1] < this.vh[1]){ this.document.classList.remove(`${this.prefix}landscape`); this.document.classList.add(`${this.prefix}protrait`); } } setViewportBreakpoints(){ if(this.vw[1] > this.prop.tablet){ this.desktop = true; this.tablet = false; this.mobile = false; } else{ if(this.vw[1] > this.prop.mobile){ this.desktop = false; this.tablet = true; this.mobile = false; } else{ this.desktop = false; this.tablet = false; this.mobile = true; } } } setViewportMobile(){ if(this.mobileCheck()){ this.document.classList.add(`${this.prefix}mobile-device`); } else{ this.document.classList.remove(`${this.prefix}mobile-device`); } } };; V.prototype.addResize = function(data){ let id = '', obj = {}; // array if(v.checkType("array", data)){ if(data.length < 2){ return false; } if(!this.checkType('function', data[1])){ return false; } let timeout = this.timeMin; if(!data[2]){ timeout = this.timeMin; } else{ if(Number.isInteger(data[2])){ timeout = data[2]; } } obj = { target: data[0], do: data[1], timeout: timeout, name: 'none' //data[1].name } } // object else{ obj = data; } // add id = this.viewport.add(obj); return id; }; V.prototype.deleteResize = function(id = ''){ let result = this.viewport.delete(id); return result; }; V.prototype.turnResize = function(id = '', bool = true){ let result = this.viewport.turn(id, bool); return result; };; V.prototype.getParam = function({ name = 'name', url = window.location.href } = { name: 'name', url: window.location.href }){ name = name.replace(/[\[\]]/g, "\\$&"); let regex = new RegExp("[?&]" + name + "(=([^]*)|&|#|$)"), results = regex.exec(url); if (!results){ return null; } if (!results[2]){ return ''; } return decodeURIComponent(results[2].replace(/\+/g, " ")); }; V.prototype.setParam = function({ name = 'name', value = 'value', push = true, url = '' } = { name: 'name', value: 'value', push: false, url: '' }){ name = encodeURI(name); value = encodeURI(value); let urlObj = null; if(url.length > 0){ urlObj = new URL(url); } else{ urlObj = window.location; } let kvp = urlObj.search.substr(1) === "" ? [] : urlObj.search.substr(1).split('&'), i=kvp.length, x; while(i--){ x = kvp[i].split('='); if (x[0] == name){ x[1] = value; kvp[i] = x.join('='); break; } } if(i<0) {kvp[kvp.length] = [name,value].join('=');} let string = urlObj.pathname + '?' + kvp.join('&'); if(value.length === 0){ string = string.replace("?" + name + "=&", "?"); string = string.replace("?" + name + "=", ""); string = string.replace("&" + name + "=", ""); string = string.replace(name + "=", ""); } if(push === true){ window.history.pushState(null, "", string); return string; } else{ return string; } }; V.prototype.popState = function(){ /*window.onpopstate = function(e){ /*if(e.state !== null) { location.reload(); } }*/ return true; }; V.prototype.ajaxCache = {}; // get cache method V.prototype.ajaxGetCache = function(prop = {}){ let exists = false; // go through all variants for(let key in this.ajaxCache){ // if url if(key == prop.url){ // go through all possible variants with the same url for(let i = 0; i < this.ajaxCache[key].length; i++){ // get obj let obj = this.ajaxCache[key][i]; // compare method if(prop.method != obj.method){ continue; } // compare data let length = Object.keys(prop.data).length, overlaps = 0; for(let dataKey in obj.data){ for(let propKey in prop.data){ if(dataKey == propKey & obj.data[dataKey] == prop.data[propKey]){ overlaps++; } } } if(overlaps == length){ exists = obj; } } } } return exists; } V.prototype.ajaxSetCache = function(prop = {}){ if(typeof this.ajaxCache[prop.url] == 'undefined'){ this.ajaxCache[prop.url] = []; } this.ajaxCache[prop.url].push(prop); return true; } // ajax query method V.prototype.ajax = function(data = {}){ // check data if(!this.checkType("object", data)){ return false; } // extend let prop = { method: 'post', url: window.location.href, data: {}, cache: false, abortOnError: true, callback: function(){}, fail: function(){}, error: function(){} }; for(let value in data){ prop[value] = data[value]; } // check let checked = this.checkTypes({ obj: prop, console: false, vars: [ ['method', 'string'], ['url', 'string'], ['data', 'object'], ['cache', 'boolean'], ['abortOnError', 'boolean'], ['callback', 'function'], ['fail', 'function'], ['error', 'function'] ] }); if(!checked){ return false; } prop.method = prop.method.toLocaleLowerCase(); if(prop.method !== 'post' & prop.method !== 'get'){ return false; } // send let existsInCache = false; if(prop.cache){ existsInCache = this.ajaxGetCache(prop); } if(!existsInCache){ let send = $[prop.method]( prop.url, prop.data, function(html){ if(prop.cache){ this.ajaxSetCache(Object.assign({content: html}, prop)); } prop.callback.call(this, html); }.bind(this) ).fail(function(jqXHR, textStatus){ if(textStatus == 'error' & prop.abortOnError){ prop.error(); } else{ if(textStatus == 'error'){ prop.error(); } prop.fail(); } }.bind(this)); setTimeout(function(p){ p.abort(); }.bind(this, send), this.ajaxTimeMax); } else{ prop.callback(existsInCache.content); } return true; }; V.prototype.bezier = function({ values = [1, 1, 1, 1], x = 0, t = 1, b = 0, c = 0, d = 1000, name = null } = { values: [1, 1, 1, 1], x: 0, t: 1, b: 0, c: 0, d: 1000, name: null }){ let result = t; if(name === null){ result = this.bezierCurve(values, t); } else{ switch(name){ case 'easeInQuad': return c * (t /= d) * t + b; break; case 'easeOutQuad': return -c * (t /= d) * (t - 2) + b; break; case 'easeInOutQuad': if ((t /= d / 2) < 1) return c / 2 * t * t + b; return -c / 2 * ((--t) * (t - 2) - 1) + b; break; case 'easeInCubic': return c * (t /= d) * t * t + b; break; case 'easeOutCubic': return c * ((t = t / d - 1) * t * t + 1) + b; break; case 'easeInOutCubic': if ((t /= d / 2) < 1) return c / 2 * t * t * t + b; return c / 2 * ((t -= 2) * t * t + 2) + b; break; case 'easeInQuart': return c * (t /= d) * t * t * t + b; break; case 'easeOutQuart': return -c * ((t = t / d - 1) * t * t * t - 1) + b; break; case 'easeInOutQuart': if ((t /= d / 2) < 1) return c / 2 * t * t * t * t + b; return -c / 2 * ((t -= 2) * t * t * t - 2) + b; break; case 'easeInQuint': return c * (t /= d) * t * t * t * t + b; break; case 'easeOutQuint': return c * ((t = t / d - 1) * t * t * t * t + 1) + b; break; case 'easeInOutQuint': if ((t /= d / 2) < 1) return c / 2 * t * t * t * t * t + b; return c / 2 * ((t -= 2) * t * t * t * t + 2) + b; break; case 'easeInSine': return -c * Math.cos(t / d * (Math.PI / 2)) + c + b; break; case 'easeOutSine': return c * Math.sin(t / d * (Math.PI / 2)) + b; break; case 'easeInOutSine': return -c / 2 * (Math.cos(Math.PI * t / d) - 1) + b; break; case 'easeInExpo': return (t == 0) ? b : c * Math.pow(2, 10 * (t / d - 1)) + b; break; case 'easeOutExpo': return (t == d) ? b + c : c * (-Math.pow(2, -10 * t / d) + 1) + b; break; case 'easeInOutExpo': if (t == 0) return b; if (t == d) return b + c; if ((t /= d / 2) < 1) return c / 2 * Math.pow(2, 10 * (t - 1)) + b; return c / 2 * (-Math.pow(2, -10 * --t) + 2) + b; break; case 'easeInCirc': return -c * (Math.sqrt(1 - (t /= d) * t) - 1) + b; break; case 'easeOutCirc': return c * Math.sqrt(1 - (t = t / d - 1) * t) + b; break; case 'easeInOutCirc': if ((t /= d / 2) < 1) return -c / 2 * (Math.sqrt(1 - t * t) - 1) + b; return c / 2 * (Math.sqrt(1 - (t -= 2) * t) + 1) + b; break; case 'easeInElastic': var s = 1.70158; var p = 0; var a = c; if (t == 0) return b; if ((t /= d) == 1) return b + c; if (!p) p = d * .3; if (a < Math.abs(c)) { a = c; var s = p / 4; } else var s = p / (2 * Math.PI) * Math.asin(c / a); return -(a * Math.pow(2, 10 * (t -= 1)) * Math.sin((t * d - s) * (2 * Math.PI) / p)) + b; break; case 'easeOutElastic': var s = 1.70158; var p = 0; var a = c; if (t == 0) return b; if ((t /= d) == 1) return b + c; if (!p) p = d * .3; if (a < Math.abs(c)) { a = c; var s = p / 4; } else var s = p / (2 * Math.PI) * Math.asin(c / a); return a * Math.pow(2, -10 * t) * Math.sin((t * d - s) * (2 * Math.PI) / p) + c + b; break; case 'easeInOutElastic': var s = 1.70158; var p = 0; var a = c; if (t == 0) return b; if ((t /= d / 2) == 2) return b + c; if (!p) p = d * (.3 * 1.5); if (a < Math.abs(c)) { a = c; var s = p / 4; } else var s = p / (2 * Math.PI) * Math.asin(c / a); if (t < 1) return -.5 * (a * Math.pow(2, 10 * (t -= 1)) * Math.sin((t * d - s) * (2 * Math.PI) / p)) + b; return a * Math.pow(2, -10 * (t -= 1)) * Math.sin((t * d - s) * (2 * Math.PI) / p) * .5 + c + b; break; case 'easeInBack': if (s == undefined) s = 1.70158; return c * (t /= d) * t * ((s + 1) * t - s) + b; break; case 'easeOutBack': if (s == undefined) s = 1.70158; return c * ((t = t / d - 1) * t * ((s + 1) * t + s) + 1) + b; break; case 'easeInOutBack': if (s == undefined) s = 1.70158; if ((t /= d / 2) < 1) return c / 2 * (t * t * (((s *= (1.525)) + 1) * t - s)) + b; return c / 2 * ((t -= 2) * t * (((s *= (1.525)) + 1) * t + s) + 2) + b; break; case 'easeInBounce': return c - this.bezier({name: 'easeOutBounce', x: x, t: (d - t), b: 0, c: c, d: d}) + b; break; case 'easeOutBounce': if ((t /= d) < (1 / 2.75)) { return c * (7.5625 * t * t) + b; } else if (t < (2 / 2.75)) { return c * (7.5625 * (t -= (1.5 / 2.75)) * t + .75) + b; } else if (t < (2.5 / 2.75)) { return c * (7.5625 * (t -= (2.25 / 2.75)) * t + .9375) + b; } else { return c * (7.5625 * (t -= (2.625 / 2.75)) * t + .984375) + b; } break; case 'easeInOutBounce': if (t < d / 2) return this.bezier({name: 'easeOutBounce', x: x, t: (t * 2), b: 0, c: c, d: d}) * .5 + b; return this.bezier({name: 'easeOutBounce', x: x, t: (t * 2 - d), b: 0, c: c, d: d}) * .5 + c * .5 + b; break; default: result = t; } } return result; } V.prototype.bezierCurve = function([x1, y1, x2, y2], t){ if (x1 === y1 && x2 === y2) { return t; } let val = []; for(let i = 0; i < 11; ++i){ val[i] = this.bezierCalc(i * .1, x1, x2); } if(t === 0){ return 0; } if(t === 1){ return 1; } return this.bezierCalc(this.bezierCurveGetX([x1, y1, x2, y2], t, val), y1, y2); }; V.prototype.bezierCurveGetX = function([x1, y1, x2, y2], t, val){ let start = 0, current = 1; for (; current !== 10 && val[current] <= t; ++current) { start += .1; } --current; let dist = (t - val[current]) / (val[current + 1] - val[current]), guessForT = start + dist * .1; let initialSlope = this.bezierCurveGetSlope(guessForT, x1, x2); if(initialSlope >= 0.001){ return this.bezierCurveNewtonRaphsonIterate(t, guessForT, x1, x2); } else if(initialSlope === 0.0){ return guessForT; } else{ return this.bezierCurveBinarySubdivide(t, start, start + .1, x1, x2); } } V.prototype.bezierCurveGetSlope = function(t, x1, x2){ return 3.0 * this.bezierCalcA(x1, x2) * t * t + 2.0 * this.bezierCalcB(x1, x2) * t + this.bezierCalcC(x1); } V.prototype.bezierCurveNewtonRaphsonIterate = function(t, guessForT, x1, x2){ for(let i = 0; i < 4; ++i){ let currentSlope = this.bezierCurveGetSlope(guessForT, x1, x2); if(currentSlope === 0.0){ return guessForT; } let currentX = this.bezierCalc(guessForT, x1, x2) - t; guessForT -= currentX / currentSlope; } return guessForT; } V.prototype.bezierCurveBinarySubdivide = function(t, a, b, x1, x2){ var currentX, currentT, i = 0; do{ currentT = a + (b - a) / 2.0; currentX = this.bezierCalc(currentT, x1, x2) - t; if(currentX > 0.0){ b = currentT; } else{ a = currentT; } } while(Math.abs(currentX) > 0.0000001 && ++i < 10); return currentT; } V.prototype.bezierCalc = function(t, x1, x2){ return ((this.bezierCalcA(x1, x2) * t + this.bezierCalcB(x1, x2)) * t + this.bezierCalcC(x1)) * t; } V.prototype.bezierCalcA = function(x1, x2){ return 1.0 - 3.0 * x2 + 3.0 * x1; } V.prototype.bezierCalcB = function(x1, x2){ return 3.0 * x2 - 6.0 * x1; } V.prototype.bezierCalcC = function(x1){ return 3.0 * x1; }; V.prototype.depthPercent = function({ scope = [0, 1], t = .5 } = { scope: [0, 1], t: .5 }){ if(!this.checkType('numberArray', scope, {count: 2})){ return false; } if(typeof t !== 'number'){ return false; } let result = (t - scope[0]) / (scope[1] - scope[0]); return result; }; V.prototype.randInt = function(min = 0, max = 100){ if(!Number.isInteger(min)){ return false; } if(!Number.isInteger(max)){ return false; } min = Math.ceil(min); max = Math.ceil(max); if(min < 0 || max > 10000000000) return 0; let rand = min + Math.random() * (max - min); rand = Math.round(rand); return rand; }; V.prototype.radians = function(val){ return val * Math.PI / 180; }; V.prototype.degrees = function(val){ return val * 180 / Math.PI; };; V.prototype.imageSize = function({ img = null, size = 'cover', width = 100, height = 100, maxWidth = width, maxHeight = height } = { img: null, size: 'cover', width: 100, height: 100, maxWidth: width, maxHeight: height }){ if(img === null){ return false; } if(size !== 'cover' & size !== 'contain'){ return false; } if(typeof width !== 'number'){ return false; } if(typeof height !== 'number'){ return false; } if(typeof maxWidth !== 'number'){ return false; } if(typeof maxHeight !== 'number'){ return false; } let imageWidth = 0, imageHeight = 0, x = 0, y = 0, iWidth = 0, iHeight = 0; if(img.tagName == 'VIDEO'){ iWidth = img.videoWidth; iHeight = img.videoHeight; } else{ iWidth = img.width; iHeight = img.height; } if(size === 'cover'){ imageWidth = width; imageHeight = iHeight * imageWidth / iWidth; x = 0; y = (height - imageHeight) / 2; if(imageHeight < height){ imageHeight = height; imageWidth = iWidth * imageHeight / iHeight; x = (width - imageWidth) / 2; y = 0; } if(maxWidth !== width || maxHeight !== height){ x = (maxWidth - imageWidth) / 2; y = (maxHeight - imageHeight) / 2; } } else if(size === 'contain'){ if(iWidth > iHeight){ imageWidth = width; imageHeight = iHeight * imageWidth / iWidth; x = 0; y = (height - imageHeight) / 2; } else if(iHeight >= iWidth){ imageHeight = height; imageWidth = iWidth * imageHeight / iHeight; x = (width - imageWidth) / 2; y = 0; } } return { img: img, imageWidth: imageWidth, imageHeight: imageHeight, x: x, y: y, size: size } }; V.prototype.Keydown = class Keydown extends V.prototype.Event{ constructor(data = {}){ super(data); this.name = 'Keydown'; this.syncInterval = 250; this.targets = [ 'stack', 'once', 'sync' ]; } checkEvent(data = {}){ if(!super.checkEvent(data)){ return false; } // target if(!this.target(data.target)){ return false } // key if(data.key){ for(let i = 0; i < data.key.length; i++){ if(!Number.isInteger(data.key[i])){ return false; } } } else{ return false; } // timeout if(data.timeout){ if(!Number.isInteger(data.timeout)){ return false; } } return true; } implement(e){ for(let i = 0; i < this.events.length; i++){ if(this.events[i] === null){ continue; } if(this.events[i].on !== true){ continue; } if(this.events[i].data.target === 'once'){ if(e.keyCode === this.events[i].data.key[0]){ this.launchEvent(this.events[i], this.events[i].data.do.bind(e, this.events[i])); } } if(this.events[i].data.target === 'stack'){ if(typeof(this.events[i].string) == "undefined"){ this.events[i].string = ''; } this.events[i].string += '-' + e.keyCode; if(typeof(this.events[i].compareString) == "undefined"){ this.events[i].compareString = ''; for(let a = 0; a < this.events[i].data.key.length; a++){ this.events[i].compareString += '-' + this.events[i].data.key[a]; } } if(this.events[i].string.includes(this.events[i].compareString)){ this.launchEvent(this.events[i], this.events[i].data.do.bind(e, this.events[i])); this.events[i].string = ''; } } if(this.events[i].data.target === 'sync'){ if(typeof(this.events[i].array) == "undefined"){ this.events[i].array = []; } this.events[i].array.push(e.keyCode); setTimeout(function(element){ element.array = []; }.bind(this, this.events[i]), this.syncInterval); let overlaps = 0; for(let a = 0; a < this.events[i].data.key.length; a++){ for(let b = 0; b < this.events[i].array.length; b++){ if(this.events[i].data.key[a] === this.events[i].array[b]){ overlaps++; } } } if(this.events[i].data.key.length === overlaps){ this.launchEvent(this.events[i], this.events[i].data.do.bind(e, this.events[i])); this.events[i].array = []; } } } return true; } setEvent(){ this.document.addEventListener("keydown", function(e){ this.implement(e); }.bind(this)); return true; } };; V.prototype.DragSwipe = class DragSwipe extends V.prototype.Event{ constructor(data = {}){ super(data); this.name = 'DragSwipe'; this.targets = [ 'start', 'end', 'move', 'up', 'down', 'left', 'right' ]; this.targetsOnce = [ 'up', 'down', 'left', 'right' ]; this.x = null; this.y = null; this.xStart = null; this.yStart = null; this.startedBool = false; } checkEvent(data = {}){ if(!super.checkEvent(data)){ return false; } // target if(!this.target(data.target)){ return false; } // timeout if(data.timeout){ if(!Number.isInteger(data.timeout)){ return false; } } return true; } eventNeeded(e, event, target){ if(event === null){ return false; } // if event on if(event.on !== true){ return false; } // if event outer does not exist if(typeof(event.data.outer) == "undefined"){ event.data.outer = this.body; } // if event ignores outer let ignoreOuter = false; if(typeof event.data.ignoreOuter == "undefined"){ ignoreOuter = false; } else{ if(event.data.ignoreOuter){ ignoreOuter = true; } } if(!ignoreOuter){ if(this.childOf(e.target, event.data.outer) !== true){ return false; } } if(event.data.target != target){ return false; } return event; } eventImplement(type = '', target = '', e){ // change started bool if(target == 'start'){ this.startedBool = true; } // return if not started if(target != 'start' & !this.startedBool){ return; } // change started bool if end if(target == 'end'){ this.startedBool = false; } // change coordinates let global = { x: this.x, y: this.y }; if(target == 'start'){ this.x = e.pageX; this.y = e.pageY; this.xStart = e.pageX; this.yStart = e.pageY; if(type == 'swipe'){ this.x = e.targetTouches[0].pageX; this.y = e.targetTouches[0].pageY; this.xStart = e.targetTouches[0].pageX; this.yStart = e.targetTouches[0].pageY; } global.x = this.x; global.y = this.y; } // get coordinates else{ global.x = e.pageX; global.y = e.pageY; if(type == 'swipe'){ if(target != 'end' & !this.targetsOnce.includes(target)){ global.x = e.targetTouches[0].pageX; global.y = e.targetTouches[0].pageY; } else{ global.x = e.changedTouches[0].pageX; global.y = e.changedTouches[0].pageY; } } } // launch events for(let i = 0; i < this.events.length; i++){ // check if can implement let result = this.eventNeeded(e, this.events[i], target); if(result){ // change outer if needed this.events[i] = result; } else{ continue; } // get coords let outer = this.events[i].data.outer, bounding = {top: 0, left: 0}, inner = { x: 0, y: 0 }, diff = { x: 0, y: 0 }; // get inner coords inner.x = global.x; inner.y = global.y; if(outer != window & outer != this.doc & outer != this.body){ bounding = outer.getBoundingClientRect(); inner.x = global.x - bounding.left; inner.y = global.y - bounding.top; } // get difference coords diff.x = inner.x - (this.x - bounding.left); diff.y = inner.y - (this.y - bounding.top); // launch event this.launchEventCoords( this.events[i], global, inner, diff ); } // change global if(target != 'start'){ this.x = global.x; this.y = global.y; } } launchEventCoords(event, global, coords, diff){ // if once event if(this.targetsOnce.includes(event.data.target)){ return this.launchEventOnce(event, global, coords, diff); } // launch event this.launchEvent( event, event.data.do.bind( this, { global: global, inner: coords, diff: diff }, event ) ); } launchEventOnce(event, global, coords, diff){ // bool let allow = false; // up if(event.data.target == 'up'){ if(global.y < this.yStart) { if(Math.abs(this.yStart - global.y) > Math.abs(event.data.k)){ allow = true; } } } // down if(event.data.target == 'down'){ if(global.y > this.yStart) { if(Math.abs(this.yStart - global.y) > Math.abs(event.data.k)){ allow = true; } } } // left if(event.data.target == 'left'){ if(global.x < this.xStart) { if(Math.abs(this.xStart - global.x) > Math.abs(event.data.k)){ allow = true; } } } // right if(event.data.target == 'right'){ if(global.x > this.xStart) { if(Math.abs(this.xStart - global.x) > Math.abs(event.data.k)){ allow = true; } } } // launch event if(allow){ this.launchEvent( event, event.data.do.bind(this, event) ); } } };; V.prototype.Swipe = class Swipe extends V.prototype.DragSwipe{ constructor(data = {}){ super(data); this.name = 'Swipe'; } setEvent(){ this.body.addEventListener("touchstart", this.eventImplement.bind(this, 'swipe', 'start')); this.body.addEventListener("touchmove", this.eventImplement.bind(this, 'swipe', 'move')); this.document.addEventListener("touchend", (e) => { this.eventImplement('swipe', 'up', e); this.eventImplement('swipe', 'down', e); this.eventImplement('swipe', 'left', e); this.eventImplement('swipe', 'right', e); this.eventImplement('swipe', 'end', e); }); return true; } };; V.prototype.Drag = class Drag extends V.prototype.DragSwipe{ constructor(data = {}){ super(data); this.name = 'Drag'; } setEvent(){ this.document.addEventListener("mousedown", this.eventImplement.bind(this, 'drag', 'start')); this.document.addEventListener("mousemove", this.eventImplement.bind(this, 'drag', 'move')); this.document.addEventListener("mouseup", (e) => { this.eventImplement('drag', 'up', e); this.eventImplement('drag', 'down', e); this.eventImplement('drag', 'left', e); this.eventImplement('drag', 'right', e); this.eventImplement('drag', 'end', e); }); return true; } };; V.prototype.Wheel = class Wheel extends V.prototype.Event{ constructor(data = {}){ super(data); this.name = 'Wheel'; this.targets = [ 'up', 'down', 'left', 'right' ]; this.timeInterval = 200; } checkEvent(data = {}){ if(!super.checkEvent(data)){ return false; } // target if(!this.target(data.target)){ return false; } // k if(data.k){ if(!this.checkType("number", data.k)){ return false; } } else{ return false; } // timeout if(data.timeout){ if(!Number.isInteger(data.timeout)){ return false; } } // outer if(!this.checkType("htmlElement", data.outer)){ return false; } return true; } add(data = {}, bool = true, console = this.prop.console){ data.time = new Date().getTime(); let id = super.add(data, bool, console); if(id !== false){ return this.setEventListener(id); } return id; } implement(id = '', e){ let event = this.getEvent(id); if(!event){ return; } if(event === null){ return; } if(event.on !== true){ return; } let time = new Date().getTime(); if(time - event.data.time < this.timeInterval){ //event.data.time = time; return; } else{ event.data.time = time; } // delta let wheelData = this.normalizeWheel(e), deltaY = wheelData.spinY, deltaX = wheelData.spinX; // up if(event.data.target === 'up'){ if(deltaY < 0 & deltaY < event.data.k * -1){ this.launchEvent(event, event.data.do.bind(e, event)); } } // down if(event.data.target === 'down'){ if(deltaY > 0 & deltaY > event.data.k){ this.launchEvent(event, event.data.do.bind(e, event)); } } // left if(event.data.target === 'left'){ if(deltaX < 0 & deltaX < event.data.k * -1){ this.launchEvent(event, event.data.do.bind(e, event)); } } // right if(event.data.target === 'right'){ if(deltaX > 0 & deltaX > event.data.k){ this.launchEvent(event, event.data.do.bind(e, event)); } } return true; } setEventListener(id = ''){ let event = this.getEvent(id); if(!event){ return false; } // add eventListener event.data.outer.addEventListener("wheel", this.implement.bind(this, id)); return event.id; } };; V.prototype.Interval = class Interval extends V.prototype.Event{ constructor(data = {}){ super(data); this.name = 'Interval'; } checkEvent(data = {}){ if(!super.checkEvent(data)){ return false; } // target if(!this.target(data.target)){ return false; } // time if(data.time){ if(!Number.isInteger(data.time)){ return false; } } else{ return false; } return true; } addCallback(id = ''){ let obj = this.getEvent(id); if(!obj){ return false; } obj.onUniversal = obj.on; obj.intervalFunc = false; if(obj.on){ this.on(id); } window.addEventListener("focus", this.on.bind(this, id, 'window')); window.addEventListener("blur", this.off.bind(this, id, 'window')); return true; } turnCallback(id = ''){ let obj = this.getEvent(id); if(!obj){ return false; } if(obj.on){ this.on(id); } else{ this.off(id); } return true; } deleteCallback(id = ''){ let obj = this.getEvent(id); if(!obj){ return false; } if(obj.intervalFunc !== false){ clearInterval(obj.intervalFunc); } obj.intervalFunc = false; obj.on = false; obj.onUniversal = false; return true; } on(id = '', e = null){ let obj = this.getEvent(id); if(!obj){ return false; } this.off(id, e); let further = false; if(e === 'window'){ if(obj.onUniversal){ further = true; } } else{ further = true; } if(further){ obj.intervalFunc = setInterval(obj.data.do.bind(this, obj), obj.data.time); obj.on = true; obj.onUniversal = true; } return true; } off(id = '', e = null){ let obj = this.getEvent(id); if(!obj){ return false; } if(obj.intervalFunc !== false){ clearInterval(obj.intervalFunc); } obj.intervalFunc = false; obj.on = false; if(e !== 'window'){ obj.onUniversal = false; } return true; } };; V.prototype.normalizeWheel_PIXEL_STEP = 10; V.prototype.normalizeWheel_LINE_HEIGHT = 40; V.prototype.normalizeWheel_PAGE_HEIGHT = 800; V.prototype.normalizeWheel = function(event){ let sX = 0, sY = 0, pX = 0, pY = 0; if('detail' in event){ sY = event.detail; } if('wheelDelta' in event){ sY = -event.wheelDelta / 120; } if('wheelDeltaY' in event){ sY = -event.wheelDeltaY / 120; } if('wheelDeltaX' in event){ sX = -event.wheelDeltaX / 120; } if('axis' in event && event.axis === event.HORIZONTAL_AXIS){ sX = sY; sY = 0; } pX = sX * this.normalizeWheel_PIXEL_STEP; pY = sY * this.normalizeWheel_PIXEL_STEP; if('deltaY' in event){ pY = event.deltaY; } if('deltaX' in event){ pX = event.deltaX; } if((pX || pY) && event.deltaMode){ if(event.deltaMode == 1){ pX *= this.normalizeWheel_LINE_HEIGHT; pY *= this.normalizeWheel_LINE_HEIGHT; } else{ pX *= this.normalizeWheel_PAGE_HEIGHT; pY *= this.normalizeWheel_PAGE_HEIGHT; } } if(pX && !sX){ sX = (pX < 1) ? -1 : 1; } if(pY && !sY){ sY = (pY < 1) ? -1 : 1; } return { spinX: sX, spinY: sY, pixelX: pX, pixelY: pY }; }; V.prototype.Class = class Class extends V.prototype.Event{ constructor(data = {}){ super(); this.name = this.constructor.name; this.prop = Object.assign(this.prop, { v: window.v, console: typeof window.v != "undefined" ? window.v.prop().console : true, eventsStorage: false }); for(let value in data){ this.prop[value] = data[value]; } this.eventsStorage = this; this.eventsStorageCustom = false; if(this.checkType("object", this.prop.eventsStorage)){ if( this.prop.eventsStorage.hasOwnProperty('addEventListener') & this.prop.eventsStorage.hasOwnProperty('removeEventListeners') & this.prop.eventsStorage.hasOwnProperty('getEventListeners') ){ this.eventsStorage = this.prop.eventsStorage; this.eventsStorageCustom = true; } } } check(){ return true; } checkEvent(data = {}){ // timeout if(data.timeout){ if(!Number.isInteger(data.timeout)){ return false; } } // do if(!this.do(data.do)){ return false; } return true; } changeProp(data = {}){ for(let value in data){ this.prop[value] = data[value]; } return this.check(); } removeEventListeners(){ if(this.eventsStorageCustom){ return this.eventsStorage.removeEventListeners(); } if(!this.checkType('array', this.eventListeners)){ this.eventListeners = []; } for(let i = 0; i < this.eventListeners.length; i++){ this.unbindEventListener(this.eventListeners[i]); } this.eventListeners = []; return true; } addEventListener(obj = {}){ if(this.eventsStorageCustom){ return this.eventsStorage.addEventListener(obj); } let result = this.bindEventListener(obj); if(!result){ return false; } this.eventListeners.push(result); return true; } getEventListeners(){ if(this.eventsStorageCustom){ return this.eventsStorage.getEventListeners(); } return this.eventListeners; } init(){ this.eventListeners = []; if(!this.check()){ return false; } this.console(`${this.name}. Using ${this.name} for`, this.prop, 'info', this.prop.console); return { removeEventListeners: this.eventsStorage.removeEventListeners.bind(this), addEventListener: this.eventsStorage.addEventListener.bind(this), getEventListeners: this.eventsStorage.getEventListeners.bind(this), add: this.add.bind(this), delete: this.delete.bind(this), turn: this.turn.bind(this), events: () => this.events, prop: () => this.prop, changeProp: this.changeProp.bind(this), targets: () => this.targets, launchEventsByTarget: this.launchEventsByTarget.bind(this) }; } }; V.prototype.Preloader = class Preloader extends V.prototype.Class{ constructor(data = {}){ super(data); this.prefix = `${this.prefix}preloader`; this.dataPrefix = `data-${this.prefix}`; this.prop = Object.assign(this.prop, { selector: `#${this.prefix}`, animation: 750, animationInner: 25, progress: { on: false, animate: false, k: .01, forceEnd: false, duration: 3000, bezier: { on: false, name: 'linear' } }, hide: true }); for(let value in data){ this.prop[value] = data[value]; } this.targets = [ 'progress', 'progressAnimate', 'hide', 'hidden' ]; } check(){ let checked = this.checkTypes({ obj: this.prop, name: this.name, console: this.prop.console, vars: [ ['selector', 'dom'], ['animation', 'integer'], ['animationInner', 'integer'], ['progress', 'object'], ['hide', 'boolean'] ] }); if(!checked){ return false; } checked = this.checkTypes({ obj: this.prop.progress, name: this.name, console: this.prop.console, vars: [ ['on', 'boolean'], ['animate', 'boolean'], ['k', 'number'], ['forceEnd', 'boolean'], ['duration', 'number'], ['bezier', 'bezier'], ] }); if(!checked){ return false; } this.outer = this.prop.v.document().querySelector(this.prop.selector); this.outer.classList.add(`${this.prefix}`); return true; } checkEvent(data = {}){ if(typeof data.target == 'undefined'){ data.target = 'hidden'; } return super.checkEvent(data); } setStyles(){ this.outer.style.opacity = '1'; this.outer.style.transition = (this.prop.animation / 1000) + 's'; return true; } start(){ // set animation inner this.prop.animationInner = this.prop.animationInner + this.prop.v.timeMin(); // add animate class setTimeout(() => { this.outer.classList.add(`${this.prefix}_animate`); }, this.prop.v.timeMin()); // set events this.setEvents(); return true; } setEvents(){ this.prop.v.addLoad(() => { this.loaded = true; this.onloaded(); }); if(this.prop.progress.on){ this.getImages(); this.getVideos(); this.resourcesTotal = this.images.length + this.videos.length; this.resourcesLoad(); if(this.prop.progress.animate){ this.progressFrameSet(); } } } getImages(){ let el = this.prop.v.document().querySelectorAll('*:not(script)'); for(let i = 0; i < el.length; i++){ let url = getComputedStyle(el[i]).backgroundImage; if(url.indexOf('none') == -1 & url.indexOf('-gradient') == -1){ if (url.indexOf('url') != -1) { let temp = url.match(/url\((.*?)\)/); url = temp[1].replace(/\"/g, ''); this.images.push(url); } } else{ if(el[i].tagName == "IMG"){ this.images.push(el[i].src); } } } } getVideos(){ let el = this.prop.v.document().querySelectorAll('video'); for(let i = 0; i < el.length; i++){ this.videos.push(el[i]); } } resourcesLoad(){ // load images for(let i = 0; i < this.images.length; i++){ let image = new Image(); image.onload = () => { this.resourceOnloaded(); }; image.onerror = () => { this.resourceOnloaded(); }; image.src = this.images[i]; } // load videos for(let i = 0; i < this.videos.length; i++){ this.videos[i].load(); this.videos[i].onloadeddata = () => { this.resourceOnloaded(); } } } resourceOnloaded(){ this.resourcesLoaded++; this.currentProgress = this.resourcesLoaded / this.resourcesTotal; this.launchEventsByTarget('progress', { progress: this.currentProgress, loaded: this.resourcesLoaded, total: this.resourcesTotal }); } addResourcesTotal(num = 1){ this.resourcesTotal += num; } addResourcesLoaded(num = 1){ for(let i = 0; i < num; i++){ this.resourceOnloaded(); } } progressFrameSet(){ this.progressFrameId = window.requestAnimationFrame(this.progressFrame.bind(this)); } progressFrame(){ this.animationProgress += (this.currentProgress - this.animationProgress) * this.prop.progress.k; if(this.animationProgress >= .99){ this.animationProgress = 1; this.onloaded(); cancelAnimationFrame(this.progressFrameId); this.launchEventsByTarget('progressAnimate', { progress: this.animationProgress, loaded: this.resourcesLoaded, total: this.resourcesTotal }); return; } this.launchEventsByTarget('progressAnimate', { progress: this.animationProgress, loaded: this.resourcesLoaded, total: this.resourcesTotal }); this.progressFrameId = window.requestAnimationFrame(this.progressFrame.bind(this)); } progressFrameForce(p, b){ let diff = 1 - this.animationProgress, result = b * diff; if(result == diff){ this.animationProgress = 1; this.onloaded(); this.launchEventsByTarget('progressAnimate', { progress: this.animationProgress, loaded: this.resourcesLoaded, total: this.resourcesTotal }); return; } this.launchEventsByTarget('progressAnimate', { progress: this.animationProgress + result, loaded: this.resourcesLoaded, total: this.resourcesTotal }); } onloaded(){ // return if page not loaded if(!this.loaded){ return; } // if progress is enabled if(this.prop.progress.on){ if(this.resourcesTotal < this.resourcesLoaded){ return; } if(this.prop.progress.animate){ if(this.animationProgress < 1){ if(this.prop.progress.forceEnd){ if(this.forceEndAnimate == null){ cancelAnimationFrame(this.progressFrameId); this.forceEndAnimate = new this.Animate({ console: this.prop.console, duration: this.prop.progress.duration, bezier: this.prop.progress.bezier, do: this.progressFrameForce.bind(this) }); this.forceEndAnimate = this.forceEndAnimate.init(); this.forceEndAnimate.run(); return; } } else{ return; } } } } this.launchEventsByTarget('hide'); if(this.prop.hide){ this.hide(); } } hide(){ let interval = this.getInterval(); if(interval === 0){ this.hideAnimate(); } else{ setTimeout(this.hideAnimate.bind(this), interval); } } getInterval(){ let timeEnd = +new Date(), difference = timeEnd - this.startTime; let interval = 0; if(difference < this.prop.animationInner){ interval = this.prop.animationInner - difference; } return interval; } hideAnimate(){ this.outer.style.opacity = '0'; this.outer.classList.add(`${this.prefix}_animated`); setTimeout( function(){ this.outer.classList.add(`${this.prefix}_hidden`); this.onhidden(); }.bind(this), this.prop.animation ); } onhidden(){ this.hidden = true; this.launchEventsByTarget('hidden'); this.console(`${this.name}. Hide`, null, 'info', this.prop.console); } init(){ // init let initObj = super.init(); if(!initObj){ return false; } // vars this.startTime = +new Date(); this.hidden = false; this.loaded = false; this.images = []; this.videos = []; this.resourcesTotal = 0; this.resourcesLoaded = 0; this.currentProgress = 0; this.animationProgress = 0; this.progressFrameId = null; this.forceEndAnimate = null; // initialize this.setStyles(); this.start(); // return obj return Object.assign(initObj, { hidden: () => this.hidden, loaded: () => this.loaded, resourcesTotal: () => this.resourcesTotal, resourcesLoaded: () => this.resourcesLoaded, animationProgress: () => this.animationProgress, hide: this.hide.bind(this), addResourcesTotal: this.addResourcesTotal.bind(this), addResourcesLoaded: this.addResourcesLoaded.bind(this) }); } }; V.prototype.Scrollbar = class Scrollbar extends V.prototype.Class{ constructor(data = {}){ super(data); this.prefix = `${this.prefix}scrollbar`; this.prop = Object.assign(this.prop, { selector: `#${this.prefix}`, init: true }); for(let value in data){ this.prop[value] = data[value]; } } check(){ let checked = this.checkTypes({ obj: this.prop, name: this.name, console: this.prop.console, vars: [ ['selector', 'dom'], ['init', 'boolean'] ] }); if(!checked){ return false; } this.outer = this.prop.v.document().querySelector(this.prop.selector); return true; } destroy(){ jQuery(this.outer).scrollbar("destroy"); this.outer.classList.remove("scrollbar-macosx"); return true; } create(){ this.outer.classList.add("scrollbar-macosx"); jQuery(this.outer).scrollbar(); return true; } init(){ if(!super.init()){ return false; } this.outer.classList.add(`${this.prefix}`); if(this.prop.init){ this.create(); } return { create: this.create.bind(this), destroy: this.destroy.bind(this), prop: () => this.prop, changeProp: this.changeProp.bind(this) }; } }; V.prototype.Animate = class Animate extends V.prototype.Class{ constructor(data = {}){ super(data); this.prop = Object.assign(this.prop, { duration: 250, scope: [0, 1], durationAuto: false, delay: 0, bezier: { on: false, values: [1, 1, 1, 1] }, do: function(progress, bezier){} }); for (let value in data) { this.prop[value] = data[value]; } } check(){ let checked = this.checkTypes({ obj: this.prop, name: this.name, console: this.prop.console, vars: [ ['duration', 'number'], ['scope', 'numberArray', {count: 2}], ['durationAuto', 'boolean'], ['delay', 'number'], ['bezier', 'bezier'], ['do', 'function'] ] }); if(!checked){ return false; } // check twice this.prop.duration = parseInt(this.prop.duration); this.prop.delay = parseInt(this.prop.delay); checked = this.checkTypes({ obj: this.prop, name: this.name, console: this.prop.console, vars: [ ['duration', 'integer'], ['delay', 'integer'] ] }); if(!checked){ return false; } return true; } animate(){ this.animating = true; let scope = [this.prop.scope[0], this.prop.scope[1]]; // continuing scope if(this.continued){ scope[0] = this.stopValue; if(this.reversed){ scope[1] = this.stopValue; scope[0] = this.prop.scope[0]; } } // calc duration let duration = this.prop.duration; if(this.prop.durationAuto){ duration = (scope[1] - scope[0]) * this.prop.duration; } // calc progress let scopeDifference = scope[1] - scope[0], progress = (Date.now() - this.time) / duration, progressOutput = progress * scopeDifference + scope[0]; // if animation ends if(progress >= 1){ progress = 1; progressOutput = scope[1]; this.animating = false; } let progressBezier = progressOutput; // if animation is stopped if(progress !== 1){ if(this.stopped){ this.stopValue = progressOutput; this.animating = false; } } // values + reversed if(this.reversed){ progressOutput = (scope[1] - scope[0]) * (1 - progress) + scope[0]; if(progress >= 1){ progressOutput = this.prop.scope[0]; this.reversed = false; } } progressBezier = progressOutput; // calc bezier if(this.prop.bezier.on){ let newBezier = {}; for(let value in this.prop.bezier){ newBezier[value] = this.prop.bezier[value]; } newBezier.t = progressOutput; newBezier.b = scope[0]; newBezier.c = scope[1]; newBezier.d = scope[1]; progressBezier = this.bezier(newBezier); } // if animation is stopped if(progress !== 1){ if(this.stopped){ this.stopValue = progressOutput; this.animating = false; } } // do this.prop.do(progressOutput, progressBezier); // continue animation if(!this.stopped){ if(progress < 1){ window.requestAnimationFrame(this.animate.bind(this)); } } } imitate(progressOutput = 0, progressBezier = progressOutput){ this.prop.do(progressOutput, progressBezier); } run(){ if(this.animating){ return false; } if(this.stopped){ this.continued = true; this.stopped = false; this.time = Date.now(); window.requestAnimationFrame(this.animate.bind(this)); } else{ this.continued = false; if(this.prop.delay === 0){ this.time = Date.now(); window.requestAnimationFrame(this.animate.bind(this)); } else{ setTimeout(function(){ this.time = Date.now(); window.requestAnimationFrame(this.animate.bind(this)); }.bind(this), this.prop.delay); } } return true; } reverse(){ if(this.animating){ return false; } this.reversed = true; return this.run(); } stop(){ if(!this.animating){ return false; } this.stopped = true; return true; } init(){ if(!super.init()){ return false; } this.continued = false; this.stopValue = 0; this.stopped = false; this.animating = false; this.reversed = false; this.time = Date.now(); return { run: this.run.bind(this), reverse: this.reverse.bind(this), stop: this.stop.bind(this), imitate: this.imitate.bind(this), prop: () => this.prop, changeProp: this.changeProp.bind(this) }; } }; V.prototype.AnimationFrame = class AnimationFrame extends V.prototype.Class{ constructor(data = {}){ super(data); this.prefix = `${this.prefix}animationFrame`; this.prop = Object.assign(this.prop, { fps: 60, run: true }); for(let value in data){ this.prop[value] = data[value]; } } /* Check */ check(){ let checked = this.checkTypes({ obj: this.prop, name: this.name, console: this.prop.console, vars: [ ['fps', 'integer'], ['run', 'boolean'] ] }); if(!checked){ return false; } return true; } /* Change Properties */ changeProp(data){ let runPrev = this.prop.run; if(!super.changeProp(data)){ return false; } if(this.prop.run !== runPrev){ this.run(); } return true; } /* Animate */ run(timestamp = 0){ // return if not to run if(!this.prop.run){ return; } // request animation frame window.requestAnimationFrame(this.run.bind(this)); // animate - launch all events this.animate(timestamp); } animate(timestamp){ if(this.time == null){ this.time = timestamp; } let seg = Math.floor((timestamp - this.time) / (1000 / this.prop.fps)); if(seg > this.frame){ this.frame = seg; this.launchEvents(); } } /* Init */ init(){ let initObj = super.init(); if(!initObj){ return false; } // vars this.time = null; this.frame = -1; // start animation this.run(); // return return initObj; } }; V.prototype.TextAnimate = class TextAnimate extends V.prototype.Class{ constructor(data = {}){ super(data); this.prefix = `${this.prefix}text`; this.prop = Object.assign(this.prop, { selector: `#${this.prefix}`, resize: true }); for(let value in data){ this.prop[value] = data[value]; } this.types = [ 'letter', 'word', 'string', 'stringletter', 'stringword' ]; } check(){ let checked = this.checkTypes({ obj: this.prop, name: this.name, console: this.prop.console, vars: [ ['selector', 'dom'], ['resize', 'boolean'] ] }); if(!checked){ return false; } this.outer = this.prop.v.document().querySelector(this.prop.selector); return true; } changeProp(data){ if(!super.changeProp(data)){ return false; } this.setEvents(); return true; } split(){ // don't change the text if(!this.splitted){ this.text = this.outer.innerText; this.splitLetters(); this.splitLettersSpan(); this.splitWords(); this.splitWordsSpan(); this.splitted = true; } this.splitStrings(); return true; } splitLetters(){ for(let i = 0; i < this.text.length; i++){ this.letters.push(this.text[i]); } return true; } splitLettersSpan(){ for(let i = 0; i < this.letters.length; i++){ let spanInfo = { element: null, spaces: false, clear: false, content: '' }; let span = document.createElement("span"); span.classList.add(`${this.prefix}__letter`); span.classList.add(`${this.prefix}__letter_${i}`); if(this.letters[i].charCodeAt(0) === 32 || this.letters[i].charCodeAt(0) === 160){ span.innerHTML = ' '; spanInfo.spaces = true; } else if(this.letters[i].charCodeAt(0) === 10){ span = document.createElement("div"); span.classList.add("clear"); span.classList.add(`${this.prefix}__space`); span.classList.add(`${this.prefix}__space_${i}`); span.innerHTML = ''; spanInfo.clear = true; } else{ span.innerHTML = this.letters[i]; span.classList.add(`${this.prefix}__letter_code-${this.letters[i].charCodeAt().toString(16)}`); } spanInfo.element = span; spanInfo.content = span.innerHTML; this.elements.letters.push(spanInfo); } this.outer.innerHTML = ''; for(let i = 0; i < this.elements.letters.length; i++){ this.outer.appendChild(this.elements.letters[i].element); } return true; } splitWords(){ let prevWord = -1, word; for(let i = 0, a = 0; i < this.elements.letters.length; i++){ if(this.elements.letters[i].clear){ a += 1; } if(prevWord !== a){ word = { element: null, spaces: false, clear: this.elements.letters[i].clear, letters: [], content: '' }; this.elements.words.push(word); } word.letters.push(this.elements.letters[i]); prevWord = a; if(this.elements.letters[i].spaces || this.elements.letters[i].clear){ a++; } } for(let i = 0; i < this.elements.words.length; i++){ let spacesNumber = 0; for(let a = 0; a < this.elements.words[i].letters.length; a++){ if(this.elements.words[i].letters[a].spaces){ spacesNumber++; } this.elements.words[i].content += this.elements.words[i].letters[a].content; } if(spacesNumber === this.elements.words[i].letters.length){ this.elements.words[i].spaces = true; } } return true; } splitWordsSpan(){ for(let i = 0; i < this.elements.words.length; i++){ let span = document.createElement("span"); span.classList.add(`${this.prefix}__word`); span.classList.add(`${this.prefix}__word_${i}`); if(this.elements.words[i].clear){ span = document.createElement("div"); span.classList.add("clear"); span.classList.add(`${this.prefix}__clear`); span.classList.add(`${this.prefix}__clear_${i}`); } this.outer.appendChild(span); this.elements.words[i].element = span; } for(let i = 0; i < this.elements.words.length; i++){ for(let a = 0; a < this.elements.words[i].letters.length; a++){ this.elements.words[i].element.appendChild(this.elements.words[i].letters[a].element); } } let wordsWithoutClear = []; for(let i = 0; i < this.elements.words.length; i++){ if(!this.elements.words[i].clear){ wordsWithoutClear.push(this.elements.words[i]); } } this.elements.words = wordsWithoutClear; return true; } splitStrings(){ let prevBounding = null, prevString = -1, string; this.elements.strings = []; for(let i = 0, a = -1; i < this.elements.words.length; i++){ let wordBounding = this.elements.words[i].element.getBoundingClientRect().top; if(wordBounding !== prevBounding){ a++; } if(prevString !== a){ string = { spaces: false, clear: false, words: [], content: '' }; this.elements.strings.push(string); } string.words.push(this.elements.words[i]); prevString = a; prevBounding = this.elements.words[i].element.getBoundingClientRect().top; } for(let i = 0; i < this.elements.strings.length; i++){ let spacesNumber = 0; for(let a = 0; a < this.elements.strings[i].words.length; a++){ if(this.elements.strings[i].words[a].spaces){ spacesNumber++; } this.elements.strings[i].content += this.elements.strings[i].words[a].content; } if(spacesNumber === this.elements.strings[i].words.length){ this.elements.strings[i].spaces = true; } } return true; } setEvents(){ if(this.prop.resize){ if(this.resizeId == null){ this.resizeId = this.prop.v.viewport.add({ target: 'wh', name: `${this.name} Resize`, do: this.eventResize.bind(this), timeout: this.prop.v.timeMin() }); } } else{ if(this.resizeId !== null){ this.prop.v.viewport.delete(this.resizeId); this.resizeId = null; } } return true; } eventResize(){ if(!this.splitted){ return false; } this.splitStrings(); return true; } checkVars(data){ let vars = { types: ['letter'], delay: 0, duration: 250, bezier: { on: false, name: 'linear' }, letter: [], word: [], string: [], strings: [], shift: .2, shiftString: .2, ignoreSpaces: true, reverse: false, callbacks: [] }; for(let value in data) { vars[value] = data[value]; } // check let checked = this.checkTypes({ obj: vars, name: this.name, console: this.prop.console, vars: [ ['types', 'stringArray', {count: 1}], ['delay', 'integer'], ['duration', 'integer'], ['bezier', 'bezier'], ['shift', 'number'], ['shiftString', 'number'], ['ignoreSpaces', 'boolean'], ['reverse', 'boolean'], ['strings', 'array'], ['callbacks', 'callbacks'], ['letter', 'styleCallbacks'], ['word', 'styleCallbacks'], ['string', 'styleCallbacks'] ] }); if(!checked){ return false; } return vars; } animate(data){ if(this.animating){ return false; } if(!this.checkVars(data)){ return false; } data = this.checkVars(data); for(let i = 0; i < data.types.length; i++){ let currentType = data.types[i], typeDefined = currentType; if(currentType === 'letter' || currentType === 'word'){ typeDefined = 'elementary' } if(currentType === 'stringletter' || currentType === 'stringword'){ typeDefined = 'string_elementary' } if(currentType === 'string'){ typeDefined = 'string'; } if(typeof(this[`animate_${typeDefined}`]) != "undefined"){ this.animating = true; setTimeout(this[`animate_${typeDefined}`].bind(this, data, currentType), data.delay); } } return true; } calcTime(data){ let intervals = [], lastDelay = 0; let elementDelay = 0; for(let i = 0, a = 0; i < data.elements.length; i++){ if(data.ignoreSpaces === true){ if(data.elements[i].spaces !== true){ elementDelay = a * data.duration * data.shift; a++; } } else{ elementDelay = a * data.duration * shift; a++; } intervals.push({ time: elementDelay, percent: 0 }); lastDelay = elementDelay; } let durationFull = lastDelay + data.duration; durationFull = parseInt(durationFull); for(let i = 0; i < intervals.length; i++){ intervals[i].percent = intervals[i].time / durationFull; intervals[i].percentEnd = (intervals[i].time + data.duration) / durationFull; } return { intervals: intervals, duration: data.duration, durationFull: durationFull, elements: data.elements, shift: data.shift }; } splitAnimate(data){ let callbacksArray = []; for(let i = 0; i < data.callbacks.length; i++){ callbacksArray.push({ target: data.callbacks[i].target, do: data.callbacks[i].do, proceeded: false }); } let animate = new this.Animate({ console: this.prop.console, duration: data.animationInfo.durationFull, do: function(data, callbackDo, callbacksArray, progress, bezier){ // split intervals for(let i = 0; i < data.intervals.length; i++){ // get current percent let current; if(progress < data.intervals[i].percent){ current = 0; } else if(progress >= data.intervals[i].percent & progress <= data.intervals[i].percentEnd){ current = this.depthPercent({ scope: [data.intervals[i].percent, data.intervals[i].percentEnd], t: progress }); } else{ current = 1; } callbackDo(data.elements[i], current); } // stop animating if(progress === 1){ this.animating = false; } // launch callbacks for(let i = 0; i < callbacksArray.length; i++){ if(progress >= callbacksArray[i].target){ if(!callbacksArray[i].proceeded){ callbacksArray[i].do(progress); callbacksArray[i].proceeded = true; } } } }.bind(this, data.animationInfo, data.do, callbacksArray) }); animate = animate.init(); animate.run(); return true; } setStylesSimple(data){ for(let i = 0; i < data.properties.length; i++){ let scope = data.properties[i].scope, p = 0, b = 0; // get progress if(data.progress >= scope[0] & data.progress < scope[1]){ p = this.depthPercent({ scope: scope, t: data.progress }); } else if(data.progress >= scope[1]){ p = 1; } // get bezier if(data.bezier.on){ let newBezier = {}; for(let value in data.bezier){ newBezier[value] = data.bezier[value]; } newBezier.t = p; newBezier.b = 0; newBezier.c = 1; newBezier.d = 1; b = this.bezier(newBezier); } else{ b = p; } // set property let property = data.properties[i].property, value = data.properties[i].value(b); data.element.element.style[property] = value; } } setStyles(data){ let animate = new this.Animate({ console: this.prop.console, duration: data.animationData.duration, bezier: data.bezier, do: function(e, properties, progress, bezier){ for(let i = 0; i < properties.length; i++){ let scope = properties[i].scope, p = 0; if(bezier >= scope[0] & bezier < scope[1]){ p = this.depthPercent({ scope: scope, t: bezier }); } else if(bezier >= scope[1]){ p = 1; } let property = properties[i].property, value = properties[i].value(p); e.element.style[property] = value; } }.bind(this, data.element, data.properties) }); animate = animate.init(); animate.run(); return true; } init(){ if(!super.init()){ return false; } this.outer.classList.add(`${this.prefix}`); this.defaultHTML = this.outer.innerHTML; this.splitted = false; this.animating = false; this.text = ''; this.letters = []; this.elements = { letters: [], words: [], strings: [] } this.resizeId = null; this.split(); this.setEvents(); return { elements: () => this.elements, split: this.splitStrings.bind(this), animate: this.animate.bind(this), animating: () => this.animating, changeProp: this.changeProp.bind(this) }; } }; V.prototype.TextAnimate.prototype.animate_elementary = function(data, type){ let elements = []; if(type === 'word'){ elements = this.elements.words; } else{ elements = this.elements.letters; } let definedProperties = []; if(type === 'word'){ definedProperties = data.word; } else{ definedProperties = data.letter; } if(data.reverse){ elements = elements.slice(); elements.reverse(); } let animationInfo = this.calcTime({ elements: elements, duration: data.duration, shift: data.shift, ignoreSpaces: data.ignoreSpaces }); this.splitAnimate({ animationInfo: animationInfo, do: function(element, progress){ this.setStylesSimple({ bezier: data.bezier, element: element, progress: progress, properties: definedProperties }); }.bind(this), callbacks: data.callbacks }); return true; };; V.prototype.TextAnimate.prototype.animate_string = function(data, type){ let elements = this.elements.strings, definedProperties = data.string; if(data.reverse){ elements = elements.slice(); elements.reverse(); } let animationInfo = this.calcTime({ elements: elements, duration: data.duration, shift: data.shift, ignoreSpaces: data.ignoreSpaces }); this.splitAnimate({ animationInfo: animationInfo, do: function(element, progress){ for(let i = 0; i < element.words.length; i++){ this.setStylesSimple({ bezier: data.bezier, element: element.words[i], progress: progress, properties: definedProperties }); } }.bind(this), callbacks: data.callbacks }); return true; };; V.prototype.TextAnimate.prototype.animate_string_elementary = function(data, type){ this.animate_string_elementaryAnimate(data, type); return true; }; V.prototype.TextAnimate.prototype.animate_string_elementaryAnimate = function(data, type){ // get properties if(type === 'stringword'){ data.definedProperties = data.word; } else{ data.definedProperties = data.letter; } // get elements let elements = this.animate_string_elementaryGetElements(data, type), elementsLength = elements.length; // get durations of each string let stringsAnimationInfo = []; for(let i = 0; i < elementsLength; i++){ let animationInfo = this.calcTime({ elements: elements[i], duration: data.duration, shift: data.shift, ignoreSpaces: data.ignoreSpaces }); stringsAnimationInfo.push(animationInfo); } // get durations & timeouts of each string let stringsDurations = [], stringsTimeouts = [], stringsTimeoutsFull = [], stringsDurationsFull = []; for(let i = 0; i < elementsLength; i++){ let timeout = 0, timeoutFull = 0; // timeout if(i !== 0){ timeout = stringsAnimationInfo[i - 1].durationFull * data.shiftString; } stringsTimeouts.push(timeout); // duration stringsDurations.push(stringsAnimationInfo[i].durationFull); // timeout full for(let a = 0; a < stringsTimeouts.length; a++){ timeoutFull += stringsTimeouts[a]; } stringsTimeoutsFull.push(timeoutFull); // duration full stringsDurationsFull.push((timeoutFull + stringsAnimationInfo[i].durationFull)); } // create animation info let animationInfo = { duration: data.duration, durationFull: Math.max.apply(Math, stringsDurationsFull), elements: stringsAnimationInfo, intervals: [] }; // calculate string intervals for(let i = 0; i < elementsLength; i++){ let obj = { time: stringsTimeoutsFull[i], percent: stringsTimeoutsFull[i] / animationInfo.durationFull, percentEnd: stringsDurationsFull[i] / animationInfo.durationFull }; animationInfo.intervals.push(obj); } // launch animation this.splitAnimate({ animationInfo: animationInfo, do: function(element, progress){ this.animate_string_elementaryAnimation(data, element, progress); }.bind(this), callbacks: data.callbacks }); return true; }; V.prototype.TextAnimate.prototype.animate_string_elementaryGetElements = function(data, type){ let elements = []; // get strings let strings = this.elements.strings; if(data.reverse){ strings = strings.slice(); strings.reverse(); } // get depth elements for(let i = 0; i < strings.length; i++){ let el = []; let words = strings[i].words; if(data.reverse){ words = words.slice(); words.reverse(); } if(type === 'stringword'){ el = words; } else{ for(let a = 0; a < words.length; a++){ let letters = strings[i].words[a].letters; if(data.reverse){ letters = letters.slice(); letters.reverse(); } for(let b = 0; b < letters.length; b++){ el.push(letters[b]); } } } elements.push(el); } // return elements return elements; } V.prototype.TextAnimate.prototype.animate_string_elementaryAnimation = function(data, obj, progress){ for(let i = 0; i < obj.intervals.length; i++){ // get current percent let current; if(progress < obj.intervals[i].percent){ current = 0; } else if(progress >= obj.intervals[i].percent & progress <= obj.intervals[i].percentEnd){ current = this.depthPercent({ scope: [obj.intervals[i].percent, obj.intervals[i].percentEnd], t: progress }); } else{ current = 1; } this.setStylesSimple({ bezier: data.bezier, element: obj.elements[i], progress: current, properties: data.definedProperties }); } }; V.prototype.Slider = class Slider extends V.prototype.Class{ constructor(data = {}){ super(data); this.prefix = `${this.prefix}slider`; this.prop = Object.assign(this.prop, { selector: `#${this.prefix}`, selectorEvents: `#${this.prefix}`, bezier: { on: false, name: 'linear' }, duration: 750, delay: 0, direction: 'h', // h / v disable: false, loop: true, start: true, keydown: false, swipe: false, wheel: false, interval: false, time: 5000, control: true, dot: true, prev: true, next: true, resize: true, resizeTimeout: 0, active: 0 }); for(let value in data){ this.prop[value] = data[value]; } } check(){ let checked = this.checkTypes({ obj: this.prop, name: this.name, console: this.prop.console, vars: [ ['selector', 'dom'], ['bezier', 'bezier'], ['duration', 'integer'], ['delay', 'integer'], ['direction', 'string'], ['disable', 'boolean'], ['loop', 'boolean'], ['start', 'boolean'], ['keydown', 'boolean'], ['swipe', 'boolean'], ['wheel', 'boolean'], ['interval', 'boolean'], ['time', 'integer'], ['control', 'boolean'], ['dot', 'boolean'], ['prev', 'boolean'], ['next', 'boolean'], ['resize', 'boolean'], ['active', 'integer'], ] }); if(!checked){ return false; } // selector events if(!this.checkType('dom', this.prop.selectorEvents)){ this.prop.selectorEvents = this.prop.selector; } // selector this.outer = this.prop.v.document().querySelector(this.prop.selector); // selector events this.outerEvents = this.prop.v.document().querySelector(this.prop.selectorEvents); // direction if(this.prop.direction !== 'v' & this.prop.direction !== 'h'){ return false; } return true; } changeProp(data){ if(!super.changeProp(data)){ return false; } this.setKeydown(); this.setSwipe(); this.setWheel(); this.setInterval(); this.setControl(); this.setDot(); this.setEventsResize(); return true; } checkItems(){ let ul = this.outer.querySelector(`.${this.prefix}__items`); if(ul === null){ return false; } this.itemsSource = ul.querySelectorAll(`.${this.prefix}__item`); if(this.itemsSource.length === 0){ return false; } return true; } createControl(){ this.prev = document.createElement("div"); this.prev.classList.add(`${this.prefix}__control`); this.prev.classList.add(`${this.prefix}__control_prev`); this.outer.appendChild(this.prev); this.next = document.createElement("div"); this.next.classList.add(`${this.prefix}__control`); this.next.classList.add(`${this.prefix}__control_next`); this.outer.appendChild(this.next); return true; } setControl(){ if(!this.prop.control){ this.outer.classList.add(`${this.prefix}_control-hidden`); } else{ this.outer.classList.remove(`${this.prefix}_control-hidden`); } return true; } setControlAbolished(num = this.active){ if(num === 0 & this.prop.loop === false){ this.prev.classList.add(`${this.prefix}__control_abolished`); } else{ this.prev.classList.remove(`${this.prefix}__control_abolished`); } if(num === (this.count - 1) & this.prop.loop === false){ this.next.classList.add(`${this.prefix}__control_abolished`); } else{ this.next.classList.remove(`${this.prefix}__control_abolished`); } return true; } createDot(){ this.dots = document.createElement("div"); this.dots.classList.add(`${this.prefix}__dots`); for(let i = 0; i < this.itemsSource.length; i++){ let dot = document.createElement("div"); dot.classList.add(`${this.prefix}__dot`); this.dots.appendChild(dot); this.dot.push(dot); } this.outer.appendChild(this.dots); return true; } setDot(){ if(!this.prop.dot){ this.outer.classList.add(`${this.prefix}_dot-hidden`); } else{ this.outer.classList.remove(`${this.prefix}_dot-hidden`); } return true; } setDotActive(num = this.active){ for(let i = 0; i < this.dot.length; i++){ if(i === num){ this.dot[i].classList.add(`${this.prefix}__dot_active`); } else{ this.dot[i].classList.remove(`${this.prefix}__dot_active`); } } return true; } setPrevBool(bool = true){ if(typeof bool !== 'boolean'){ return false; } this.prevBool = bool; if(this.prevBool === true){ this.prev.classList.remove(`${this.prefix}__control_disabled`); } else{ this.prev.classList.add(`${this.prefix}__control_disabled`); } return true; } setNextBool(bool = true){ if(typeof bool !== 'boolean'){ return false; } this.nextBool = bool; if(this.nextBool === true){ this.next.classList.remove(`${this.prefix}__control_disabled`); } else{ this.next.classList.add(`${this.prefix}__control_disabled`); } return true; } setEvents(){ // keydown this.keydownEventIDs.push(this.prop.v.keydown.add({ target: 'once', key: [37], do: this.keydownEvent.bind(this) }, this.prop.keydown, this.prop.console)); this.keydownEventIDs.push(this.prop.v.keydown.add({ target: 'once', key: [38], do: this.keydownEvent.bind(this) }, this.prop.keydown, this.prop.console)); this.keydownEventIDs.push(this.prop.v.keydown.add({ target: 'once', key: [39], do: this.keydownEvent.bind(this) }, this.prop.keydown, this.prop.console)); this.keydownEventIDs.push(this.prop.v.keydown.add({ target: 'once', key: [40], do: this.keydownEvent.bind(this) }, this.prop.keydown, this.prop.console)); // swipe this.swipeEventIDs.push(this.prop.v.swipe.add({ target: 'right', outer: this.outerEvents, k: 100, do: this.swipeEvent.bind(this) }, this.prop.swipe, this.prop.console)); this.swipeEventIDs.push(this.prop.v.swipe.add({ target: 'left', outer: this.outerEvents, k: 100, do: this.swipeEvent.bind(this) }, this.prop.swipe, this.prop.console)); this.swipeEventIDs.push(this.prop.v.swipe.add({ target: 'down', outer: this.outerEvents, k: 100, do: this.swipeEvent.bind(this) }, this.prop.swipe, this.prop.console)); this.swipeEventIDs.push(this.prop.v.swipe.add({ target: 'up', outer: this.outerEvents, k: 100, do: this.swipeEvent.bind(this) }, this.prop.swipe, this.prop.console)); // wheel this.wheelEventIDs.push(this.prop.v.wheel.add({ target: 'right', outer: this.outerEvents, k: .5, do: this.wheelEvent.bind(this) }, this.prop.wheel, this.prop.console)); this.wheelEventIDs.push(this.prop.v.wheel.add({ target: 'left', outer: this.outerEvents, k: .5, do: this.wheelEvent.bind(this) }, this.prop.wheel, this.prop.console)); this.wheelEventIDs.push(this.prop.v.wheel.add({ target: 'down', outer: this.outerEvents, k: .1, do: this.wheelEvent.bind(this) }, this.prop.wheel, this.prop.console)); this.wheelEventIDs.push(this.prop.v.wheel.add({ target: 'up', outer: this.outerEvents, k: .1, do: this.wheelEvent.bind(this) }, this.prop.wheel, this.prop.console)); // interval this.intervalEventIDs.push(this.prop.v.interval.add({ time: this.prop.time, do: this.setNext.bind(this) }, this.prop.interval, this.prop.console)); // control this.addEventListener({ el: this.prev, target: 'click', do: this.setPrev.bind(this, "controlPrev") }); this.addEventListener({ el: this.next, target: 'click', do: this.setNext.bind(this, "controlNext") }); // dot for(let i = 0; i < this.dot.length; i++){ this.addEventListener({ el: this.dot[i], target: 'click', do: this.set.bind(this, i, true, "dot", "none") }); } return true; } setEventsResize(){ if(this.resizeID != null){ this.prop.v.viewport.delete(this.resizeID); this.resizeID = null; } let timeout = this.prop.resizeTimeout; if(timeout < this.prop.v.timeMin()){ timeout = this.prop.v.timeMin(); } if(this.prop.resize){ this.resizeID = this.prop.v.viewport.add({ target: 'wh', name: `${this.name} Resize`, do: function(){ this.setSize(); this.startSlide(this.active); }.bind(this), timeout: timeout }); } } destroyEvents(){ // keydown for(let i = 0; i < this.keydownEventIDs.length; i++){ this.prop.v.keydown.delete(this.keydownEventIDs[i]); } // swipe for(let i = 0; i < this.swipeEventIDs.length; i++){ this.prop.v.swipe.delete(this.swipeEventIDs[i]); } // wheel for(let i = 0; i < this.wheelEventIDs.length; i++){ this.prop.v.wheel.delete(this.wheelEventIDs[i]); } // resize if(this.resizeID != null){ this.prop.v.viewport.delete(this.resizeID); this.resizeID = null; } } keydownEvent(data){ if(this.prop.direction === 'h'){ if(data.data.key[0] === 37){ this.setPrev("keydown"); } else if(data.data.key[0] === 39){ this.setNext("keydown"); } else{ return false; } } if(this.prop.direction === 'v'){ if(data.data.key[0] === 38){ this.setPrev("keydown"); } else if(data.data.key[0] === 40){ this.setNext("keydown"); } else{ return false; } } return true; } swipeEvent(data){ if(this.prop.direction === 'h'){ if(data.data.target === 'right'){ this.setPrev("swipe"); } else if(data.data.target === 'left'){ this.setNext("swipe"); } else{ return false; } } if(this.prop.direction === 'v'){ if(data.data.target === 'down'){ this.setPrev("swipe"); } else if(data.data.target === 'up'){ this.setNext("swipe"); } else{ return false; } } return true; } wheelEvent(data){ if(this.prop.direction === 'h'){ if(data.data.target === 'left'){ this.setPrev("wheel"); } else if(data.data.target === 'right'){ this.setNext("wheel"); } else{ return false; } } if(this.prop.direction === 'v'){ if(data.data.target === 'up'){ this.setPrev("swipe"); } else if(data.data.target === 'down'){ this.setNext("swipe"); } else{ return false; } } return true; } setKeydown(){ for(let i = 0; i < this.keydownEventIDs.length; i++){ this.prop.v.keydown.turn(this.keydownEventIDs[i], this.prop.keydown, this.prop.console); } return true; } setSwipe(){ for(let i = 0; i < this.swipeEventIDs.length; i++){ this.prop.v.swipe.turn(this.swipeEventIDs[i], this.prop.swipe, this.prop.console); } return true; } setWheel(){ for(let i = 0; i < this.wheelEventIDs.length; i++){ this.prop.v.wheel.turn(this.wheelEventIDs[i], this.prop.wheel, this.prop.console); } return true; } setInterval(){ for(let i = 0; i < this.intervalEventIDs.length; i++){ this.prop.v.interval.turn(this.intervalEventIDs[i], this.prop.interval, this.prop.console); } return true; } setIntervalOff(){ for(let i = 0; i < this.intervalEventIDs.length; i++){ this.prop.v.interval.turn(this.intervalEventIDs[i], false, this.prop.console); } return true; } setSize(){ this.width = this.outer.clientWidth; this.height = this.outer.clientHeight; return true; } getPrev(num = this.active){ let newActive = num; newActive -= 1; if(newActive < 0){ if(!this.prop.loop){ return false; } else{ newActive = this.count - 1; } } return newActive; } getNext(num = this.active){ let newActive = num; newActive += 1; if(newActive > this.count - 1){ if(!this.prop.loop){ return false; } else{ newActive = 0; } } return newActive; } setPrev(type = 'none'){ if(this.animating === true || this.prevBool !== true){ return false; } let num = this.getPrev(); if(num === false){ return false; } this.set(num, true, "prev", type); return true; } setNext(type = 'none'){ if(this.animating === true || this.nextBool !== true){ return false; } let num = this.getNext(); if(num === false){ return false; } this.set(num, true, "next", type); return true; } getActive(){ return this.active; } set(num = this.active, changeActive = true, dir = "next", type = "none"){ // if disabled if(this.prop.disable){ return false; } // if animating if(this.animating){ return false; } // get num num = parseInt(num); if(num < 0 || num > this.count - 1 || (num === this.active & this.activeShown)){ return false; } // disable and enable interval this.setIntervalOff(); setTimeout(this.setInterval.bind(this), this.prop.delay + this.prop.duration); // set classes buttons this.setControlAbolished(num); // chage active if(changeActive){ this.active = num; } // set classes items for(let i = 0; i < this.itemsSource.length; i++){ if(num === i){ this.itemsSource[i].classList.add(`${this.prefix}__item_active`); } else{ this.itemsSource[i].classList.remove(`${this.prefix}__item_active`); } } // set classes dots this.setDotActive(num); return true; } startSlide(num = this.active, force = false){ if(this.animating === true & !force){ return false; } if(this.firstStart & !this.prop.start){ return false; } if(!this.activeShown){ return false; } this.active = num; this.firstStart = false; this.activeShown = true; this.outer.classList.add(`${this.prefix}_showActive`); this.itemsSource[num].classList.add(`${this.prefix}__item_active`); this.setDotActive(num); return true; } showActive(){ if(this.activeShown || this.animating){ return false; } this.activeShown = true; this.outer.classList.add(`${this.prefix}_showActive`); this.itemsSource[this.active].classList.add(`${this.prefix}__item_active`); this.setDotActive(this.active); return true; } hideActive(){ if(!this.activeShown || this.animating){ return false; } this.activeShown = false; this.outer.classList.remove(`${this.prefix}_showActive`); this.itemsSource[this.active].classList.remove(`${this.prefix}__item_active`); this.setDotActive(this.active); return true; } init(){ let initObj = super.init(); if(!initObj){ return false; } // check this.itemsSource = []; if(!this.checkItems()){ return false; } this.outer.classList.add(`${this.prefix}`); // vars this.active = this.prop.active; this.animating = false; this.firstStart = true; this.activeShown = false; this.prev = false; this.next = false; this.prevBool = false; this.nextBool = false; this.dots = false; this.dot = []; this.keydownEventIDs = []; this.swipeEventIDs = []; this.wheelEventIDs = []; this.intervalEventIDs = []; this.resizeID = null; this.loopTypes = [ 'keydown', 'wheel', 'swipe', 'controlPrev', 'controlNext' ]; // run this.createControl(); this.setControl(); this.setControlAbolished(); this.createDot(); this.setDot(); this.setDotActive(this.active); this.setPrevBool(this.prop.prev); this.setNextBool(this.prop.next); this.setEvents(); this.setEventsResize(); this.setSize(); // return return Object.assign(initObj, { count: () => this.count, animating: () => this.animating, itemsSource: () => this.itemsSource, getActive: this.getActive.bind(this), setPrev: this.setPrevBool.bind(this), setNext: this.setNextBool.bind(this), set: this.set.bind(this), prev: this.setPrev.bind(this), next: this.setNext.bind(this), getPrev: this.getPrev.bind(this), getNext: this.getNext.bind(this), showActive: this.showActive.bind(this), hideActive: this.hideActive.bind(this), destroyEvents: this.destroyEvents.bind(this) }); } }; V.prototype.SliderCanvas = class SliderCanvas extends V.prototype.Slider{ constructor(data = {}){ super(data); this.prefix = `${this.prefix}`; this.prop = Object.assign(this.prop, { animations: { prev: [0, .5], next: [.5, 1] }, resetAnimatingTimeout: 0, parallaxX: 0, parallaxY: 0, parallaxPrev: false, hidePrev: true, fill: 'transparent', reverse: false, reverseSwipe: false, zoom: false, zoomHTML: false, zoomK: 2, zoomAnimation: 350, useVideo: false, tapVideo: false, tapVideoText: 'Tap and hold', tapVideoDuration: 250, asyncLoad: false }); for(let value in data){ this.prop[value] = data[value]; } this.targets = [ 'prev', 'next', 'before', 'after', 'show', 'hide', 'start', 'firstStart', 'zoomGain', 'zoomDiscard' ]; } check(){ if(!super.check()){ return false; } let checked = this.checkTypes({ obj: this.prop, name: this.name, console: this.prop.console, vars: [ ['animations', 'object'], ['resetAnimatingTimeout', 'integer'], ['parallaxX', 'number'], ['parallaxY', 'number'], ['parallaxPrev', 'boolean'], ['hidePrev', 'boolean'], ['fill', 'string'], ['reverse', 'boolean'], ['reverseSwipe', 'boolean'], ['zoom', 'boolean'], ['zoomHTML', 'boolean'], ['zoomK', 'number'], ['zoomAnimation', 'integer'], ['useVideo', 'boolean'], ['tapVideo', 'boolean'], ['tapVideoText', 'string'], ['tapVideoDuration', 'integer'], ['asyncLoad', 'boolean'] ] }); if(!checked){ return false; } // animations checked = this.checkTypes({ obj: this.prop.animations, name: this.name, console: this.prop.console, vars: [ ['prev', 'numberArray', {count: 2}], ['next', 'numberArray', {count: 2}] ] }); if(!checked){ return false; } return true; } changeProp(data){ if(!super.changeProp(data)){ return false; } this.setMaxParallax(); // zoom this.zoomSetProp(); // tap this.tapSet(); return true; } zoomInit(){ // zoom html this.zoomHTML = document.createElement("div"); this.zoomHTML.classList.add(`${this.prefix}__zoom`); this.outer.appendChild(this.zoomHTML); // zoom bg this.zoomBg = document.createElement("div"); this.zoomBg.classList.add(`bg-image`); this.zoomHTML.appendChild(this.zoomBg); // button this.zoomButton = document.createElement("div"); this.zoomButton.classList.add(`${this.prefix}__zoom-button`); this.outer.appendChild(this.zoomButton); // prop this.zoomSetProp(); } zoomEvents(){ // canvas click for(let i = 0; i < this.canvas.length; i++){ this.addEventListener({ target: 'click', el: this.canvas[i], do: function(){ if(!this.prop.zoomHTML){ this.zoomCanvasClick(); } }.bind(this) }); this.addEventListener({ target: 'mousemove', el: this.canvas[i], do: function(e){ if(!this.prop.zoomHTML){ this.zoomX = e.offsetX; this.zoomY = e.offsetY; } }.bind(this) }); } // button click this.addEventListener({ target: 'click', el: this.zoomButton, do: this.zoomCanvasClick.bind(this) }); // zoom scroll this.addEventListener({ target: 'scroll', el: this.zoomHTML, do: this.zoomScrollEvent.bind(this) }); } zoomScrollEvent(){ let coords = { x: this.zoomHTML.scrollLeft / (this.zoomHTML.scrollWidth - this.zoomHTML.clientWidth), y: this.zoomHTML.scrollTop / (this.zoomHTML.scrollHeight - this.zoomHTML.clientHeight) }; this.zoomX = coords.x * this.outer.clientWidth; this.zoomY = coords.y * this.outer.clientHeight; } zoomSetProp(){ // classes if(this.prop.zoom){ this.outer.classList.add(`${this.prefix}_zoom`); } else{ this.outer.classList.remove(`${this.prefix}_zoom`); } if(this.prop.zoomHTML){ this.outer.classList.add(`${this.prefix}_zoom_html`); } else{ this.outer.classList.remove(`${this.prefix}_zoom_html`); } // reisze this.zoomResize(); } zoomResize(){ if(this.zoomBg){ let width = this.outer.clientWidth * this.prop.zoomK; let height = this.outer.clientHeight * this.prop.zoomK; this.zoomBg.style.width = `${width}px`; this.zoomBg.style.height = `${height}px`; } } zoomScroll(){ $(this.zoomHTML).animate({ scrollTop: ((this.zoomBg.clientHeight - this.zoomHTML.clientHeight) / this.prop.zoomK), scrollLeft: ((this.zoomBg.clientWidth - this.zoomHTML.clientWidth) / this.prop.zoomK) }, 0); } zoomCanvasClick(e){ // return if not allowed if(!this.prop.zoom || this.firstStartSlide || this.zoomAnimating){ return false; } // if not zoomed yet if(!this.zoomed){ // zoom html - center if(this.prop.zoomHTML & !this.zoomHTML.classList.contains(`${this.prefix}__zoom_shown`)){ this.zoomX = this.outer.clientWidth / 2; this.zoomY = this.outer.clientHeight / 2; } // canvas manipulate this.zoomAnimating = true; // button class this.zoomButton.classList.add(`${this.prefix}__zoom-button_active`); let animate = new this.Animate({ console: this.prop.console, duration: this.prop.zoomAnimation, bezier: this.prop.bezier, do: this.animateCanvas.bind(this, { ctx: 0, num: this.active, action: 'zoomGain', do: function(){ // vars this.zoomed = true; this.zoomedHover = true; this.zoomAnimating = false; // start animation this.zoomLoop(); // show image this.zoomHTML.classList.add(`${this.prefix}__zoom_shown`); this.zoomScroll(0); }.bind(this) }) }); animate = animate.init(); animate.run(); // event this.launchEventsByTarget('zoomGain'); } // if already zoomed else{ // vars this.zoomedHover = false; this.zoomAnimating = true; // button class this.zoomButton.classList.remove(`${this.prefix}__zoom-button_active`); // canvas manipulate let animate = new this.Animate({ console: this.prop.console, duration: this.prop.zoomAnimation, bezier: this.prop.bezier, do: this.animateCanvas.bind(this, { ctx: 0, num: this.active, action: 'zoomDiscard', do: function(){ // vars this.zoomed = false; this.animating = false; this.zoomAnimating = false; // hide image this.zoomHTML.classList.remove(`${this.prefix}__zoom_shown`); // start slide & end animation this.startSlide(); }.bind(this) }) }); animate = animate.init(); animate.run(); // event this.launchEventsByTarget('zoomDiscard'); } } zoomLoop(){ this.animateCanvas({ ctx: 0, num: this.active, action: 'zoomGain', do: () => {} }, 1, 1); if(this.zoomedHover){ window.requestAnimationFrame(this.zoomLoop.bind(this)); } } tapInit(){ this.isTap = false; this.timeTap = 0; this.tap = document.createElement("div"); this.tap.classList.add(`${this.prefix}__tap`); this.outer.appendChild(this.tap); this.videoOuter = document.createElement("div"); this.videoOuter.classList.add(`${this.prefix}__video`); this.outer.appendChild(this.videoOuter); return true; } tapSet(){ if(!this.prop.tapVideo){ this.outer.classList.add(`${this.prefix}_tap-hidden`); } else{ this.outer.classList.remove(`${this.prefix}_tap-hidden`); } this.tap.innerHTML = `
${this.prop.tapVideoText}`; return true; } tapShowHide(num = this.active){ if(this.videos[num] == null){ this.outer.classList.add(`${this.prefix}_tap-hide`); } else{ this.outer.classList.remove(`${this.prefix}_tap-hide`); } } tapEvents(){ this.tap.addEventListener("touchstart", this.tapEventOn.bind(this)); this.tap.addEventListener("touchend", this.tapEventOff.bind(this)); this.tap.addEventListener("mousedown", this.tapEventOn.bind(this)); this.tap.addEventListener("mouseup", this.tapEventOff.bind(this)); return true; } tapEventOn(){ if(this.animating || this.isTap){ return; } this.isTap = true; this.tap.classList.add(`${this.prefix}__tap_active`); setTimeout(() => { if(this.isTap){ this.tapRender(); } }, this.prop.tapVideoDuration); } tapEventOff(){ this.isTap = false; this.tap.classList.remove(`${this.prefix}__tap_active`); this.tapRender(); } tapRender(){ let video = this.videos[this.active]; if(video == null){ return; } if(this.isTap){ video.load(); let playPromise = video.play(); if(playPromise !== undefined){ playPromise.then(function(){ }).catch(function(error){ }.bind(this)); } video.classList.add("active"); } else{ let pausePromise = video.pause(); if(pausePromise !== undefined){ pausePromise.then(function(){ }).catch(function(error){ setTimeout(() => { if(!this.isTap){ video.currentTime = 0; } }, 350); }.bind(this)); } video.classList.remove("active"); } } createCanvas(){ for(let i = 0; i < this.canvasAmount; i++){ let e = document.createElement("canvas"); this.outer.appendChild(e); this.canvas.push(e); } for(let i = 0; i < this.canvas.length; i++){ this.ctx.push(this.canvas[i].getContext('2d')); let ctx = this.ctx[this.ctx.length - 1]; ctx.mozImageSmoothingEnabled = false; ctx.webkitImageSmoothingEnabled = false; ctx.msImageSmoothingEnabled = false; ctx.imageSmoothingEnabled = false; } for(let i = 0; i < this.canvasAmount; i++){ let e = document.createElement("canvas"); this.canvasAdditional.push(e); } for(let i = 0; i < this.canvasAdditional.length; i++){ this.ctxAdditional.push(this.canvasAdditional[i].getContext('2d')); let ctx = this.ctxAdditional[this.ctxAdditional.length - 1]; ctx.mozImageSmoothingEnabled = false; ctx.webkitImageSmoothingEnabled = false; ctx.msImageSmoothingEnabled = false; ctx.imageSmoothingEnabled = false; } return true; } createImages(){ for(let i = 0; i < this.itemsSource.length; i++){ // image let img = this.itemsSource[i].querySelector("img"); if(img !== null){ let src = img.getAttribute("src"); if(src === null || src.length === 0){ continue; } let image = new Image(); image[this.data.loaded] = false; image.addEventListener('load', function(image){ image[this.data.loaded] = true; this.loaded++; this.startSlide(this.active); }.bind(this, image), false); image.src = src; // add images this.images.push(image); this.imagesTotal.push(image); // image tablet let imageTablet = img.getAttribute(this.data.imageTablet); if(imageTablet === null || imageTablet.length === 0){ this.imagesTablet.push(image); } else{ let img = new Image(); img[this.data.loaded] = false; img.addEventListener('load', function(img){ img[this.data.loaded] = true; this.loaded++; this.startSlide(this.active); }.bind(this, img), false); img.src = imageTablet; this.imagesTablet.push(img); this.imagesTotal.push(img); } // image mobile let imageMobile = img.getAttribute(this.data.imageMobile); if(imageMobile === null || imageMobile.length === 0){ this.imagesMobile.push(image); } else{ let img = new Image(); img[this.data.loaded] = false; img.addEventListener('load', function(img){ img[this.data.loaded] = true; this.loaded++; this.startSlide(this.active); }.bind(this, img), false); img.src = imageMobile; this.imagesMobile.push(img); this.imagesTotal.push(img); } // video if(this.prop.useVideo){ let video = this.itemsSource[i].querySelector("video"); if(video !== null & !((this.prop.v.browser() == 'firefox' || this.prop.v.browser() == 'opera') & !this.prop.v.desktop())){ video.setAttribute("playsinline", 'playsinline'); video.setAttribute("preload", 'metadata'); video.setAttribute("loop", 'loop'); video.setAttribute("muted", ''); video[this.data.loaded] = false; this.videos.push(video); // on loaded video.addEventListener("loadedmetadata", function(video){ video[this.data.loaded] = true; this.loadedVideos++; this.startSlide(this.active); }.bind(this, video), false); // move this.videoOuter.appendChild(video); } else{ this.videos.push(null); } } else{ this.videos.push(null); } } } return true; } setEvents(){ if(!super.setEvents()){ return false; } return true; } setSize(){ if(!super.setSize()){ return false; } // video if(this.videos){ for(let i = 0; i < this.videos.length; i++){ if(this.videos[i] != null){ let size = this.imageSize({ img: this.videos[i], width: this.width * this.maxParallax, height: this.height * this.maxParallax, maxWidth: this.width, maxHeight: this.height }); this.videos[i].style.top = size.y + 'px'; this.videos[i].style.left = size.x + 'px'; this.videos[i].style.height = size.imageHeight + 'px'; this.videos[i].style.width = size.imageWidth + 'px'; } } } // sizes this.dpr = this.prop.v.dpr(); let displayWidth = Math.floor(this.width * this.dpr), displayHeight = Math.floor(this.height * this.dpr); if(this.width !== displayWidth || this.height !== displayHeight){ this.width = displayWidth; this.height = displayHeight; } for(let i = 0; i < this.canvas.length; i++){ this.canvas[i].width = this.width; this.canvas[i].height = this.height; } // get images array this.imagesCurrent = this.images; if(this.prop.v.tablet()){ this.imagesCurrent = this.imagesTablet; } if(this.prop.v.mobile()){ this.imagesCurrent = this.imagesMobile; } return true; } setMaxParallax(){ this.maxParallax = 1 + (Math.max(Math.abs(this.prop.parallaxX), Math.abs(this.prop.parallaxY)) * 2); return true; } startSlide(num = this.active, force = false){ // wait for images & videos to load if(!this.prop.asyncLoad){ if(this.loaded < this.countImages || this.loadedVideos < this.countVideos){ return false; } } // if async load is enabled else{ let currentImage = this.imagesCurrent[num]; if(!currentImage[this.data.loaded]){ return false; } let currentVideo = this.videos[num]; if(currentVideo != null){ if(!currentVideo[this.data.loaded]){ return false; } } } // set size this.setSize(); // continue if(!super.startSlide(num, force)){ return false; } this.ctx[0].save(); this.ctx[0].beginPath(); this.ctx[0].clearRect(0, 0, this.width, this.height); this.ctx[0].rect(0, 0, this.width, this.height); this.ctx[0].fillStyle = this.prop.fill; this.ctx[0].fillRect(0, 0, this.width, this.height); // video let image = this.imagesCurrent[this.active], size = {}, element = null; element = image; size = this.imageSize({ img: element, width: this.width * this.maxParallax, height: this.height * this.maxParallax, maxWidth: this.width, maxHeight: this.height }); this.imageInfo = { outer: { width: this.width * this.maxParallax, height: this.height * this.maxParallax, maxWidth: this.width, maxHeight: this.height }, size: size }; this.ctx[0].drawImage(image, 0, 0, image.width, image.height, size.x, size.y, size.imageWidth, size.imageHeight); this.ctx[0].closePath(); this.ctx[0].restore(); /* CTX 1 */ this.ctx[1].save(); this.ctx[1].beginPath(); this.ctx[1].clearRect(0, 0, this.width, this.height); this.ctx[1].closePath(); this.ctx[1].restore(); /* CTX 2 */ this.ctx[2].save(); this.ctx[2].beginPath(); this.ctx[2].clearRect(0, 0, this.width, this.height); this.ctx[2].closePath(); this.ctx[2].restore(); // Tap this.tapShowHide(num); // event this.launchEventsByTarget("start"); if(this.firstStartSlide){ this.launchEventsByTarget("firstStart"); } // first start this.firstStartSlide = false; this.animating = false; return true; } set(num = this.active, changeActive = true, dir = "next", type = "none"){ let prevNum = this.active; if(!super.set(num, false, dir, type)){ return false; } if(this.isTap){ return false; } /* Tap */ this.tapShowHide(num); /* Get Settings */ let settings = { prev: { duration: (this.prop.animations.prev[1] - this.prop.animations.prev[0]) * this.prop.duration, delay: this.prop.animations.prev[0] * this.prop.duration, reversed: false }, next: { duration:(this.prop.animations.next[1] - this.prop.animations.next[0]) * this.prop.duration, delay: this.activeShown ? this.prop.animations.next[0] * this.prop.duration : 0, reversed: false } } if(this.loopTypes.includes(type)){ if(dir === "prev"){ settings.prev.reversed = true; settings.next.reversed = true; } else if(dir === "next"){ if(num < prevNum){ settings.prev.reversed = false; settings.next.reversed = false; } } } else{ if(num < prevNum){ settings.prev.reversed = true; settings.next.reversed = true; } } if(type == 'swipe' & this.prop.reverseSwipe){ if(settings.prev.reversed){ settings.prev.reversed = false; } else{ settings.prev.reversed = true; } if(settings.next.reversed){ settings.next.reversed = false; } else{ settings.next.reversed = true; } } /* Callbacks */ this.launchEventsByTarget("before", {prev: prevNum, next: num, dir: dir, type: type}); if(num > prevNum){ this.launchEventsByTarget("next", {prev: prevNum, next: num, dir: dir, type: type}); } else{ this.launchEventsByTarget("prev", {prev: prevNum, next: num, dir: dir, type: type}); } /* Animate */ this.animating = true; setTimeout(function(){ if(this.activeShown){ this.animate({ duration: settings.prev.duration, delay: settings.prev.delay, ctx: 1, num: prevNum, action: 'hide', reversed: settings.prev.reversed }); //this.activeShown = true; this.animate({ duration: settings.next.duration, delay: settings.next.delay, ctx: 2, num: num, action: 'show', reversed: settings.next.reversed, do: function(num){ this.launchEventsByTarget("after", {prev: this.active, next: num, dir: dir, type: type}); this.active = num; setTimeout(() => { this.animating = false; this.startSlide(num); }, this.prop.v.timeMin() + this.prop.resetAnimatingTimeout); }.bind(this, num) }); } else{ if(changeActive){ this.active = num; } this.animating = false; return this.showActive(); } }.bind(this), this.prop.delay); return true; } showActive(){ if(!super.showActive()){ return false; } let currentDuration = (this.prop.animations.next[1] - this.prop.animations.next[0]) * this.prop.duration; this.animate({ duration: currentDuration, ctx: 1, num: this.active, action: 'showActive', do: function(){ if(this.firstStart){ this.firstStart = false; } this.animating = false; this.startSlide(); this.launchEventsByTarget("show"); }.bind(this) }); return true; } hideActive(){ if(!super.hideActive()){ return false; } let currentDuration = (this.prop.animations.next[1] - this.prop.animations.next[0]) * this.prop.duration; this.animate({ duration: currentDuration, ctx: 1, num: this.active, action: 'hideActive', reversed: false, do: function(){ this.animating = false; this.launchEventsByTarget("hide"); }.bind(this) }); return true; } animate(data){ let properties = { duration: this.prop.duration, delay: 0, ctx: 0, num: this.active, action: 'show', reversed: false, do: function(){} }; for(let value in data){ properties[value] = data[value]; } this.ctx[0].save(); this.ctx[0].beginPath(); this.ctx[0].clearRect(0, 0, this.width, this.height); this.ctx[0].closePath(); this.ctx[0].restore(); this.animateCanvas({ ctx: properties.ctx, num: properties.num, action: properties.action, reversed: properties.reversed, do: properties.do }, 0, 0); let animate = new this.Animate({ console: this.prop.console, duration: parseInt(properties.duration), delay: parseInt(properties.delay), bezier: this.prop.bezier, do: this.animateCanvas.bind(this, { ctx: properties.ctx, num: properties.num, action: properties.action, reversed: properties.reversed, do: properties.do }) }); animate = animate.init(); animate.run(); return true; } animateCanvas(d, progress, bezier){ let data = {}; for(let value in d){ data[value] = d[value]; } this.animating = true; /* Zoom */ let currentZoom = 1; if(data.action == 'zoomGain'){ currentZoom = (this.prop.zoomK - 1) * bezier; currentZoom += 1; } else if(data.action == 'zoomDiscard'){ currentZoom = (this.prop.zoomK - 1) * (1 - bezier); currentZoom += 1; } /* Image */ let image = this.imagesCurrent[data.num], size = {}, element = null; element = image; size = this.imageSize({ img: element, width: this.width * this.maxParallax * currentZoom, height: this.height * this.maxParallax * currentZoom, maxWidth: this.width, maxHeight: this.height }); /* Get Reversed */ if(this.prop.reverse){ if(data.reversed){ data.reversed = false; } else{ data.reversed = true; } } /* Get Parallax Progress according to whether ACTION is SHOW or HIDE */ let parallaxProgress; if(data.action === 'show' || data.action === 'showActive'){ parallaxProgress = 1 - bezier; } else{ if(this.prop.parallaxPrev || data.action === 'hideActive'){ parallaxProgress = bezier; } else{ parallaxProgress = 0; } } if(data.action === 'zoomDiscard' || data.action === 'zoomGain'){ parallaxProgress = 0; } /* Get Parallax K according to whether REVERSE is TRUE or NOT */ let parallaxXK = this.prop.parallaxX, parallaxYK = this.prop.parallaxY; if(data.action === 'hide' || data.action === 'hideActive'){ parallaxXK *= -1; parallaxYK *= -1; } if(data.reversed){ parallaxXK *= -1; parallaxYK *= -1; } /* Calculate Parallax */ let pX = parallaxXK * this.width * parallaxProgress, pY = parallaxYK * this.height * parallaxProgress; let x = size.x - pX, y = size.y - pY; let clipWidth, clipHeight, left = 0, top = 0, translateX = 0, translateY = 0; /* Not Zoom */ if(data.action !== 'zoomGain' & data.action !== 'zoomDiscard'){ /* Directions */ if(this.prop.direction === 'h'){ clipWidth = this.width * bezier; clipHeight = this.height; if(data.reversed){ left = this.width - clipWidth; } if(data.action === 'hide' || data.action === 'hideActive'){ clipWidth = this.width * (1 - bezier); left = this.width - clipWidth; if(data.action === 'hide'){ if(!this.prop.hidePrev){ clipWidth = this.width; left = 0; } } if(data.reversed){ left = 0; } } } else{ clipWidth = this.width; clipHeight = this.height * bezier; if(data.reversed){ top = this.height - clipHeight; } clipHeight = this.height * bezier; clipWidth = this.width; if(data.reversed){ top = this.height - clipHeight; } if(data.action === 'hide' || data.action === 'hideActive'){ clipHeight = this.height * (1 - bezier); top = this.height - clipHeight; if(data.action === 'hide'){ if(!this.prop.hidePrev){ clipHeight = this.height; top = 0; } } if(data.reversed){ top = 0; } } } } /* Zoom */ else{ let coords = { x: this.zoomX / this.outer.clientWidth, y: this.zoomY / this.outer.clientHeight, }; let p = bezier; if(data.action == 'zoomDiscard'){ p = 1 - p; } // x if(coords.x != .5){ translateX = (1 - (coords.x / .5)); translateX *= this.width * (this.prop.zoomK - 1) / 2; translateX *= p; x += translateX; } // y if(coords.y != .5){ translateY = (1 - (coords.y / .5)); translateY *= this.width * (this.prop.zoomK - 1) / 2; translateY *= p; y += translateY; } clipWidth = this.width; clipHeight = this.height; } this.ctx[data.ctx].save(); this.ctx[data.ctx].beginPath(); this.ctx[data.ctx].clearRect(0, 0, this.width, this.height); this.ctx[data.ctx].rect(left, top, clipWidth, clipHeight); this.ctx[data.ctx].closePath(); this.ctx[data.ctx].clip(); this.ctx[data.ctx].fillStyle = this.prop.fill; this.ctx[data.ctx].fillRect(0, 0, this.width, this.height); this.ctx[data.ctx].drawImage(image, 0, 0, image.width, image.height, x, y, size.imageWidth, size.imageHeight); this.ctx[data.ctx].restore(); if(progress === 1){ data.do.call(this); } return true; } init(){ this.maxParallax = 0; this.canvas = []; this.canvasAdditional = []; let initObj = super.init(); if(!initObj){ return false; } // data this.data = { imageTablet: `data-${this.prefix}-imageTablet`, imageMobile: `data-${this.prefix}-imageMobile`, loaded: `data-${this.prefix}-loaded` }; // vars this.canvasAmount = 3; this.ctx = []; this.ctxAdditional = []; this.videos = []; this.loadedVideos = 0; this.images = []; this.imagesCurrent = []; this.imagesTotal = []; this.imagesTablet = []; this.imagesMobile = []; this.videos = []; this.loaded = 0; this.count = 0; this.width = 0; this.height = 0; this.dpr = 1; this.imageInfo = null; this.firstStartSlide = true; if(this.prop.start){ this.activeShown = true; } this.zoomBg = false; this.zoomed = false; this.zoomedHover = false; this.zoomX = 0; this.zoomY = 0; this.zoomAnimating = false; // create video & tap this.tapInit(); this.tapSet(); this.tapShowHide(); this.tapEvents(); // run this.createCanvas(); this.createImages(); this.count = this.images.length; this.countImages = this.imagesTotal.length; this.countVideos = 0; for(let i = 0; i < this.videos.length; i++){ if(this.videos[i] != null){ this.countVideos++; } } this.zoomInit(); this.zoomEvents(); this.setMaxParallax(); this.setSize(); // start this.startSlide(); // return return Object.assign(initObj, { images: () => this.images, imageInfo: () => this.imageInfo, firstStart: () => this.firstStartSlide, zoom: this.zoomCanvasClick.bind(this) }); } }; V.prototype.SliderContent = class SliderContent extends V.prototype.Slider{ constructor(data = {}){ super(data); this.prefixAdditional = `${this.prefix}Content`; for(let value in data){ this.prop[value] = data[value]; } this.targets = [ 'prev', 'next', 'before', 'after', 'show', 'hide' ]; } check(){ if(!super.check()){ return false; } return true; } checkItems(){ let ul = this.outer.querySelector(`.${this.prefixAdditional}__items`); if(ul === null){ return false; } this.itemsSource = ul.querySelectorAll(`.${this.prefixAdditional}__item`); if(this.itemsSource.length === 0){ return false; } return true; } createControl(){ if(!super.createControl()){ return false; } this.prev.classList.add(`${this.prefixAdditional}__control`); this.prev.classList.add(`${this.prefixAdditional}__control_prev`); this.next.classList.add(`${this.prefixAdditional}__control`); this.next.classList.add(`${this.prefixAdditional}__control_next`); return true; } setControl(){ if(!super.setControl()){ return false; } if(!this.prop.control){ this.outer.classList.add(`${this.prefixAdditional}_control-hidden`); } else{ this.outer.classList.remove(`${this.prefixAdditional}_control-hidden`); } return true; } createDot(){ if(!super.createDot()){ return false; } this.dots.classList.add(`${this.prefixAdditional}__dots`); for(let i = 0; i < this.dot.length; i++){ this.dot[i].classList.add(`${this.prefixAdditional}__dot`); } return true; } setDot(){ if(!super.setDot()){ return false; } if(!this.prop.dot){ this.outer.classList.add(`${this.prefixAdditional}_dot-hidden`); } else{ this.outer.classList.remove(`${this.prefixAdditional}_dot-hidden`); } return true; } setDotActive(num = this.active){ if(!super.setDotActive(num)){ return false; } for(let i = 0; i < this.dot.length; i++){ if(i === num){ this.dot[i].classList.add(`${this.prefixAdditional}__dot_active`); } else{ this.dot[i].classList.remove(`${this.prefixAdditional}__dot_active`); } } return true; } setPrevBool(bool = true){ if(!super.setPrevBool(bool)){ return false; } if(this.prevBool === true){ this.prev.classList.remove(`${this.prefixAdditional}__control_disabled`); } else{ this.prev.classList.add(`${this.prefixAdditional}__control_disabled`); } return true; } setNextBool(bool = true){ if(!super.setNextBool(bool)){ return false; } if(this.nextBool === true){ this.next.classList.remove(`${this.prefixAdditional}__control_disabled`); } else{ this.next.classList.add(`${this.prefixAdditional}__control_disabled`); } return true; } set(num = this.active, changeActive = true, dir = "next", type = "none"){ let prevNum = this.active; if(!super.set(num, false, dir, type)){ return false; } /* Classes */ num = parseInt(num); if(num === 0 & this.prop.loop === false){ this.prev.classList.add(`${this.prefixAdditional}__control_abolished`); } else{ this.prev.classList.remove(`${this.prefixAdditional}__control_abolished`); } if(num === (this.count - 1) & this.prop.loop === false){ this.next.classList.add(`${this.prefixAdditional}__control_abolished`); } else{ this.next.classList.remove(`${this.prefixAdditional}__control_abolished`); } for(let i = 0; i < this.itemsSource.length; i++){ if(num === i){ this.itemsSource[i].classList.add(`${this.prefixAdditional}__item_active`); } else{ this.itemsSource[i].classList.remove(`${this.prefixAdditional}__item_active`); } } /* Callbacks */ this.launchEventsByTarget("before", {prev: prevNum, next: num, dir: dir, type: type}); if(this.loopTypes.includes(type)){ if(dir === "prev"){ this.launchEventsByTarget("prev", {prev: prevNum, next: num, dir: dir, type: type}); } else{ this.launchEventsByTarget("next", {prev: prevNum, next: num, dir: dir, type: type}); } } else{ if(num > prevNum){ this.launchEventsByTarget("next", {prev: prevNum, next: num, dir: dir, type: type}); } else{ this.launchEventsByTarget("prev", {prev: prevNum, next: num, dir: dir, type: type}); } } /* Animate */ this.animating = true; if(!this.activeShown){ if(changeActive){ this.active = num; } this.animating = false; return this.showActive(); } setTimeout(function(){ this.launchEventsByTarget("after", {prev: this.active, next: num, dir: dir, type: type}); if(changeActive){ this.active = num; } this.animating = false; this.startSlide(num); }.bind(this), this.prop.delay + this.prop.duration); return true; } startSlide(num = this.active){ if(!super.startSlide(num)){ return false; } this.outer.classList.add(`${this.prefixAdditional}_showActive`); this.itemsSource[num].classList.add(`${this.prefixAdditional}__item_active`); return true; } showActive(){ if(!super.showActive()){ return false; } this.outer.classList.add(`${this.prefixAdditional}_showActive`); this.itemsSource[this.active].classList.add(`${this.prefixAdditional}__item_active`); this.animating = true; setTimeout(function(){ if(this.firstStart){ this.firstStart = false; } this.startSlide(); this.animating = false; this.launchEventsByTarget("show"); }.bind(this), this.prop.duration); return true; } hideActive(){ if(!super.hideActive()){ return false; } this.outer.classList.remove(`${this.prefixAdditional}_showActive`); this.itemsSource[this.active].classList.remove(`${this.prefixAdditional}__item_active`); this.animating = true; setTimeout(function(){ this.animating = false; this.launchEventsByTarget("hide"); }.bind(this), this.prop.duration); return true; } init(){ let initObj = super.init(); if(!initObj){ return false; } this.outer.classList.add(`${this.prefixAdditional}`); // vars this.count = this.itemsSource.length; // start if(this.prop.start){ this.activeShown = true; } this.startSlide(); // return return initObj; } }; V.prototype.Cursor = class Cursor extends V.prototype.Class{ constructor(data = {}){ super(data); this.prefix = `${this.prefix}cursor`; this.prop = Object.assign(this.prop, { selector: `#${this.prefix}`, selectorAnchor: `.${this.prefix}__hover`, k: .3, run: true, hideDefault: false, width: 36, height: 36, radius: 18, helpers: 0, moveInner: { on: true, k: .1, max: 1000, ignore: .1 } }); for(let value in data){ this.prop[value] = data[value]; } this.targets = [ ]; } /* Check */ check(){ let checked = this.checkTypes({ obj: this.prop, name: this.name, console: this.prop.console, vars: [ ['selector', 'dom'], ['selectorAnchor', 'dom'], ['k', 'number'], ['run', 'boolean'], ['hideDefault', 'boolean'], ['width', 'integer'], ['height', 'integer'], ['radius', 'integer'], ['helpers', 'integer'], ['moveInner', 'object'] ] }); if(!checked){ return false; } checked = this.checkTypes({ obj: this.prop.moveInner, name: this.name, console: this.prop.console, vars: [ ['on', 'boolean'], ['k', 'number'], ['max', 'number'], ['ignore', 'number'] ] }); if(!checked){ return false; } // get outer this.outer = this.prop.v.document().querySelector(this.prop.selector); // hide default if(this.prop.hideDefault){ this.outer.classList.add(`${this.prefix}_hideDefault`); } else{ this.outer.classList.remove(`${this.prefix}_hideDefault`); } return true; } /* Change Properties */ changeProp(data){ let runPrev = this.prop.run; if(!super.changeProp(data)){ return false; } if(this.prop.run !== runPrev){ this.run(); } return true; } /* Create Elements */ create(){ // outer this.outer.classList.add(`${this.prefix}`); // element this.element = document.createElement("div"); this.element.classList.add(`${this.prefix}__element`); this.outer.appendChild(this.element); // border this.border = document.createElement("div"); this.border.classList.add(`${this.prefix}__border`); this.element.appendChild(this.border); // helpers for(let i = 0; i < this.prop.helpers; i++){ let helper = document.createElement("div"); helper.classList.add(`${this.prefix}__helper`); helper.classList.add(`${this.prefix}__helper_${i}`); this.element.appendChild(helper); this.helpers.push(helper); } return true; } /* Set Events */ setEvents(){ this.addEventListener({ el: this.outer, target: 'mousemove', do: this.mousemove.bind(this) }); this.addEventListener({ el: window, target: 'mouseover', do: this.mouseover.bind(this) }); this.addEventListener({ el: window, target: 'mouseout', do: this.mouseout.bind(this) }); this.addEventListener({ el: this.prop.v.document(), target: 'mousedown', do: this.mousedown.bind(this) }); this.addEventListener({ el: this.prop.v.document(), target: 'mouseup', do: this.mouseup.bind(this) }); return true; } mousemove(e){ this.coords.x = e.x; this.coords.y = e.y; if(!this.shown){ this.shown = true; this.element.classList.add(`${this.prefix}__element_shown`); this.animate(true); } } mouseover(e){ this.element.classList.add(`${this.prefix}__element_shown`); } mouseout(e){ this.element.classList.remove(`${this.prefix}__element_shown`); } mousedown(e){ this.element.classList.add(`${this.prefix}__element_click`); } mouseup(e){ this.element.classList.remove(`${this.prefix}__element_click`); } /* Update Elements */ updateElements(){ let el = this.prop.v.document().querySelectorAll(this.prop.selectorAnchor), array = []; // get existing elements for(let i = 0; i < this.elements.length; i++){ if(this.childOf(this.elements[i], this.outer)){ array.push(this.elements[i]); } } this.elements = array; // add new elements for(let i = 0; i < el.length; i++){ // skip if proceeded let attribute = el[i].getAttribute(this.data.proceeded); if(attribute != null){ continue; } // set vars el[i][this.data.data] = { hovered: false, inner: el[i].parentNode.querySelector(`.${this.prefix}__inner`), bounding: {}, x: 0, y: 0, xCurrent: 0, yCurrent: 0, moveInnerMax: null }; if(el[i][this.data.data].inner){ el[i][this.data.data].bounding = el[i].getBoundingClientRect(); } if(el[i].getAttribute(this.data.moveInnerMax)){ el[i][this.data.data].moveInnerMax = parseFloat(el[i].getAttribute(this.data.moveInnerMax)); } this.elements.push(el[i]); // set events this.addEventListener({ el: el[i], target: 'mouseover', do: this.mouseoverAnchor.bind(this, el[i]) }); this.addEventListener({ el: el[i], target: 'mouseout', do: this.mouseoutAnchor.bind(this, el[i]) }); // set proceeded attribute el[i].setAttribute(this.data.proceeded, "true"); } } /* Set Events Anchors */ mouseoverAnchor(el, e){ // return if not run if(!this.prop.run){ return; } // change hovered this.hovered = true; // change vars in element hovered el[this.data.data].hovered = true; // get values let width = el.getAttribute(this.data.width), height = el.getAttribute(this.data.height), borderColor = el.getAttribute(this.data.borderColor), cursorClass = el.getAttribute(this.data.class); // width if(width){ width = parseInt(width); this.pos.width = width; } else{ this.pos.width = el.getBoundingClientRect().width; } // height if(height){ height = parseInt(height); this.pos.height = height; } else{ this.pos.height = el.getBoundingClientRect().height; } // border color if(borderColor){ this.border.style.borderColor = borderColor; } // border radius this.pos.radius = this.pos.height / 2; // class el.parentNode.classList.add(`${this.prefix}_hovered`); if(cursorClass){ this.element.classList.add(cursorClass); } } mouseoutAnchor(el, e){ // return if not run if(!this.prop.run){ return; } // change hovered this.hovered = false; // change vars in element hovered el[this.data.data].hovered = false; // border color this.border.style.borderColor = ''; // border radius this.pos.radius = this.prop.radius; // class el.parentNode.classList.remove(`${this.prefix}_hovered`); let cursorClass = el.getAttribute(this.data.class); if(cursorClass){ this.element.classList.remove(cursorClass); } } resetHover(){ this.hovered = false; for(let i = 0; i < this.elements.length; i++){ this.mouseoutAnchor(this.elements[i]); } } /* Animate */ run(){ if(!this.prop.run){ return; } window.requestAnimationFrame(this.run.bind(this)); this.animate(); } animate(force = false){ // get k let k = this.prop.k; if(force){ k = 1; } // x & y let x = this.coords.x, y = this.coords.y; // change x & y if hovered if(this.hovered){ x = x - ((this.pos.width - this.prop.width) / 2); y = y - ((this.pos.height - this.prop.height) / 2); } // move and reduce x & y this.pos.x += (x - this.pos.x) * k; this.pos.y += (y - this.pos.y) * k; // width & height let width = this.prop.width, height = this.prop.height; if(this.hovered){ this.pos.widthCurrent += (this.pos.width - this.pos.widthCurrent) * k; width = this.pos.widthCurrent; this.pos.heightCurrent += (this.pos.height - this.pos.heightCurrent) * k; height = this.pos.heightCurrent; } else{ this.pos.widthCurrent -= (this.pos.widthCurrent - this.prop.width) * k; width = this.pos.widthCurrent; this.pos.heightCurrent -= (this.pos.heightCurrent - this.prop.height) * k; height = this.pos.heightCurrent; } // borderRadius if(this.hovered){ this.pos.radiusCurrent += (this.pos.radius - this.pos.radiusCurrent) * k; } else{ this.pos.radiusCurrent -= (this.pos.radiusCurrent - this.prop.radius) * k; } let radius = this.pos.radiusCurrent; // apply this.element.style.transform = `translate3d(${this.pos.x}px, ${this.pos.y}px, 0)`; this.element.style.width = `${width}px`; this.element.style.height = `${height}px`; this.border.style.borderRadius = `${radius}px`; // move elements let max = this.prop.moveInner.max; for(let i = 0; i < this.elements.length; i++){ let el = this.elements[i], data = el[this.data.data]; if(data.hovered & data.inner != null & this.prop.moveInner.on){ // get x & y el[this.data.data].bounding = el.getBoundingClientRect(); let x = this.coords.x - data.bounding.left - (this.pos.width / 2) - ((el.clientWidth - this.pos.width) / 2), y = this.coords.y - data.bounding.top - (this.pos.height / 2) - ((el.clientHeight - this.pos.height) / 2); data.xCurrent += (x - data.xCurrent) * this.prop.moveInner.k; data.yCurrent += (y - data.yCurrent) * this.prop.moveInner.k; // if more than maximum value if(data.moveInnerMax != null){ max = data.moveInnerMax; } if(Math.abs(data.xCurrent) > max){ if(data.xCurrent < 0){ data.xCurrent = -max; } else if(data.xCurrent > 0){ data.xCurrent = max; } } if(Math.abs(data.yCurrent) > max){ if(data.yCurrent < 0){ data.yCurrent = -max; } else if(data.yCurrent > 0){ data.yCurrent = max; } } // apply data.inner.style.transform = `translate3d(${data.xCurrent}px, ${data.yCurrent}px, 0)`; } else if(!data.hovered & data.inner != null){ if( (data.xCurrent == 0 || Math.abs(data.xCurrent) <= this.prop.moveInner.ignore) & (data.yCurrent == 0 || Math.abs(data.yCurrent) <= this.prop.moveInner.ignore) ){ continue; } data.xCurrent -= data.xCurrent * this.prop.moveInner.k; data.yCurrent -= data.yCurrent * this.prop.moveInner.k; // apply data.inner.style.transform = `translate3d(${data.xCurrent}px, ${data.yCurrent}px, 0)`; } } } /* Init */ init(){ let initObj = super.init(); if(!initObj){ return false; } // vars this.coords = { x: 0, y: 0 }; this.pos = { x: 0, y: 0, width: this.prop.width, widthCurrent: this.prop.width, height: this.prop.height, heightCurrent: this.prop.height, radius: this.prop.radius, radiusCurrent: this.prop.radius }; this.data = { proceeded: `data-${this.prefix}-proceeded`, data: `data-${this.prefix}-data`, width: `data-${this.prefix}-width`, height: `data-${this.prefix}-height`, borderColor: `data-${this.prefix}-borderColor`, class: `data-${this.prefix}-class`, moveInnerMax: `data-${this.prefix}-moveInnerMax`, timeout: `data-${this.prefix}-timeout`, }; this.elements = []; this.helpers = []; this.hovered = false; this.shown = false; this.resizeId = null; // create elements this.create(); // set events this.setEvents(); this.updateElements(); // start animation this.run(); // return return Object.assign(initObj, { getElement: () => this.element, getElements: () => this.elements, getBorder: () => this.border, getHelpers: () => this.helpers, getOuter: () => this.outer, getPos: () => this.pos, updateElements: this.updateElements.bind(this), resetHover: this.resetHover.bind(this) }); } }; V.prototype.Menu = class Menu extends V.prototype.Class{ constructor(data = {}){ super(data); this.prefix = `${this.prefix}menu`; this.prop = Object.assign(this.prop, { selector: `#${this.prefix}`, selectorButton: `#${this.prefix}-button`, animation: 500, animationButton: 650, animationInner: { on: false, duration: 500 }, delays: { show: 0, hide: 0 }, keydown: { on: true, key: 27 }, link: { on: false, href: '' } }); for(let value in data){ this.prop[value] = data[value]; } this.targets = [ 'show', 'shown', 'hide', 'hidden' ]; } check(){ let checked = this.checkTypes({ obj: this.prop, name: this.name, console: this.prop.console, vars: [ ['selector', 'dom'], ['selectorButton', 'dom'], ['animation', 'integer'], ['animationButton', 'integer'], ['animationInner', 'object'], ['delays', 'object'], ['keydown', 'object'], ['link', 'object'] ] }); if(!checked){ return false; } checked = this.checkTypes({ obj: this.prop.delays, name: this.name, console: this.prop.console, vars: [ ['show', 'integer'], ['hide', 'integer'] ] }); if(!checked){ return false; } checked = this.checkTypes({ obj: this.prop.animationInner, name: this.name, console: this.prop.console, vars: [ ['on', 'boolean'], ['duration', 'integer'] ] }); if(!checked){ return false; } checked = this.checkTypes({ obj: this.prop.keydown, name: this.name, console: this.prop.console, vars: [ ['on', 'boolean'], ['key', 'integer'] ] }); if(!checked){ return false; } checked = this.checkTypes({ obj: this.prop.link, name: this.name, console: this.prop.console, vars: [ ['on', 'boolean'], ['href', 'string'] ] }); if(!checked){ return false; } this.outer = this.prop.v.document().querySelector(this.prop.selector); this.button = this.prop.v.document().querySelector(this.prop.selectorButton); return true; } changeProp(data){ if(!super.changeProp(data)){ return false; } this.keydownEvents(); this.linkEvent(); return true; } setEvents(){ this.buttonEvents(); this.keydownEvents(); this.linkEvent(); return true; } buttonEvents(){ this.button.setAttribute(`data-${this.prop.v.prefix()}preloader-none`, true); this.addEventListener({ el: this.button, target: 'click', do: this.clickButton.bind(this) }); this.addEventListener({ el: this.button, target: 'mouseover', do: this.mouseoverButton.bind(this) }); this.addEventListener({ el: this.button, target: 'mouseleave', do: this.mouseleaveButton.bind(this) }); return true; } clickButton(e){ e.preventDefault(); this.buttonClick(); } mouseoverButton(e){ this.buttonHovered = true; } mouseleaveButton(e){ this.buttonHovered = false; } keydownEvents(){ for(let i = 0; i < this.keydownEventIDs.length; i++){ this.prop.v.keydown.delete(this.keydownEventIDs[i], this.prop.console); } this.keydownEventIDs.push(this.prop.v.keydown.add({ target: 'once', key: [this.prop.keydown.key], do: this.hide.bind(this) }, this.prop.keydown.on, this.prop.console)); return true; } linkEvent(){ if(this.prop.link.on){ this.button.classList.add(`${this.prefix}-button_close`); this.button.classList.add(`${this.prefix}-button_forbidden-hover`); this.button.href = this.prop.link.href; } else{ this.button.classList.remove(`${this.prefix}-button_close`); this.button.classList.remove(`${this.prefix}-button_forbidden-hover`); this.button.href = ''; } return true; } buttonClick(){ if(this.prop.link.on){ window.location.href = this.prop.link.href; } else{ this.showHide(); } return true; } show(){ if(this.shown){ return false; } return this.showHide(); } hide(){ if(!this.shown){ return false; } return this.showHide(); } showHide(){ if(this.animating){ return false; } this.buttonHoverForbidden = true; this.animating = true; if(this.shown){ this.launchEventsByTarget("hide"); if(this.prop.delays.hide === 0){ this.hideFunc(); } else{ setTimeout(this.hideFunc.bind(this), this.prop.delays.hide); } } else{ this.launchEventsByTarget("show"); if(this.prop.delays.show === 0){ this.showFunc(); } else{ setTimeout(this.showFunc.bind(this), this.prop.delays.show); } } return true; } showFunc(){ this.prop.v.document().classList.add(`${this.prefix}_shown`); this.outer.classList.add(`${this.prefix}_show`); this.button.classList.add(`${this.prefix}-button_close`); this.outer.classList.remove(`${this.prefix}_prepare-hide`); setTimeout(function(){ this.outer.classList.add(`${this.prefix}_prepare-show`); this.button.classList.add(`${this.prefix}-button_forbidden-hover`); }.bind(this), this.prop.v.timeMin()); setTimeout(function(){ this.shown = true; if(this.prop.animationInner.on){ this.outer.classList.add(`${this.prefix}_animation-show`); setTimeout(function(){ this.animating = false; this.launchEventsByTarget("shown"); }.bind(this), this.prop.animationInner.duration); } else{ this.animating = false; this.launchEventsByTarget("shown"); } }.bind(this), this.prop.animation); return true; } hideFunc(){ this.outer.classList.remove(`${this.prefix}_animation-show`); if(this.prop.animationInner.on){ setTimeout(this.hideFuncInner.bind(this), this.prop.animationInner.duration); } else{ this.hideFuncInner(); } return true; } hideFuncInner(){ this.prop.v.document().classList.remove(`${this.prefix}_shown`); this.button.classList.remove(`${this.prefix}-button_close`); this.outer.classList.remove(`${this.prefix}_prepare-show`); this.outer.classList.add(`${this.prefix}_prepare-hide`); setTimeout(function(){ this.outer.classList.remove(`${this.prefix}_show`); this.shown = false; this.animating = false; this.launchEventsByTarget("hidden"); }.bind(this), this.prop.animation); setTimeout(function(){ if(this.buttonHovered){ $(this.button).one("mouseleave", function(){ if(this.buttonHoverForbidden){ this.button.classList.remove(`${this.prefix}-button_forbidden-hover`); } }.bind(this)); } else{ this.button.classList.remove(`${this.prefix}-button_forbidden-hover`); } }.bind(this), this.prop.animationButton); return true; } init(){ let initObj = super.init(); if(!initObj){ return false; } this.outer.classList.add(`${this.prefix}`); this.button.classList.add(`${this.prefix}-button`); this.shown = false; this.animating = false; this.buttonHovered = false; this.buttonHoverForbidden = false; this.keydownEventIDs = []; this.setEvents(); return Object.assign(initObj, { shown: () => this.shown, animating: () => this.animating, show: this.show.bind(this), hide: this.hide.bind(this), showHide: this.showHide.bind(this) }); } }; V.prototype.Filter = class Filter extends V.prototype.Class{ constructor(data = {}){ super(data); this.prefix = `${this.prefix}filter`; this.prop = Object.assign(this.prop, { selectors: { item: `.${this.prefix}__item`, title: `.${this.prefix}__title`, value: `.${this.prefix}__value`, markers: `.${this.prefix}__markers` }, saveOnChange: true, updateTitle: true, updateCount: true, removeDisabledActive: true, start: true, disabledTries: 1000, popstateEvent: true, popstateEventReload: true, setParamToNull: false, param: 'page', markers: true, separator: '__', separatorAjax: '__', separatorAjaxCount: '--', cache: false }); for(let value in data){ this.prop[value] = data[value]; } this.targets = [ 'title', 'value', 'start', 'reset', 'save', 'count' ]; } check(){ let checked = this.checkTypes({ obj: this.prop, name: this.name, console: this.prop.console, vars: [ ['selectors', 'object'], ['saveOnChange', 'boolean'], ['updateTitle', 'boolean'], ['updateCount', 'boolean'], ['removeDisabledActive', 'boolean'], ['start', 'boolean'], ['disabledTries', 'integer'], ['popstateEvent', 'boolean'], ['popstateEventReload', 'boolean'], ['setParamToNull', 'boolean'], ['param', 'string'], ['markers', 'boolean'], ['separator', 'string'], ['separatorAjax', 'string'], ['separatorAjaxCount', 'string'], ['cache', 'boolean'] ] }); if(!checked){ return false; } checked = this.checkTypes({ obj: this.prop.selectors, name: this.name, console: this.prop.console, vars: [ ['item', 'string'], ['title', 'string'], ['value', 'string'], ['markers', 'string'] ] }); if(!checked){ return false; } if(this.prop.markers){ let checked = this.checkTypes({ obj: this.prop.selectors, name: this.name, console: this.prop.console, vars: [ ['markers', 'dom'] ] }); if(!checked){ return false; } } return true; } changeProp(data){ if(!super.changeProp(data)){ return false; } if(!this.setItems()){ return false; } this.start(); this.set(); return true; } setItems(){ if(!this.addMarkers()){ return false; } this.addItems(); this.addValues(); return true; } addMarkers(){ if(this.prop.markers){ this.markers = this.prop.v.document().querySelector(this.prop.selectors.markers); this.markers.classList.add(`${this.prefix}__markers`); } return true; } addItems(){ let itemsArray = this.prop.v.document().querySelectorAll(this.prop.selectors.item); for(let i = 0; i < itemsArray.length; i++){ let id = itemsArray[i].getAttribute(this.data.id), proceeded = itemsArray[i].getAttribute(this.data.proceeded); if(id === null){ continue; } else{ if(proceeded !== null){ continue; } this.items.push(itemsArray[i]); this.ids.push(id); let title = this.prop.v.document().querySelector(`${this.prop.selectors.title}[${this.data.id}="${id}"]`); if(title !== null){ this.titles[id] = title; this.titlesDefault[id] = title.innerHTML; title.classList.add(`${this.prefix}__title`); } itemsArray[i].classList.add(`${this.prefix}__item`); itemsArray[i].setAttribute(this.data.proceeded, true); } } return true; } addValues(){ for(let i = 0; i < this.ids.length; i++){ let valuesArray = this.prop.v.document().querySelectorAll(`${this.prop.selectors.value}[${this.data.id}="${this.ids[i]}"]`); for(let a = 0; a < valuesArray.length; a++){ if(valuesArray[a].getAttribute(this.data.value) == null){ continue; } if(valuesArray[a].getAttribute(this.data.proceeded) !== null){ continue; } valuesArray[a].classList.add(`${this.prefix}__value`); valuesArray[a].setAttribute(this.data.proceeded, true); valuesArray[a].setAttribute(`data-${this.prop.v.prefix()}preloader-none`, true); this.valueEvent(valuesArray[a]); this.values.push(valuesArray[a]); } } return true; } getItem(id = ''){ let outer = null; for(let i = 0; i < this.items.length; i++){ if(this.items[i].getAttribute(this.data.id) == id){ outer = this.items[i]; } } return outer; } getValues(id = ''){ let array = []; for(let i = 0; i < this.values.length; i++){ if(this.values[i].getAttribute(this.data.id) == id){ array.push(this.values[i]); } } return array; } getValueActive(element){ return element.classList.contains(this.classes.valueActive); } getValueDisabled(element){ return element.classList.contains(this.classes.valueDisabled); } valuesRemoveActive(values, exceptValue){ for(let i = 0; i < values.length; i++){ if(values[i].getAttribute(this.data.value) != exceptValue){ values[i].classList.remove(this.classes.valueActive); } } return true; } valueToggleActive(element){ if(this.getValueActive(element)){ element.classList.remove(this.classes.valueActive); } else{ element.classList.add(this.classes.valueActive); } return true; } markersToggleActive(){ if(this.markers.children.length > 0){ this.markers.classList.remove(`${this.prefix}__markers_empty`); } else{ this.markers.classList.add(`${this.prefix}__markers_empty`); } return true; } valueEvent(element){ this.addEventListener({ el: element, target: 'click', do: this.valueClick.bind(this, element) }); return true; } valueClick(element, e = null){ if(e !== null){ e.preventDefault(); } if(!this.valueClickCheck(element)){ return false; } // get id let id = element.getAttribute(this.data.id), value = element.getAttribute(this.data.value); // get item let item = this.getItem(id); if(item === null){ return false; } // get values let values = this.getValues(id); // remove active if(item.getAttribute(this.data.count) !== null){ this.valuesRemoveActive(values, value); } // toggle active this.valueToggleActive(element); // toggle active all if(item.getAttribute(this.data.count) == null & element.getAttribute(this.data.all) !== null){ if(element.classList.contains(this.classes.valueActive)){ for(let i = 0; i < values.length; i++){ values[i].classList.add(this.classes.valueActive); } } else{ for(let i = 0; i < values.length; i++){ values[i].classList.remove(this.classes.valueActive); } } } this.launchEventsByTarget("value", { element: element, id: id, active: this.getValueActive(element), disabled: this.getValueDisabled(element) }); // continue setting elements if(this.prop.saveOnChange){ this.save(); } else{ this.set(); this.count(); } return true; } valueClickCheck(element){ if(this.loading & this.prop.updateCount){ return false; } if(this.getValueDisabled(element) & !this.getValueActive(element)){ return false; } if(this.getValueActive(element) & !this.prop.removeDisabledActive){ return false; } return true; } setTitle(){ for(let i = 0; i < this.ids.length; i++){ if(typeof this.titles[this.ids[i]] != "undefined"){ let title = '', id = this.ids[i]; let values = this.getValues(id); for(let a = 0; a < values.length; a++){ if(this.getValueActive(values[a])){ let value = values[a].innerHTML; title += ', ' + value; } } if(title === ''){ title = this.titlesDefault[this.ids[i]]; } else{ if(this.prop.updateTitle){ title = title.substring(2); } else{ title = this.titlesDefault[this.ids[i]]; } } this.titles[this.ids[i]].innerHTML = title; this.launchEventsByTarget("title", { element: this.titles[this.ids[i]], id: this.ids[i], title: title }); } } return true; } setMarker(){ if(!this.prop.markers){ return false; } this.removeChildren(this.markers); for(let i = 0; i < this.ids.length; i++){ let values = this.getValues(this.ids[i]); for(let a = 0; a < values.length; a++){ if(this.getValueActive(values[a]) & values[a].getAttribute(this.data.all) === null){ let html = values[a].innerHTML, marker = this.createMarker(html, values[a]); this.markers.appendChild(marker); } } this.markersToggleActive(); } return true; } createMarker(html, value){ let element = document.createElement("div"); element.classList.add(`${this.prefix}__marker`); element.innerHTML = `