ts-query
Version:
its simple library for dom control.
1,824 lines (1,590 loc) • 78.9 kB
JavaScript
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