// Generated by CoffeeScript 2.0.0-beta4
(function() {
// 主要的選擇器函式。
var ts;
ts = function(selector, context) {
var nodes, ref, tag;
nodes = [];
// 如果選擇器是文字,但是是標籤(如:`
`)就建立新的元素
if (typeof selector === 'string' && selector[0] === '<') {
tag = selector.match(/<(.*)\/>|<(.*)>/);
nodes = [document.createElement((ref = tag[1]) != null ? ref : tag[2])];
// 如果選擇器是一般的文字,就選取元素。
} else if (typeof selector === 'string' && context === void 0) {
document.querySelectorAll(selector).forEach(function(element) {
return nodes.push(element);
});
// 如果選擇器有上下文選擇器,就透過選擇器找出上下文元素。
} else if (typeof context === 'string') {
nodes = ts(selector).find(context).toArray();
// 如果選擇器是 NodeList 就轉換成元素陣列然後取出來接著繼續。
} else if (selector instanceof NodeList) {
selector.forEach(function(element) {
return nodes.push(element);
});
// 如果選擇器是陣列,就當作是元素陣列,取出來然後繼續。
// 或傳入的是一個選擇器,就取出裡面的元素然後繼續。
} else if (Array.isArray(selector) || (selector != null ? selector.isSelector : void 0) === true) {
nodes = nodes.concat(selector);
selector = selector.selector;
context = selector != null ? selector.context : void 0;
// 如果是單個 DOM 元素,就放入選擇器然後繼續。
} else if (selector instanceof HTMLElement || selector instanceof HTMLDocument || selector instanceof HTMLBodyElement || selector === window) {
nodes = [selector];
}
// 保存目前的選擇器文字與上下文選擇器文字。
nodes.selector = typeof selector === 'string' ? selector : null;
nodes.context = typeof context === 'string' ? context : null;
// 將自訂的選擇器方法插入到節點陣列中,這樣才能夠串連使用。
Object.defineProperties(nodes, ts.fn);
// 將節點陣列標註為是選擇器,這樣才能判斷傳入的是不是我們自己的選擇器。
Object.defineProperty(nodes, 'isSelector', {
value: true
});
return nodes;
};
// 註冊到視窗上。
window.ts = ts;
// 函式鏈。
ts.fn = {};
// 輔助函式。
ts.helper = {};
// 事件輔助函式。
ts.helper.eventAlias = function(event) {
var alias, pair;
pair = event.split('.');
alias = pair[1] !== void 0 ? `.${pair[1]}` : '';
switch (false) {
case pair.indexOf('animationend') === -1:
return `webkitAnimationEnd${alias} mozAnimationEnd${alias} MSAnimationEnd${alias} oanimationend${alias} animationend${alias}`;
case pair.indexOf('transitionend') === -1:
return `webkitTransitionEnd${alias} mozTransitionEnd${alias} oTransitionEnd${alias} msTransitionEnd${alias} transitionend${alias}`;
default:
return event;
}
};
// 是否為物件。
ts.isPlainObject = function(object) {
return Object.prototype.toString.call(object) === '[object Object]';
};
// 是否為可觸控裝置。
ts.isTouchDevice = function() {
return 'ontouchstart' in window || navigator.maxTouchPoints;
};
// 延展物件的函式,與 ES 的 `...` 不同之處在於 extend 並不會替換掉整個子物件,而會以補插的方式執行。
// https://gomakethings.com/vanilla-javascript-version-of-jquery-extend/
ts.extend = function() {
var deep, extended, i, length, merge, obj;
extended = {};
deep = true;
i = 0;
length = arguments.length;
if (Object.prototype.toString.call(arguments[0]) === '[object Boolean]') {
deep = arguments[0];
i++;
}
merge = function(obj) {
var prop;
for (prop in obj) {
if (Object.prototype.hasOwnProperty.call(obj, prop)) {
if (deep && Object.prototype.toString.call(obj[prop]) === '[object Object]') {
extended[prop] = ts.extend(true, extended[prop], obj[prop]);
} else {
extended[prop] = obj[prop];
}
}
}
};
while (i < length) {
obj = arguments[i];
merge(obj);
i++;
}
return extended;
};
// 建立元素
ts.createElement = (html) => {
var div;
div = document.createElement('div');
div.innerHTML = html.trim();
return div.firstChild;
};
// 註冊 Tocas 模塊
ts.register = ({NAME, MODULE_NAMESPACE, Settings}, starter) => {
return ts.fn[NAME] = {
value: function(parameters) {
var $allModules, consoleText, errorHeaderCSS, headerCSS, messageCSS, methodInvoked, query, queryArguments, returnedValue;
$allModules = ts(this);
query = arguments[0];
queryArguments = [].slice.call(arguments, 1);
methodInvoked = typeof query === 'string';
returnedValue = void 0;
consoleText = (args) => {
//currentdate = new Date();
//datetime = "#{currentdate.getFullYear()}/#{(currentdate.getMonth()+1)}/#{currentdate.getDate()}/@#{currentdate.getHours()}:#{currentdate.getMinutes()}:#{currentdate.getSeconds()}"
return `%c${NAME}%c ${args[0]}`;
};
headerCSS = "background : #EEE;\ncolor : #5A5A5A;\nfont-size : 1em;\npadding : 8px 8px;\nline-height : 5px;\nmargin : 5px 0 5px 0;\nborder-radius: 1000em;";
errorHeaderCSS = `${headerCSS}\nbackground: #CE5F58;\ncolor: #FFF;`;
messageCSS = "font-weight: bold;";
$allModules.each(function(_, index) {
var $this, debug, element, error, initialize, instance, instantiate, invoke, module, observeChanges, settings;
$this = ts(this);
element = this;
instance = $this.data(MODULE_NAMESPACE);
settings = ts.isPlainObject(parameters) ? ts.extend(Settings, parameters) : ts.extend(Settings);
debug = function() {
if (!settings.debug || settings.silent) {
return;
}
return console.info.call(console, consoleText(arguments), headerCSS, messageCSS, "\n", ...Array.prototype.slice.call(arguments).slice(1));
};
error = function() {
if (settings.silent) {
return;
}
error = Function.prototype.bind.call(console.error, console, consoleText(arguments), errorHeaderCSS, messageCSS);
return error.apply(console, Array.prototype.slice.call(arguments, 1));
};
instantiate = () => {
module.instantiate();
instance = module;
return $this.data(MODULE_NAMESPACE, instance);
};
initialize = () => {
module.initialize();
if (settings.observeChanges) {
observeChanges();
}
return instantiate();
};
observeChanges = () => {
var observer;
if (!'MutationObserver' in window) {
debug('找不到樹狀結構變更觀測者,略過結構監聽動作', element);
return;
}
observer = new MutationObserver((mutations) => {
//debug 'DOM 樹狀結構已變更,更新快取資料'
return module.refresh();
});
return observer.observe(element, {
childList: true,
subtree: true
});
};
//debug '已設置 DOM 樹狀結構異動觀察者', observer
invoke = (query, passedArguments, context) => {
var camelCaseValue, depth, found, j, len, maxDepth, object, response, value;
object = instance;
maxDepth = void 0;
found = void 0;
response = void 0;
passedArguments = passedArguments || queryArguments;
context = element || context;
if (typeof query === 'string' && object !== void 0) {
query = query.split(/[\. ]/);
maxDepth = query.length - 1;
for (depth = j = 0, len = query.length; j < len; depth = ++j) {
value = query[depth];
camelCaseValue = query;
if (depth !== maxDepth) {
camelCaseValue = value + query[depth + 1].charAt(0).toUpperCase() + query[depth + 1].slice(1);
}
switch (false) {
case !(ts.isPlainObject(object[camelCaseValue]) && depth !== maxDepth):
object = object[camelCaseValue];
break;
case object[camelCaseValue] === void 0:
found = object[camelCaseValue];
break;
case !(ts.isPlainObject(object[value]) && depth !== maxDepth):
object = object[value];
break;
case object[value] === void 0:
found = object[value];
break;
default:
error('欲呼叫的方法並不存在', query);
break;
}
}
}
switch (false) {
case typeof found !== 'function':
response = found.apply(context, passedArguments);
break;
case found === void 0:
response = found;
}
switch (false) {
case response !== $allModules:
returnedValue = $allModules;
break;
default:
returnedValue = response;
}
return found;
};
module = starter({$allModules, $this, element, debug, settings, instance, index});
if (methodInvoked) {
if (instance === void 0) {
initialize();
}
return invoke(query);
} else {
if (instance !== void 0) {
invoke('destroy');
}
return initialize();
}
});
if (returnedValue !== void 0) {
return returnedValue;
} else {
return $allModules;
}
}
};
};
// Get
// 取得選擇器內的指定元素,並且回傳一個 DOM 元素而非選擇器。
ts.fn.get = {
value: function(index = 0) {
return this[index];
}
};
// ToArray
// 將選擇器轉換成帶有節點的一般陣列。
ts.fn.toArray = {
value: function() {
var array;
array = [];
this.forEach(function(element) {
return array.push(element);
});
return array;
}
};
// Each
// 遍歷整個選擇器陣列。
ts.fn.each = {
value: function(callback) {
this.forEach(function(element, index) {
return callback.call(element, element, index);
});
return this;
}
};
// CollectSwap
// 將收集到的元素替換掉目前選擇器內的所有元素。
ts.fn.collectSwap = {
value: function(callback) {
var collection, newSelector;
collection = [];
this.each(function(element, index) {
var result;
result = callback.call(element, element, index);
if (result === void 0 || result === null) {
return;
}
if (result instanceof NodeList) {
return result.forEach(function(el) {
return collection.push(el);
});
} else if (Array.isArray(result)) {
return collection = collection.concat(result);
} else {
if (collection.indexOf(result) === -1) {
return collection.push(result);
}
}
});
// 透過 Set 型態移除重複的節點。
collection = new Set(collection);
// 然後將 Set 轉換成陣列,建立新的選擇器。
newSelector = ts([...collection]);
// 保存選擇器之前的所有節點。
Object.defineProperty(newSelector, 'prevObject', {
value: this
});
// 回傳這個新的選擇器。
return newSelector;
}
};
// Eq
// 取得選擇器的指定元素,然後繼續回傳僅帶有該元素的選擇器。
ts.fn.eq = {
value: function(index) {
return ts(this.get(index));
}
};
// Parent
// 回傳元素的父元素選擇器。
ts.fn.parent = {
value: function() {
return this.collectSwap(function() {
return this.parentNode;
});
}
};
// Closest
// 回傳最接近指定的父元素選擇器。
ts.fn.closest = {
value: function(selector) {
return this.collectSwap(function() {
return this.closest(selector);
});
}
};
// Find
// 在目前元素中搜尋指定元素並回傳其選擇器。
ts.fn.find = {
value: function(selector) {
return this.collectSwap(function() {
return this.querySelectorAll(selector);
});
}
};
// Insert Before
// 將選擇器元素安插在指定元素前。
ts.fn.insertBefore = {
value: function(target) {
return this.each(function() {
return ts(target).each((element) => {
return element.parentNode.insertBefore(this, element);
});
});
}
};
// Insert After
// 將選擇器元素安插在指定元素後。
ts.fn.insertAfter = {
value: function(target) {
return this.each(function() {
return ts(target).each((element) => {
return element.parentNode.insertBefore(this, element.nextSibling);
});
});
}
};
// Wrap
// 將元素用指定元素包覆起來。
ts.fn.wrap = {
value: function(element) {
return this.each(function() {
if (this.nextSibling) {
this.parentNode.insertBefore(element, this.nextSibling);
} else {
this.parentNode.appendChild(element);
}
return element.appendChild(this);
});
}
};
// Clone
// 複製元素。
ts.fn.clone = {
value: function() {
return this.collectSwap(function() {
return this.cloneNode(true);
});
}
};
// Append
// 將元素插入在目前選擇器元素的內部最後面。
ts.fn.append = {
value: function(element) {
var shouldClone;
shouldClone = this.length !== 1;
if (element.isSelector !== void 0) {
return this.each(function() {
return element.each((e) => {
return this.appendChild(shouldClone ? e.cloneNode(true) : e);
});
});
} else if (typeof element === 'string') {
return this.each(function() {
return this.insertAdjacentHTML('beforeend', element);
});
} else {
return this.each(function() {
return this.appendChild(shouldClone ? element.cloneNode(true) : element);
});
}
}
};
// AppendTo
// 將目前選擇器元素插入到指定元素的內部最後面。
ts.fn.appendTo = {
value: function(selector) {
return this.each(function() {
return ts(selector).append(this);
});
}
};
// Prepend
// 將元素插入在目前選擇器元素的內部最前面。
ts.fn.prepend = {
value: function(element) {
var shouldClone;
shouldClone = this.length !== 1;
if (element.isSelector !== void 0) {
return this.each(function() {
return element.each((e) => {
return this.prepend(shouldClone ? e.cloneNode(true) : e);
});
});
} else if (typeof element === 'string') {
return this.each(function() {
return this.insertAdjacentHTML('afterbegin', element);
});
} else {
return this.each(function() {
return this.prepend(shouldClone ? element.cloneNode(true) : element);
});
}
}
};
// PrependTo
// 將目前選擇器元素插入到指定元素的內部最前面。
ts.fn.prependTo = {
value: function(selector) {
return this.each(function() {
return ts(selector).prepend(this);
});
}
};
// Remove
// 將選擇器元素從頁面上中移除。
ts.fn.remove = {
value: function() {
return this.each(function() {
var ref;
return (ref = this.parentNode) != null ? ref.removeChild(this) : void 0;
});
}
};
// Is
// 選擇一些元素,然後用來比對目前的選擇器元素是否在這群當中。
ts.fn.is = {
value: function(selector) {
var compareElements, isInElements;
compareElements = document.querySelectorAll(selector);
isInElements = false;
this.each(function() {
return compareElements.forEach(function(compareElement) {
if (this === compareElement) {
return isInElements = true;
}
}, this);
});
return isInElements;
}
};
// Contains
// 是否擁有指定子元素。
ts.fn.contains = {
value: function(selector) {
var ref;
return (ref = this.get(0)) != null ? ref.contains(ts(selector).get()) : void 0;
}
};
// Not
// 將指定元素從選擇器中剔除。
ts.fn.not = {
value: function(selector) {
return ts(this.toArray().filter((element) => {
return ts(selector).indexOf(element) === -1;
}));
}
};
// Slice
// 替元素陣列進行切分。
ts.fn.slice = {
value: function(from, to) {
return ts(this.toArray().slice(from, to));
}
};
// Children
// 取得容器裡的第一層子節點。
ts.fn.children = {
value: function(selector) {
return this.collectSwap(function() {
return this.querySelectorAll(selector != null ? `:scope > ${selector}` : ':scope > *');
});
}
};
// Replace With
// 將元素替換為指定選擇器元素。
ts.fn.replaceWith = {
value: function(selector) {
var element;
element = ts(selector).get();
return this.each(function() {
return this.replaceWith(element);
});
}
};
// Last
// 選擇器中的最後一個元素。
ts.fn.last = {
value: function() {
return this.eq(this.length - 1);
}
};
// Next
// 下一個元素。
ts.fn.next = {
value: function() {
return this.collectSwap(function() {
return this.nextElementSibling;
});
}
};
// Prev
// 上一個元素。
ts.fn.prev = {
value: function() {
return this.collectSwap(function() {
return this.previousElementSibling;
});
}
};
// NextAll
// 這個元素之後的所有同階層元素。
ts.fn.nextAll = {
value: function(selector) {
return this.collectSwap(function() {
var $children, $parent, $self, index;
$self = ts(this);
$parent = $self.parent();
$children = selector != null ? $parent.find(`:scope > ${selector}`) : $parent.find(':scope > *');
index = $self.index();
return $children.slice(index + 1);
});
}
};
// PrevAll
// 這個元素之前的所有同階層元素。
ts.fn.prevAll = {
value: function(selector) {
return this.collectSwap(function() {
var $children, $parent, $self, index;
$self = ts(this);
$parent = $self.parent();
$children = selector != null ? $parent.find(`:scope > ${selector}`) : $parent.find(':scope > *');
index = $self.index();
return $children.slice(0, index);
});
}
};
// AddBack
// 在目前的選擇器節點陣列中加上先前選擇的所有節點。
ts.fn.addBack = {
value: function() {
if (this.prevObject) {
this.prevObject.toArray().forEach((element) => {
return this.push(element);
});
}
return this;
}
};
// Index
// 該元素在容器內的索引。
ts.fn.index = {
value: function() {
var index, node;
node = this.get(0);
index = 0;
if (node == null) {
return -1;
}
while ((node = node.previousElementSibling)) {
index++;
}
return index;
}
};
// Attr
// 取得或是建立新的標籤到目前的選擇器元素。
ts.fn.attr = {
value: function(name, value) {
var ref;
// 如果有 value 就設置簡單鍵值資料。
if (value !== void 0) {
return this.each(function() {
return this.setAttribute(name, value);
});
// 如果傳入的是物件就設置多重資料。
} else if (typeof name === 'object') {
return this.each(function() {
var key, results;
results = [];
for (key in name) {
results.push(this.setAttribute(key, name[key]));
}
return results;
});
} else {
return (ref = this.get()) != null ? ref.getAttribute(name) : void 0;
}
}
};
// RemoveAttr
// 移除目前選擇器元素的指定標籤。
ts.fn.removeAttr = {
value: function(name) {
return this.each(function() {
return this.removeAttribute(name);
});
}
};
// AddClass
// 在目前選擇器元素插入新的樣式類別名稱。
ts.fn.addClass = {
value: function(names) {
var name, newNames;
if (typeof names === 'object') {
newNames = '';
for (name in names) {
if (names[name] === true) {
newNames += ` ${name}`;
}
}
names = newNames;
} else {
names = Array.prototype.slice.call(arguments).join(' ');
}
return this.each(function() {
return DOMTokenList.prototype.add.apply(this.classList, names.split(' ').filter(Boolean));
});
}
};
// RemoveClass
// 移除目前選擇器元素的指定樣式類別。
ts.fn.removeClass = {
value: function(names) {
var name, newNames;
if (typeof names === 'object') {
newNames = '';
for (name in names) {
if (names[name] === true) {
newNames += ` ${name}`;
}
}
names = newNames;
} else {
names = Array.prototype.slice.call(arguments).join(' ');
}
//console.log @
return this.each(function() {
return DOMTokenList.prototype.remove.apply(this.classList, names.split(' ').filter(Boolean));
});
}
};
// ToggleClass
// 切換目前選擇器元素的樣式。
ts.fn.toggleClass = {
value: function(names) {
return this.each(function() {
return names.split(' ').forEach(function(name) {
return this.classList.toggle(name);
}, this);
});
}
};
// HasClass
// 回傳選擇器元素是否帶有指定樣式類別,是布林值。
ts.fn.hasClass = {
value: function(name) {
var ref;
return (ref = this.get(0)) != null ? ref.classList.contains(name) : void 0;
}
};
// CSS
// 將選擇器元素套用指定的 CSS 樣式。
ts.fn.css = {
value: function(name, value) {
var key;
// 有 name 也有 value 就設置樣式。
if (typeof name === 'string' && value !== void 0) {
return this.each(function() {
return this.style[name] = value;
});
// 有 name 但沒有 value 就取得樣式。
} else if (typeof name === 'string' && value === void 0) {
if (this.get() != null) {
return document.defaultView.getComputedStyle(this.get(), null).getPropertyValue(name);
} else {
return null;
}
// 有 name 但他是 object,就設置多重樣式。
} else if (typeof name === 'object') {
for (key in name) {
this.each(function() {
return this.style[key] = name[key];
});
}
return this;
}
}
};
// Rect
// 回傳選擇器元素的渲染形狀。
ts.fn.rect = {
value: function() {
var ref;
return (ref = this.get(0)) != null ? ref.getBoundingClientRect() : void 0;
}
};
// On
// 綁定並註冊一個事件監聽器。
ts.fn.on = {
value: function() {
var data, events, handler, options, selector;
switch (arguments.length) {
// Event 與 Handler。
case 2:
events = arguments[0];
handler = arguments[1];
break;
// Event 與 Selector 與 Handler。
// Event 與 Data 與 Handler。
// Event 與 Handler 與 Options。
case 3:
events = arguments[0];
handler = arguments[2];
switch (typeof arguments[1]) {
case "string":
selector = arguments[1];
break;
case "function":
handler = arguments[1];
options = arguments[2];
break;
default:
data = arguments[1];
}
break;
// Event 與 Selector 與 Data 與 Handler。
// Event 與 Selector 與 Handler 與 Options。
case 4:
events = arguments[0];
selector = arguments[1];
handler = arguments[3];
switch (typeof arguments[2]) {
case "function":
handler = arguments[2];
options = arguments[3];
break;
default:
data = arguments[2];
}
break;
// Event 與 Selector 與 Data 與 Handler 與 Options。
case 5:
events = arguments[0];
selector = arguments[1];
data = arguments[2];
handler = arguments[3];
options = arguments[4];
}
events = ts.helper.eventAlias(events);
// $events.click =
// {
// anonymous: [
// {
// once : true,
// selector: ".button",
// data : {},
// func : func()
// }
// ]
// alias1: [
// {
// once : true,
// selector: ".button",
// data : {},
// func : func()
// }
// ]
// }
return this.each(function() {
if (this.addEventListener === void 0) {
return;
}
if (this.$events === void 0) {
this.$events = {};
}
return events.split(' ').forEach(function(eventName) {
var event, eventAlias, hasAlias;
event = eventName.split('.');
// 透過事件的「event.alias」取得「點」後面的別名。
hasAlias = event.length > 1;
eventName = event[0];
eventAlias = hasAlias ? event[1] : null;
// 如果事件還沒在這個物件內產生過,就初始化一個事件結構。
if (this.$events[eventName] === void 0) {
this.$events[eventName] = {
anonymous: []
};
// 然後建立一個管理多個事件的事件管理處理程式。
this.addEventListener(eventName, function(event) {
var alias, calledAlias, closest, context, hasArgs, index, ref, ref1, ref2, results, single;
// 是否有自訂參數。
hasArgs = ((ref = event.detail) != null ? (ref1 = ref.args) != null ? ref1.length : void 0 : void 0) > 0;
// 是否有呼叫事件別名。
calledAlias = (ref2 = event.detail) != null ? ref2.alias : void 0;
// 如果該事件已經被移除則停止後續的反應。
if (this.$events[eventName] === void 0) {
return;
}
results = [];
// 將被觸發的事件裡面的所有處理程式全部呼叫一次。
for (alias in this.$events[eventName]) {
if (calledAlias && calledAlias !== alias) {
continue;
}
index = this.$events[eventName][alias].length;
results.push((function() {
var results1;
results1 = [];
while (index--) {
if (this.$events[eventName] === void 0) {
continue;
}
if (this.$events[eventName][alias] === void 0) {
continue;
}
single = this.$events[eventName][alias][index];
// 設置事件的上下文。
context = this;
// 如果這個事件有選擇器的話,則使用該選擇器為主。
if (single.selector !== void 0) {
selector = single.selector;
closest = ts(event.target).closest(selector);
// 如果找不到指定選擇棄的元素,就不要觸發此事件。
if (closest.length === 0) {
continue;
} else {
// 替換上下文為選擇器元素。
context = closest.get();
}
}
// 將事件預資料放入事件中供處理函式取得。
event.data = single.data;
if (hasArgs) {
single.func.call(context, event, ...event.detail.args);
} else {
single.func.call(context, event);
}
// 如果這個程式只能被呼叫一次就在處理程式呼叫後移除。
if (single.once === true) {
results1.push(this.$events[eventName][alias].splice(index, 1));
} else {
results1.push(void 0);
}
}
return results1;
}).call(this));
}
return results;
});
}
// 將新的事件處理程式註冊到事件清單中。
// 如果有別名,就不要推送到匿名陣列中,我們替這個別名另開物件。
if (hasAlias) {
if (this.$events[eventName][eventAlias] === void 0) {
this.$events[eventName][eventAlias] = [];
}
return this.$events[eventName][eventAlias].push({
func: handler,
selector: selector,
data: data,
once: options != null ? options.once : void 0
});
} else {
// 如果沒有,就照常推進匿名陣列中。
return this.$events[eventName].anonymous.push({
func: handler,
selector: selector,
data: data,
once: options != null ? options.once : void 0
});
}
}, this);
});
}
};
// One
// 綁定一次性的事件監聽器,當被觸發之後就會被移除。
ts.fn.one = {
value: function(events, handler) {
events = ts.helper.eventAlias(events);
return this.each(function() {
return ts(this).on(events, handler, {
once: true
});
});
}
};
// Off
// 註銷事件監聽器。
ts.fn.off = {
value: function(events, handler) {
events = ts.helper.eventAlias(events);
return this.each(function() {
if (this.$events === void 0) {
return;
}
return events.split(' ').forEach((eventName) => {
var alias, aliasName, event, hasAlias, isAlias, results;
// 將事件名稱由中間的「.」切成兩半。
event = eventName.split('.');
// 如果事件開頭是「.」符號,表示這是個別名,不是事件名稱。
isAlias = eventName[0] === '.';
// 如果事件分切後有兩個項目,表示這個事件有別名。
hasAlias = event.length === 2 && event[0] !== '';
if (hasAlias || isAlias) {
// 如果有別名的話,取得別名。
aliasName = event[1];
}
// 如果此事件不是只有別名的話,取得事件名稱。
eventName = !isAlias ? event[0] : void 0;
switch (false) {
// 當有指定監聽函式時。
case !(handler !== void 0 && this.$events[eventName] !== void 0):
return this.$events[eventName].anonymous.forEach((item, index) => {
if (handler === item.func) {
return this.$events[eventName].anonymous.splice(index, 1);
}
});
// 當本事件名稱不僅是別名時。
case !(!isAlias && hasAlias && this.$events[eventName] !== void 0):
// 移除指定事件的別名監聽函式。
return delete this.$events[eventName][aliasName];
// 當僅有指定別名時。
case !(isAlias && !hasAlias):
results = [];
// 移除所有與此別名有關的事件監聽器。
for (event in this.$events) {
results.push((function() {
var results1;
results1 = [];
for (alias in this.$events[event]) {
if (aliasName === alias) {
results1.push(delete this.$events[event][aliasName]);
} else {
results1.push(void 0);
}
}
return results1;
}).call(this));
}
return results;
break;
// 當僅有指定事件名稱時。
case this.$events[eventName] === void 0:
// 清空該事件的所有事件監聽器。
return delete this.$events[eventName];
}
}, this);
});
}
};
// Trigger
// 觸發指定事件。
ts.fn.trigger = {
value: function(events) {
var customArguments;
events = ts.helper.eventAlias(events);
customArguments = [].slice.call(arguments, 1);
return this.each(function() {
return events.split(' ').forEach((eventName) => {
var alias, event, name;
event = eventName.split('.');
name = event[0];
alias = event.length > 1 ? event[1] : null;
event = new CustomEvent(name, {
detail: {
args: customArguments,
alias: alias
}
});
return this.dispatchEvent(event);
});
});
}
};
// Emulate
// 在指定的秒數過後觸發指定事件,若已被觸發則不再次觸發。
// 這能用以強迫讓某個事件發生。
ts.fn.emulate = {
value: function(event, duration) {
return this.each(function() {
var called;
called = false;
ts(this).one(event, function() {
return called = true;
});
return setTimeout(() => {
if (!called) {
return ts(this).trigger(event);
}
}, duration);
});
}
};
// Text
// 變更或取得選擇器元素的內容文字。
ts.fn.text = {
value: function(text) {
var ref;
if (text !== void 0) {
return this.each(function() {
return this.innerText = text;
});
} else {
return (ref = this.get()) != null ? ref.innerText : void 0;
}
}
};
// Val
// 變更或取得選擇器元素的值。
ts.fn.val = {
value: function(value) {
var ref;
if (value !== void 0) {
return this.each(function() {
return this.value = value;
});
} else {
return (ref = this.get()) != null ? ref.value : void 0;
}
}
};
// HTML
// 變更或取得選擇器元素的 HTML。
ts.fn.html = {
value: function(html) {
var ref;
if (html !== void 0) {
return this.each(function() {
return this.innerHTML = html;
});
} else {
return (ref = this.get()) != null ? ref.innerHTML : void 0;
}
}
};
// Empty
// 將選擇器元素的內容清除,例如值或文字。
ts.fn.empty = {
value: function() {
return this.each(function() {
if (this.value !== void 0) {
this.value = null;
}
if (this.innerHTML !== void 0) {
this.innerHTML = null;
}
if (this.innerText !== void 0) {
return this.innerText = null;
}
});
}
};
// Prop
// 變更或取得選擇器元素的屬性,例如 `.src`、`.width`。
ts.fn.prop = {
value: function(name, value) {
var key, ref;
// 有 name 也有 value 就設置屬性。
if (typeof name === 'string' && value !== void 0) {
return this.each(function() {
return this[name] = value;
});
// 有 name 但沒有 value 就取得屬性。
} else if (typeof name === 'string' && value === void 0) {
return (ref = this.get()) != null ? ref[name] : void 0;
// 有 name 但他是 object,就設置多重屬性。
} else if (typeof name === 'object') {
for (key in name) {
this.each(function() {
return this[key] = name[key];
});
}
return this;
}
}
};
// Data
// 在選擇器元素中存放資料,類似 Attr 但頁面不可見。
ts.fn.data = {
value: function(name, value) {
var key, ref, ref1;
// 有 name 也有 value 就設置資料。
if (typeof name === 'string' && value !== void 0) {
return this.each(function() {
if (this.$data === void 0) {
this.$data = {};
}
return this.$data[name] = value;
});
// 有 name 但沒有 value 就取得資料。
} else if (typeof name === 'string' && value === void 0) {
return (ref = this.get()) != null ? (ref1 = ref.$data) != null ? ref1[name] : void 0 : void 0;
// 有 name 但他是 object,就設置多重樣式。
} else if (typeof name === 'object') {
for (key in name) {
this.each(function() {
if (this.$data === void 0) {
this.$data = {};
}
return this.$data[key] = name[key];
});
}
return this;
}
}
};
// Remove Data
// 移除指定的資料。
ts.fn.removeData = {
value: function(name) {
return this.each(function() {
if (this.$data[name] != null) {
return delete this.$data[name];
}
});
}
};
// Has Timer
// 確認是否有指定的計時器。
ts.fn.hasTimer = {
value: function(name) {
var ref, ref1;
return ((ref = this.get(0)) != null ? (ref1 = ref.$timers) != null ? ref1[name] : void 0 : void 0) != null;
}
};
// Get Timer
// 取得計時器內容。
ts.fn.getTimer = {
value: function(name) {
var ref, ref1;
return (ref = this.get(0)) != null ? (ref1 = ref.$timers) != null ? ref1[name] : void 0 : void 0;
}
};
// Set Timer
// 設置一個新的計時器。
ts.fn.setTimer = {
value: function(options) {
options = Object.assign({}, {
name: '',
callback: function() {},
interval: 0,
looping: false,
visible: false
}, options);
return this.each(function() {
var timer;
if (this.$timers === void 0) {
this.$timers = {};
}
if (this.$timers[options.name] !== void 0) {
clearInterval(this.$timers[options.name].timer);
}
timer = () => {
var ref;
// 當設置有說明,頁面不可見的時候就不要繼續計時。
if (options.visible && document.hidden) {
return;
}
// 替計時器加上 10 毫秒。
this.$timers[options.name].passed += 10;
// 如果計時器的經過時間還不到使用者設定的時間
// 就返回而不要繼續執行。
if (this.$timers[options.name].passed < options.interval) {
return;
}
// 呼叫回呼函式。
options.callback();
// 如果要循環的話,就在計時器執行後重設時間即可。
if (options.looping) {
return this.$timers[options.name].passed = 0;
} else {
// 不然就移除計時器資訊。
return clearInterval((ref = this.$timers[options.name]) != null ? ref.timer : void 0);
}
};
// 移除在 DOM 元素內的這個計時器物件。
//delete @$timers[options.name]
// 在此元素內初始化計時器物件。
return this.$timers[options.name] = {
timer: setInterval(timer, 10),
passed: 0,
callback: options.callback,
interval: options.interval,
looping: options.looping,
visible: options.visible,
initializer: timer,
paused: false
};
});
}
};
// Pause Timer
// 暫停一個計時器。
ts.fn.pauseTimer = {
value: function(name) {
return this.each(function() {
var ref;
if (((ref = this.$timers) != null ? ref[name] : void 0) == null) {
return;
}
// 清除計數計時器達到暫停效果。
clearInterval(this.$timers[name].timer);
// 表示暫停。
return this.$timers[name].paused = true;
});
}
};
// Play Timer
// 重啟一個計時器。
ts.fn.playTimer = {
value: function(name) {
return this.each(function() {
var ref;
if (((ref = this.$timers) != null ? ref[name] : void 0) == null) {
return;
}
if (!this.$timers[name].paused) {
return;
}
// 重新初始化計數計時器來達到繼續的效果。
this.$timers[name].timer = setInterval(this.$timers[name].initializer, 10);
// 表示重新啟動。
return this.$timers[name].paused = false;
});
}
};
// Remove Timer
// 移除一個計時器。
ts.fn.removeTimer = {
value: function(name) {
return this.each(function() {
var ref;
if (((ref = this.$timers) != null ? ref[name] : void 0) == null) {
return;
}
// 清除計數計時器。
clearInterval(this.$timers[name].timer);
// 移除在 DOM 元素內的計時器物件。
return delete this.$timers[name];
});
}
};
// Repaint
// 讓瀏覽器重繪元素。
ts.fn.repaint = {
value: function() {
return this.each(function() {
return void(this.offsetHeight);
});
}
};
}).call(this);