// 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);