UNPKG

ts-query

Version:

its simple library for dom control.

1,824 lines (1,590 loc) 78.9 kB
var $ = (function (W, D) { "use strict"; var pr = "prototype", c = "constructor", d = "document", w = "window", co = console, A = Array; /** * @class E * @param {HTMLElement|HTMLInputElement} node * @constructor */ var E = function (node) { /** * Объект для хранения временных данных * @type {{}} * @private */ this._state = {}; /** * элемент * @type {HTMLElement|HTMLInputElement} * @private */ this._node = node; }; /** * Ссылка на прототип для быстрой и компактной записи (профит при обфусцировании) * @type {Object} */ var ep = E.prototype; /** * Получаем или ставим атрибут * @param {string} name * @param {string} [value] * @returns {string|null} */ ep.attr = function (name, value) { if (E._hasVal(value)) { this._node.setAttribute(name, value); } else { return this._node.getAttribute(name) || ""; } }; /** * Добавляем класс * @param {string} className */ ep.addClass = function (className) { if (!this.hasClass(className)) { var classList = this._node.className.split(" "); classList.push(className); this._node.className = $.trim(classList.join(" ")); } }; /** * Убираем класс * @param {string} className */ ep.removeClass = function (className) { if (this.hasClass(className)) { var classList = this._node.className.split(" "); classList.splice(classList.indexOf(className), 1); this._node.className = $.trim(classList.join(" ")); } }; /** * Добавляем/получаем стили элемента * @param {string|Object} name * @param [value] * @returns {string|*} */ ep.css = function (name, value) { if (typeof name == "object") { $.forEach(name, function (value, name) { this._setCss(name, value); }, this); return this; } if (E._hasVal(value)) { this._setCss(name, value); } else { return this._getCss(name); } }; /** * Скрываем элемент * @returns {ep} */ ep.hide = function () { var display = this.css('display'); if (display != 'none') { this._state.display = display; this.css('display', 'none'); } return this; }; /** * Показываем элемент * @returns {ep} */ ep.show = function () { var display = this.css('display'); if (display === 'none') { this.css('display', this._state.display || 'block'); } return this; }; /** * Скрываем или показываем элемент * @param {boolean} state * @returns {ep} */ ep.toggleDisplay = function (state) { if (!E._hasVal(state)) { state = (this.css('display') == 'none'); } return (state ? this.show() : this.hide()); }; /** * Добавляем/убираем класс * @param {string} className * @param {boolean} [state] */ ep.toggleClass = function (className, state) { if (!E._hasVal(state)) { state = !this.hasClass(className); } return (state ? this.addClass(className) : this.removeClass(className)); }; /** * Добавляем/получаем value элемента * @param {string} [value] * @returns {string|string} */ ep.val = function (value) { if (E._hasVal(value)) { this._node.value = value; } else { return this._node.value || ""; } }; /** * Проверяем наличие класса * @param {string} className * @returns {boolean} */ ep.hasClass = function (className) { return (this._node.className.split(" ").indexOf(className) != -1); }; /** * Удаляем атрибут * @param {string} name */ ep.removeAttr = function (name) { this._node.removeAttribute(name); }; ["width", "height"].forEach(function (method) { ep[method] = function (param) { if (E._hasVal(param)) { this._setCss(method, typeof param == "number" ? param + "px" : param); } else { return this._node[$.camelCase("client " + method)] || parseInt(this._getCss(method)) || 0; } } }); /** * Добавляем/получаем содержимое элемента * @param {string} [html] * @returns {string} */ ep.html = function (html) { if (E._hasVal(html)) { this._node.innerHTML = html; } else { return this._node.innerHTML; } }; ep.remove = function () { this._remove(); if (this._node.parentNode) { this._node.parentNode.removeChild(this._node); } }; ep._remove = function () { }; /** * Устанавливаем стиль элемента * @param {string} name * @param {string} value * @private */ ep._setCss = function (name, value) { var $name; name = $.camelCase(name); if (!(name in E.test.style)) { if (!E._activePrefix) { if (!E._prefexes.some(function (prefix) { var $name = $.camelCase(prefix + name); if ($name in E.test.style) { E._activePrefix = prefix; name = $name; return true; } })) { co.warn("Не удалось найти префикс!", name, value); } } else { $name = $.camelCase(E._activePrefix + name); if ($name in E.test.style) { name = $name; } else { co.warn("Не корректный стиль!", name, value); } } } this._node.style[name] = value; }; /** * Получаем стиль * @param {string} name * @returns {string} * @private */ ep._getCss = function (name) { name = $.camelCase(name); var styles = [this._node.style, getComputedStyle(this._node)]; var result = styles[0][name] || styles[1][name] || ""; var check = function (name, callback) { return styles.some(function (style) { var $name = $.camelCase(name); if ($name in style) { result = style[$name]; callback ? callback() : false; return true; } }); }; if (!result) { if (E._activePrefix) { if (!check(E._activePrefix + name)) { co.warn("Не удалось получить стиль!", name); } } else { if (!E._prefexes.some(function (prefix) { return check(prefix + name, function () { E._activePrefix = prefix; }); })) { co.warn("Не удалось получить стиль и префикс!", name); } } } return result; }; /** * Проверяет наличие значения * @param val * @returns {boolean} * @private */ E._hasVal = function (val) { return val != undefined; }; E._createE = function (node) { return new E(node); }; /** * Активный префикс * @type {string} * @private */ E._activePrefix = ""; /** * Массив префиксов браузеров * @type {string[]} * @private */ E._prefexes = [ "-moz-", "-ms-", "-webkit-", "-o-" ]; /** * @type {HTMLElement} */ E.test = D.createElement("DIV"); /** * @class $ * @extends Array * @param param * @returns {$} */ var $ = function $(param) { if (this instanceof $) { A[pr].forEach.call(arguments, function (arg) { this.add(arg); }, this); } else { return new $(param); } }; $[pr] = []; $[pr][c] = $; var p = $.prototype; ["addClass", "removeClass", "toggleClass", "removeAttr", "show", "hide", "toggleDisplay"].forEach(function (method) { p[method] = function (className) { this._toAll(method, [className]); return this; }; }); ["val", "html", "width", "height"].forEach(function (method) { p[method] = function (val) { return this._setOrGet(method, val); } }); ["attr"].forEach(function (method) { p[method] = function (name, value) { return this._setOrGet(method, value, name); } }); /** * Добавляем элементы * @param param * @return $ */ p.add = function (param) { if (A.isArray(param)) { param.forEach(this.add, this); } else { this._toElem(param).forEach(function (el) { this.push(el); }, this); } return this; }; /** * Проверяет наличие класса у первого элемента коллекции * @param {string} className * @returns {boolean} */ p.hasClass = function (className) { if (!this._has()) return false; return this[0].hasClass(className); }; /** * Ищем элементы в первом элементе коллекции * @param selector * @returns {$} */ p.find = function (selector) { if (!this._has()) return this; return new $(A[pr].slice.call(this[0]._node.querySelectorAll(selector))); }; /** * Получаем копию ноды первого элемента коллекции * @returns {$} */ p.clone = function () { if (!this._has()) return this; return new $(this[0]._node.cloneNode(true)); }; /** * Применяем стили всем элементам коллекции или получаем стиль первого * @param {string|Object} name * @param {string} [value] * @returns {string|$} */ p.css = function (name, value) { if (typeof name == "object") { return this._toAll("css", [name]); } else { if (E._hasVal(value)) { return this._toAll("css", [name, value]); } else { return this[0].css(name); } } }; /** * Перебираем все элементы коллекции * @param callback * @returns {$} */ p.each = function (callback) { this.forEach(function (el, index) { callback(this.eq(index), el._node, index); }, this); return this; }; /** * Получаем коллекцию элементов дочерних первому элементу коллекции * @returns {$} */ p.children = function () { if (!this._has()) return this; return new $(A[pr].slice.call(this[0]._node.childNodes)); }; /** * Получаем новую коллекцию с элементом по номеру * @param index * @returns {$} */ p.eq = function (index) { if (!this._has()) return this; return new $(this[index || 0]); }; /** * Получаем ДОМ элемент из коллекции по номеру * @param index * @returns {HTMLElement|null} */ p.get = function (index) { if (!this._has()) return null; return this[index || 0]._node; }; /** * Получаем коллекцию из родительского элемента */ p.parent = function () { if (!this._has()) return this; return new $(this[0]._node.parentNode); }; /** * Добавляем в конец набора элементов * @param param * @returns {$} */ p.append = function (param) { if (!this._has()) return this; this._toElem(param, true).forEach(function (elem) { this[0]._node.appendChild(elem._node); }, this); }; /** * Добавляем в начало набора элементов * @param param * @returns {$} */ p.prepend = function (param) { if (!this._has()) return this; this._toElem(param, true).forEach(function (elem) { var childs = A[pr].filter.call(this[0]._node.childNodes, function (el) { return $.isElement(el) }); if (childs.length) { this[0]._node.insertBefore(elem._node, childs[0]); } else { this[0]._node.appendChild(elem._node); } }, this); }; /** * Приводим элементы к 1 типу * @param param * @param notSelector * @returns {*} * @private */ p._toElem = function (param, notSelector) { if ($.isElement(param)) { return [E._createE(param)]; } else if (param instanceof E) { return [param]; } else if (param instanceof $) { return [param[0]]; } else if (typeof param == "string") { if (/<.+?>/.test(param)) { return $.parse(param).map(function (el) { return E._createE(el) }); } else { if (notSelector) { return [{_node: document.createTextNode(param)}]; } else { return A[pr].slice.call(D.querySelectorAll(param)).map(function (el) { return E._createE(el) }); } } } else { co.log("wrong param!", param); return []; } }; /** * Выполняем для всех элементов коллекции * @param method * @param args * @returns {$} * @private */ p._toAll = function (method, args) { this.forEach(function (elem) { elem[method].apply(elem, args); }); return this; }; /** * Проверяем есть ли элементы в коллекции * @returns {boolean} * @private */ p._has = function () { if (!this.length) { co.warn("not length!"); return false; } else { return true; } }; /** * Задаем или получаем данные для элементов коллекции * @param method * @param argToCheck * @param [arg] * @returns {*} * @private */ p._setOrGet = function (method, argToCheck, arg) { if (!this._has()) return this; if (E._hasVal(argToCheck)) { var args = arg ? [arg, argToCheck] : [argToCheck]; this._toAll(method, args); return this; } else { return this[0][method](arg); } }; /** * Парсим строку превращая её в ДОМ * @param html * @returns {Array} */ $.parse = function (html) { var div = D.createElement("div"); div.innerHTML = html; return A[pr].filter.call(div.childNodes, function (elem) { return $.isElement(elem); }); }; /** * @param {number} min * @param {number} max * @returns {number} */ $.random = function (min, max) { return Math.random() * (max - min) + min; }; /** * @param {number} min * @param {number} max * @returns {number} */ $.randomInt = function (min, max) { return Math.floor(Math.random() * (max - min + 1)) + min; }; /** * @param {string} text * @returns {string} */ $.trim = (function () { if ("trim" in String[pr]) { return function (text) { return text.trim(); } } return function (text) { return (text || "").replace(/^\s+|\s+$/g, ""); } })(); /** * @param {string} text * @returns {string} */ $.camelCase = function (text) { return text.split(/[^\d\w]/).map(function (str, index) { return index ? str.charAt(0).toUpperCase() + str.substr(1) : str; }).join(""); }; /** * @returns {string} */ $.guuid = function () { return s4() + s4() + '-' + s4() + '-' + s4() + '-' + s4() + '-' + s4() + s4() + s4(); }; /** * @param some * @returns {boolean} */ $.isElement = function (some) { return ((some instanceof Node) && (some["nodeType"] == 1)); }; /** * @param {Object|Array} some * @param {function} callback * @param {*} [context] * @param {*} [argument] */ $.forEach = function (some, callback, context, argument) { if (A.isArray(some)) { some.forEach(function (value, id) { callback.call(context || this, value, id, argument); }); } else { Object.keys(some).forEach(function (name) { callback.call(context || this, some[name], name, argument); }); } }; /** * @param {Object|Array} some * @param {function} callback * @param {*} [context] * @param {*} [argument] * @returns {boolean} */ $.some = function (some, callback, context, argument) { if (A.isArray(some)) { return some.some(function (value, index) { return callback.call(context || this, value, index, argument); }); } else { return Object.keys(some).some(function (name) { return callback.call(context || this, some[name], name, argument); }); } }; /** * @param {Object|Array} some * @param {function} callback * @param {*} [context] * @param {*} [argument] * @returns {boolean} */ $.every = function (some, callback, context, argument) { return !$.some(some, function (value, name) { return !callback.call(context || this, value, name, argument); }); }; /** * @param {Object|Array} some * @param {function} callback * @param {*} [context] * @param {*} [argument] * @returns {{id: null, value: null}} */ $.findFirst = function (some, callback, context, argument) { var result = { id: null, value: null }; $.some(some, function (value, id) { if (callback.call(context || window, value, id, argument)) { result = { id: id, value: value }; return true; } }); return result; }; $.floor = function (num) { return (num + 0.5) << 0; }; $.roundTo = function (num, count) { var d = Math.pow(10, count); return $.floor(num * d) / d; }; $.addPlugin = function (callback) { callback($, E); }; $.events = {}; /** * Проверяем если винда с mcPointer * @type {boolean} */ $.isPointer = false; /** * @returns {string} */ function s4() { return Math.floor((1 + Math.random()) * 0x10000) .toString(16) .substring(1); } var getEventSupport = function (event) { event = "on" + event; var target = document.createElement("div"); target.setAttribute(event, ""); var isSupported = typeof target[event] === "function"; if (typeof target[event] !== "undefined") target[event] = null; target.removeAttribute(event); return isSupported; }; var events = { mouse: { start: "mousedown", move: "mousemove", end: "mouseup" }, mobile: { start: "touchstart", move: "touchmove", end: "touchend" }, win: { start: "MSPointerDown", move: "MSPointerMove", end: "MSPointerUp" } }; (function () { if (window.navigator.msPointerEnabled) { $.events = events.win; $.isPointer = true; } else if (getEventSupport("touchmove")) { $.events = events.mobile; } else { $.events = events.mouse; } })(); window["requestAnimationFrame"] = (function () { return window.requestAnimationFrame || window["webkitRequestAnimationFrame"] || window["mozRequestAnimationFrame"] || window["oRequestAnimationFrame"] || window["msRequestAnimationFrame"] || function (callback) { window.setTimeout(callback, 1000 / 60); }; })(); return $; })(window["$window"] || window, window["$document"] || document); (function (W, D) { $.addPlugin(function ($, E) { "use strict"; var pr = "prototype", p = $[pr], ep = E[pr], A = Array, ID = "_ID_"; /** * Функция наследования * @param child * @param parent */ var extend = function (child, parent) { var P = function () { }; P.prototype = parent.prototype; child.prototype = new P(); child.prototype.constructor = child; }; var pr = "prototype", p = $[pr], A = Array, ID = "__ID__", D = window['$document'] || document; var extend = function (child, parent) { var P = function () {}; P.prototype = parent.prototype; child.prototype = new P(); child.prototype.constructor = child; }; ///--- /** * @class BaseEvent * @constructor */ var BaseEvent = function () { this.type = null; }; /** * @param event */ BaseEvent[pr].init = function (event) { this.originEvent = event.originEvent; }; /** * @returns {string} */ BaseEvent[pr].getPrefix = function () { return "User:"; }; /** * @returns {string} */ BaseEvent[pr].getEventString = function () { return this.getPrefix() + this.type; }; /** * @returns {Object} */ BaseEvent[pr].getClone = function () { return Object.create(this); }; var pr = "prototype", p = $[pr], A = Array, ID = "__ID__", D = window['$document'] || document; var extend = function (child, parent) { var P = function () {}; P.prototype = parent.prototype; child.prototype = new P(); child.prototype.constructor = child; }; ///--- var Touch = function (e, finger, status) { this.init(e); this.status = status; this.type = "touch"; this.coordinates = {x: finger.pageX, y: finger.pageY}; this.time = finger.time; }; extend(Touch, BaseEvent); Touch[pr].getEventString = function () { return BaseEvent[pr].getEventString.call(this) + ":" + this.status; }; var pr = "prototype", p = $[pr], A = Array, ID = "__ID__", D = window['$document'] || document; var extend = function (child, parent) { var P = function () {}; P.prototype = parent.prototype; child.prototype = new P(); child.prototype.constructor = child; }; ///--- var Move = function (e, finger, history) { this.init(e); this.type = "move"; this.startCoordinates = Move.getStartCoordinates(history); this.coordinates = Move.getCoordinates(finger); this.startTime = history.touch.time; this.lastTime = Date.now(); this.currentDistance(history); this.currentSpeed(history); this.initSwipeSpeed(history); }; extend(Move, BaseEvent); Move[pr].currentDistance = function (history) { this.distanceX = this.coordinates.x - this.startCoordinates.x; this.distanceY = this.coordinates.y - this.startCoordinates.y; this.distance = Math.sqrt(Math.pow(this.distanceX, 2) + Math.pow(this.distanceY, 2)); if (history.move) { this.lastDistanceX = this.distanceX - history.move.distanceX; this.lastDistanceY = this.distanceY - history.move.distanceY; this.lastDistance = this.distance - history.move.distance; } else { this.lastDistance = 0; this.lastDistanceX = 0; this.lastDistanceY = 0; } }; Move[pr].currentSpeed = function(history) { var allTime = this.lastTime - this.startTime, localTime; this.speedX = this.distanceX / allTime; this.speedY = this.distanceY / allTime; this.speed = this.distance / allTime; if (history.move) { localTime = this.lastTime - history.move.lastTime; this.lastSpeedX = this.lastDistanceX / localTime; this.lastSpeedY = this.lastDistanceY / localTime; this.lastSpeed = this.lastDistance / localTime; } else { this.lastSpeed = 0; this.lastDistanceX = 0; this.lastDistanceY = 0; } }; Move[pr].initSwipeSpeed = function (history) { if (history.move && history.move.hasSwipeSpeed) { this.hasSwipeSpeed = true; } else { this.hasSwipeSpeed = this.lastSpeed > Move.swipeSpeed; } }; Move.getStartCoordinates = function (history) { return { x: history.touch.coordinates.x, y: history.touch.coordinates.y } }; Move.getCoordinates = function (finger) { return { x: finger.pageX, y: finger.pageY } }; Move.swipeSpeed = 0.5; var pr = "prototype", p = $[pr], A = Array, ID = "__ID__", D = window['$document'] || document; var extend = function (child, parent) { var P = function () {}; P.prototype = parent.prototype; child.prototype = new P(); child.prototype.constructor = child; }; ///--- var Swipe = function (e, finger, history) { this.init(e); this.type = "swipe"; this.direction = "left"; this.startCoordinates = Swipe.getStartCoordinates(history); this.vector = Swipe.getVector(finger, history); this.isHorizontal = Swipe.isHorizontal(this.vector); if (this.isHorizontal) { this.direction = Swipe.getDirection(this.vector.x, "left", "right"); } else { this.direction = Swipe.getDirection(this.vector.y, "up", "down"); } }; extend(Swipe, BaseEvent); Swipe[pr].getEventString = function () { return BaseEvent.prototype.getEventString.call(this) + ":" + (this.isHorizontal ? "horizontal:" : "vertical:") + this.direction; }; Swipe.getStartCoordinates = function (history) { return { x: history.touch.coordinates.x, y: history.touch.coordinates.y }; }; Swipe.getVector = function (finger, history) { return { x: finger.pageX - history.touch.coordinates.x, y: finger.pageY - history.touch.coordinates.y }; }; Swipe.isHorizontal = function (vector) { return (Math.abs(vector.x) / Math.abs(vector.y || 0.00001) > Swipe.horizontalFactor); }; Swipe.getDirection = function (vector, direction1, direction2) { if (vector < 0) { return direction1; } else { return direction2; } }; Swipe.horizontalFactor = 2/3; var pr = "prototype", p = $[pr], A = Array, ID = "__ID__", D = window['$document'] || document; var extend = function (child, parent) { var P = function () {}; P.prototype = parent.prototype; child.prototype = new P(); child.prototype.constructor = child; }; ///--- var Tap = function (e, finger) { this.init(e); this.type = "tap"; this.coordinates = { x: finger.pageX, y: finger.pageY }; this.time = finger.time; }; extend(Tap, BaseEvent); var pr = "prototype", p = $[pr], A = Array, ID = "__ID__", D = window['$document'] || document; var extend = function (child, parent) { var P = function () {}; P.prototype = parent.prototype; child.prototype = new P(); child.prototype.constructor = child; }; ///--- var MultiTouch = function (e, firstFinger, secondFinger, history) { this.startDistance = 0; this.distance = 0; this.deltaDistance = 0; this.angle = 0; this.deltaAngle = 0; this.zoom = 1; this.deltaZoom = 0; this.init(e); this.type = "multiTouch"; this.vector = { x: secondFinger.pageX - firstFinger.pageX, y: secondFinger.pageY - firstFinger.pageY }; this.distance = Math.sqrt(Math.pow(this.vector.x, 2) + Math.pow(this.vector.y, 2)); this.angle = Math.atan(this.vector.y / this.vector.x) * 180 / Math.PI; if (history) { this.startDistance = history.startDistance; this.deltaAngle = this.angle - history.angle; this.deltaDistance = this.distance - history.distance; this.zoom = this.distance / this.startDistance; this.deltaZoom = this.zoom - history.zoom; } else { this.startDistance = this.distance; } }; extend(MultiTouch, BaseEvent); E[pr] = ep; /** * Подписываемся на событие * @param {string} eventName * @param {function} handler * @param {*} [context] */ ep.on = function (eventName, handler, context) { if (!this._events) this._events = {}; if (!this._ID) { this._ID = $._add(this); this._node[ID] = this._ID; } if (!this._events[eventName]) this._events[eventName] = []; var event_obj = { event: eventName, handler: handler, context: context || new $(this) }; this._events[eventName].push(event_obj); if (eventName.indexOf("User") != 0) { var $handler = function (event) { return handler.call(context || this, event); }; event_obj.originHandler = $handler; this._node.addEventListener(eventName, $handler, false); } else { if (!this._hasCustom) { this._addCustom(); } } }; /** * Отписываемся от события * @param {string} [eventName] * @param {function} [handler] * @returns {ep} */ ep.off = function (eventName, handler) { if (!this._events) return this; $.forEach(this._events, function (events, $eventName) { if (!eventName || eventName == $eventName) { events = events.filter(function (eventObject) { if (!handler || handler == eventObject.handler) { this._node.removeEventListener($eventName, eventObject.originHandler || eventObject.handler); return false; } else { return true; } }, this); } if (events.length == 0) { delete this._events[$eventName]; } }, this); if (this._hasCustom && !$.some(this._events, function (events, eventName) { return eventName.indexOf("User") == 0; })) { this._removeCustom(); } if (!Object.keys(this._events).length) { $._remove(this._ID); this._node[ID] = null; this._ID = null; } }; /** * Запускаем событие * @param {string} eventName * @param {Array} [args] * @returns {ep} */ ep.trigger = function (eventName, args) { if (!this._events) return this; if (!eventName) { console.log("Неверные параметры!"); return this; } if (!args) args = []; if (!A.isArray(args)) args = [args]; E._splitEvents(eventName).forEach(function (event, index) { if (this._events[event]) { this._startUserEvent(event, E._currentArgs(eventName, index, args.slice())); } }, this); return this; }; /** * Не забываем снять все обрботчики с убиваемого элемента * @private */ ep._remove = function () { this.off(); }; /** * Запускаем событие (для trigger) * @param {string} event * @param {Array} localArgs * @private */ ep._startUserEvent = function (event, localArgs) { this._events[event].forEach(function (eventObject) { eventObject.handler.apply(eventObject.context, localArgs); }); }; /** * Добавляем приватные обработчики для создания тач событий * @private */ ep._addCustom = function () { this._hasCustom = true; var $this = this; /** * @param {IqueryEvent} e * @private */ this._start = function (e) { e.preventDefault(); $this._onStart(e); }; this._node.addEventListener($.events.start, this._start, false); }; /** * Обрабатываем прикосновение * @param {IqueryEvent} e * @private */ ep._onStart = function (e) { var $this = this; E._fingers = E._fingers.concat(E._getTouches(e, true)); this._createTouchEvent(e, E._fingers.slice(), "start"); /** * Функция для подписки на движение пальца * @param {IqueryEvent} e */ var move = function (e) { e.preventDefault(); $this._onMove(e); }; /** * Функция для подписки на отрыв пальца * @param {IqueryEvent} e */ var end = function (e) { e.preventDefault(); $this._onEnd(e); if (!E._fingers.length) { D.removeEventListener($.events.move, move); D.removeEventListener($.events.end, end); $this.__hasEvents = false; } }; if (!this.__hasEvents) { D.addEventListener($.events.move, move, false); D.addEventListener($.events.end, end, false); this.__hasEvents = true; } }; /** * Обрабатываем движение пальца * @param {IqueryEvent} e * @private */ ep._onMove = function (e) { var fingers = E._getFingers(e); if (fingers.length == 1) { this._createMoveEvent(e, fingers); } else { this._createMultitouch(e, fingers); } }; /** * Обрабатываем отрыв пальца * @param {IqueryEvent} e * @private */ ep._onEnd = function (e) { var touches = E._getTouches(e, true); var fingers = E._getFingers(e, touches, true); this._createSwipe(e, fingers); this._createTapEvent(e, fingers); this._createTouchEvent(e, fingers, "end"); E._clearEvents(fingers); E._fingers = E._fingers.filter(function (finger) { return !$.some(touches, E._getFingerById, E, finger.identifier); }); }; /** * Создаем событие прикосновения * @param {IqueryEvent} e * @param {Array} fingers массив пальцев * @param {string} state * @private */ ep._createTouchEvent = function (e, fingers, state) { fingers.forEach(function (finger) { this._startEvent(new Touch(e, finger, state), finger); }, this); }; /** * Создаем событие движения * @param {IqueryEvent} e * @param {Array} fingers * @private */ ep._createMoveEvent = function (e, fingers) { var finger = fingers[0]; this._startEvent(new Move(e, finger, E._Event.fingers[finger.identifier]), finger); }; /** * Создаем мультитач событие * @param {IqueryEvent} e * @param {Array} fingers * @private */ ep._createMultitouch = function (e, fingers) { fingers = fingers.sort(function (a, b) { return a.time - b.time }); this._startEvent(new MultiTouch(e, fingers[0], fingers[1], E._Event.multitouch)); }; /** * Создаем тап событие * @param {IqueryEvent} e * @param {Array} fingers * @private */ ep._createTapEvent = function (e, fingers) { fingers.forEach(function (finger) { if (E._isTap(finger)) { this._startEvent(new Tap(e, finger), finger); } }, this); }; /** * Создаем свайп событие * @param {IqueryEvent} e * @param {Array} fingers * @private */ ep._createSwipe = function (e, fingers) { fingers.forEach(function (finger) { if (E._isSwipe(finger)) { this._startEvent(new Swipe(e, finger, E._Event.fingers[finger.identifier]), finger); } }, this); }; /** * Отписываемся от приватных событий * @private */ ep._removeCustom = function () { this._hasCustom = false; this._node.removeEventListener($.events.start, this._start); }; /** * Запускаем событие * @param EVENT * @param [finger] * @private */ ep._startEvent = function (EVENT, finger) { if (!finger) { E._Event.multitouch = EVENT; } else { if (!E._Event.fingers[finger.identifier]) E._Event.fingers[finger.identifier] = {}; E._Event.fingers[finger.identifier][EVENT.type] = EVENT; } this.trigger(EVENT.getEventString(), [EVENT.getClone()]); }; /** * Проверяем надо ли запускать тап для этого пальца * @param finger * @returns {boolean} * @private */ E._isTap = function (finger) { if (!E._Event.fingers[finger.identifier]) return false; if (!E._Event.fingers[finger.identifier].touch) return E._message("Нет тача!", "warn"); if (E._Event.fingers[finger.identifier].move && E._Event.fingers[finger.identifier].move.distance > 15) return false; return (Date.now() - E._Event.fingers[finger.identifier].touch.time < E._tapTime); }; /** * Проверяем надо ли запускать свайп для этого пальца * @param finger * @returns {boolean} * @private */ E._isSwipe = function (finger) { return ((E._Event.fingers[finger.identifier]) && (E._Event.fingers[finger.identifier].move) && (E._Event.fingers[finger.identifier].move.distance > 30) && (E._Event.fingers[finger.identifier].move.hasSwipeSpeed) && (Date.now() - E._Event.fingers[finger.identifier].touch.time < E._tapTime)); }; /** * Получаем список пальцев из события * @param {IqueryEvent} e * @param {boolean} [startOrEnd] * @returns {Array} * @private */ E._getTouches = function (e, startOrEnd) { var result = []; if ($.isPointer) { if (!e.pointerId) return E._message("Нет идентификатора пальца!"); result.push(E._getFingerData(e)); } else if (e.touches) { var touches = startOrEnd ? e.changedTouches : e.touches; result = A[pr].map.call(touches, function (touch) { return E._getFingerData(touch); }); } else { result.push(E._getFingerData(e)); } return result; }; /** * Получаем список пальцев * @param {IqueryEvent} e * @param {Array} [fingers] * @param {boolean} [isEnd] * @returns {Array} * @private */ E._getFingers = function (e, fingers, isEnd) { var result; fingers = fingers || E._getTouches(e); if (isEnd) { result = E._fingers.filter(function (finger) { return $.some(fingers, E._getFingerById, E, finger.identifier); }); } E._fingers = E._fingers.map(function (finger) { var fingerData = $.findFirst(result || fingers, E._getFingerById, E, finger.identifier); if (fingerData.id != null) { return E._getFingerData(fingerData.value, finger.time); } else { return finger; } }); return result || E._fingers.slice(); }; /** * Функция для итератора из статики $ (проверяем наличие пальца в E._fingers) * @param finger * @param index * @param id * @returns {boolean} * @private */ E._getFingerById = function (finger, index, id) { return finger.identifier == id; }; /** * Активные пальцы на экране * @type {Array} * @private */ E._fingers = []; /** * Вывадит сообщение в лог * @param {string} message * @param {string} [type] * @param {*} [returns] * @returns {*} * @private */ E._message = function (message, type, returns) { console[type || "error"](message); return returns || false; }; /** * Время на тап * @type {number} * @private */ E._tapTime = 300; E._Event = { multitouch: null, fingers: {} }; /** * Очищаем события * @private */ E._clearEvents = function (fingers) { if (fingers.length == 1) { E._Event.multitouch = null; } fingers.forEach(function (finger) { delete E._Event.fingers[finger.identifier]; }); }; /** * Получаем данные по событию * @param data * @param [time] * @returns {{time: (*|number|Date), identifier: (*|number), pageX: (*|number|Number), pageY: (*|number|Number), target: (*|HTMLElement|string|Node|EventTarget)}} * @private */ E._getFingerData = function (data, time) { return { time: time || data.timeStamp || Date.now(), identifier: data.identifier || data.pointerId || 0, pageX: data.pageX, pageY: data.pageY, target: data.target } }; /** * Рассчитываем аргументы для trigger * @param {string} eventName * @param {number} index * @param {Array} args * @returns {Array} * @private */ E._currentArgs = function (eventName, index, args) { var arr = eventName.split(":"); arr.splice(0, index + 1); return arr.concat(args); }; /** * Получаем список событий для запуска для trigger * @param {string} eventName * @returns {Array} * @private */ E._splitEvents = function (eventName) { var events = eventName.split(":"), result = []; for (var i = 0; i < events.length; i++) { result.push(events.slice(0, i + 1).join(":")); } return result; }; /** * Получаем обёртку над элементом * @param node * @returns {*} * @private */ E._createE = function (node) { return $._getById(node[ID]) || new E(node); }; $._elems = {}; $._add = function (element) { var uuid; while (!(uuid && !(uuid in this._elems))) { uuid = $.guuid(); } this._elems[uuid] = element; return uuid; }; $._remove = function (uuid) { delete this._elems[uuid]; }; $._getById = function (uuid) { return this._elems[uuid] || null; }; ["on", "off", "trigger"].forEach(function (method) { p[method] = function () { return this._toAll(method, A[pr].slice.call(arguments)); } }); }); })(window["$window"] || window, window["$document"] || document); (function (W, D) { $.addPlugin(function ($, E) { "use strict"; // a CSSMatrix shim // http://www.w3.org/TR/css3-3d-transforms/#cssmatrix-interface // http://www.w3.org/TR/css3-2d-transforms/#cssmatrix-interface /** * CSSMatrix Shim * @constructor */ var CSSMatrix = function(){ var a = [].slice.call(arguments), m = this; if (a.length) for (var i = a.length; i--;){ if (Math.abs(a[i]) < CSSMatrix.SMALL_NUMBER) a[i] = 0; } m.setIdentity(); if (a.length == 16){ m.m11 = m.a = a[0]; m.m12 = m.b = a[1]; m.m13 = a[2]; m.m14 = a[3]; m.m21 = m.c = a[4]; m.m22 = m.d = a[5]; m.m23 = a[6]; m.m24 = a[7]; m.m31 = a[8]; m.m32 = a[9]; m.m33 = a[10]; m.m34 = a[11]; m.m41 = m.e = a[12]; m.m42 = m.f = a[13]; m.m43 = a[14]; m.m44 = a[15]; } else if (a.length == 6) { this.affine = true; m.m11 = m.a = a[0]; m.m12 = m.b = a[1]; m.m14 = m.e = a[4]; m.m21 = m.c = a[2]; m.m22 = m.d = a[3]; m.m24 = m.f = a[5]; } else if (a.length === 1 && typeof a[0] == 'string') { m.setMatrixValue(a[0]); } else if (a.length > 0) { throw new TypeError('Invalid Matrix Value'); } }; // decimal values in WebKitCSSMatrix.prototype.toString are truncated to 6 digits CSSMatrix.SMALL_NUMBER = 1e-6; // Transformations // http://en.wikipedia.org/wiki/Rotation_matrix CSSMatrix.Rotate = function(rx, ry, rz){ rx *= Math.PI / 180; ry *= Math.PI / 180; rz *= Math.PI / 180; // minus sin() because of right-handed system var cosx = Math.cos(rx), sinx = - Math.sin(rx); var cosy = Math.cos(ry), siny = - Math.sin(ry); var cosz = Math.cos(rz), sinz = - Math.sin(rz); var m = new CSSMatrix(); m.m11 = m.a = cosy * cosz; m.m12 = m.b = - cosy * sinz; m.m13 = siny; m.m21 = m.c = sinx * siny * cosz + cosx * sinz; m.m22 = m.d = cosx * cosz - sinx * siny * sinz; m.m23 = - sinx * cosy; m.m31 = sinx * sinz - cosx * siny * cosz; m.m32 = sinx * cosz + cosx * siny * sinz; m.m33 = cosx * cosy; return m; }; CSSMatrix.RotateAxisAngle = function(x, y, z, angle){ angle *= Math.PI / 360; var sinA = Math.sin(angle), cosA = Math.cos(angle), sinA2 = sinA * sinA; var length = Math.sqrt(x * x + y * y + z * z); if (length === 0){ // bad vector length, use something reasonable x = 0; y = 0; z = 1; } else { x /= length; y /= length; z /= length; } var x2 = x * x, y2 = y * y, z2 = z * z; var m = new CSSMatrix(); m.m11 = m.a = 1 - 2 * (y2 + z2) * sinA2; m.m12 = m.b = 2 * (x * y * sinA2 + z * sinA * cosA); m.m13 = 2 * (x * z * sinA2 - y * sinA * cosA); m.m21 = m.c = 2 * (y * x * sinA2 - z * sinA * cosA); m.m22 = m.d = 1 - 2 * (z2 + x2) * sinA2; m.m23 = 2 * (y * z * sinA2 + x * sinA * cosA); m.m31 = 2 * (z * x * sinA2 + y * sinA * cosA); m.m32 = 2 * (z * y * sinA2 - x * sinA * cosA); m.m33 = 1 - 2 * (x2 + y2) * sinA2; m.m14 = m.m24 = m.m34 = 0; m.m41 = m.e = m.m42 = m.f = m.m43 = 0; m.m44 = 1; return m; }; CSSMatrix.ScaleX = function(x){ var m = new CSSMatrix(); m.m11 = m.a = x; return m; }; CSSMatrix.ScaleY = function(y){ var m = new CSSMatrix(); m.m22 = m.d = y; return m; }; CSSMatrix.ScaleZ = function(z){ var m = new CSSMatrix(); m.m33 = z; return m; }; CSSMatrix.Scale = function(x, y, z){ var m = new CSSMatrix(); m.m11 = m.a = x; m.m22 = m.d = y; m.m33 = z; return m; }; CSSMatrix.SkewX = function(angle){ angle *= Math.PI / 180; var m = new CSSMatrix(); m.m21 = m.c = Math.tan(angle); return m; }; CSSMatrix.SkewY = function(angle){ angle *= Math.PI / 180; var m = new CSSMatrix(); m.m12 = m.b = Math.tan(angle); return m; }; CSSMatrix.Translate = function(x, y, z){ var m = new CSSMatrix(); m.m41 = m.e = x; m.m42 = m.f = y; m.m43 = z; return m; }; CSSMatrix.multiply = function(m1, m2){ var m11 = m2.m11 * m1.m11 + m2.m12 * m1.m21 + m2.m13 * m1.m31 + m2.m14 * m1.m41, m12 = m2.m11 * m1.m12 + m2.m12 * m1.m22 + m2.m13 * m1.m32 + m2.m14 * m1.m42, m13 = m2.m11 * m1.m13 + m2.m12 * m1.m23 + m2.m13 * m1.m33 + m2.m14 * m1.m43, m14 = m2.m11 * m1.m14 + m2.m12 * m1.m24 + m2.m13 * m1.m34 + m2.m14 * m1.m44, m21 = m2.m21 * m1.m11 + m2.m22 * m1.m21 + m2.m23 * m1.m31 + m2.m24 * m1.m41, m22 = m2.m21 * m1.m12 + m2.m22 * m1.m22 + m2.m23 * m1.m32 + m2.m24 * m1.m42, m23 = m2.m21 * m1.m13 + m2.m22 * m1.m23 + m2.m23 * m1.m33 + m2.m24 * m1.m43, m24 = m2.m21 * m1.m14 + m2.m22 * m1.m24 + m2.m23 * m1.m34 + m2.m24 * m1.m44, m31 = m2.m31 * m1.m11 + m2.m32 * m1.m21 + m2.m33 * m1.m31 + m2.m34 * m1.m41, m32 = m2.m31 * m1.m12 + m2.m32 * m1.m22 + m2.m33 * m1.m32 + m2.m34 * m1.m42, m33 = m2.m31 * m1.m13 + m2.m32