123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632 |
- // Generated by CoffeeScript 2.3.1
- (function() {
- // 主要的選擇器函式。
- var ts;
- ts = function(selector, context) {
- var nodes, ref, tag;
- nodes = [];
- // 如果選擇器是文字,但是是標籤(如:`<div>`)就建立新的元素
- 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;
- };
- // 取得裝置資料。
- ts.device = () => {
- var device;
- switch (false) {
- case !(window.innerWidth < 767):
- device = 'mobile';
- break;
- case !(window.innerWidth > 767 && window.innerWidth < 991):
- device = 'tablet';
- break;
- case !(window.innerWidth > 991 && window.innerWidth < 1199):
- device = 'computer';
- break;
- case !(window.innerWidth > 1199 && window.innerWidth < 1919):
- device = 'large';
- }
- return {
- device: device
- };
- };
- // 從指定坐標取得元素。
- ts.fromPoint = (x, y) => {
- return ts(document.elementFromPoint(x, y));
- };
- // 延展物件的函式,與 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 = (module) => {
- var name;
- name = module.name.toLowerCase();
- return ts.fn[name] = {
- value: function() {
- var $allModules, consoleText, errorHeaderCSS, headerCSS, messageCSS, methodInvoked, moduleNamespace, query, queryArguments, returnedValue;
- $allModules = ts(this);
- moduleNamespace = `module-${name}`;
- query = arguments[0];
- queryArguments = Array.prototype.slice.call(arguments, 1);
- methodInvoked = typeof query === 'string';
- returnedValue = void 0;
- consoleText = (args) => {
- 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 $module, applyEventNamespace, debug, destroy, element, error, eventNamespace, id, initialize, instance, instantiate, invoke, listener, observeChanges, settings;
- element = this;
- $module = ts(element);
- id = $module.uniqueID();
- instance = $module.data(moduleNamespace);
- eventNamespace = `.${name}-${id}`;
-
- settings = ts.extend(module.prototype.settings, {
- // 消音所有提示,甚至是錯誤訊息。
- silent: false,
- // 顯示除錯訊息。
- debug: true,
- // 監聽 DOM 結構異動並自動重整快取。
- observeChanges: true
- });
- settings = ts.isPlainObject(query) ? ts.extend(settings, query) : ts.extend(settings);
-
- applyEventNamespace = (events = '') => {
- var newEvents;
- newEvents = '';
- events.split(' ').forEach((event) => {
- return newEvents += `${event}${eventNamespace}`;
- });
- return newEvents;
- };
-
- listener = {
- on: function() {
- var callback, handlerIndex, newArguments;
- newArguments = arguments;
- newArguments[0] = applyEventNamespace(newArguments[0]);
- newArguments = Array.from(newArguments);
- handlerIndex = -1;
- newArguments.forEach((el, index) => {
- if (typeof el === 'function') {
- return handlerIndex = index;
- }
- });
- callback = newArguments[handlerIndex];
- newArguments[handlerIndex] = function() {
- var args, event, self;
- event = arguments[0];
- args = Array.prototype.slice.call(arguments, 1);
- self = this;
- return callback.call(self, self, event, ...args);
- };
- return $module.on.apply($module, newArguments);
- },
-
- off: function() {
- var newArguments;
- newArguments = arguments;
- newArguments[0] = applyEventNamespace(newArguments[0]);
- return $module.off.apply($module, newArguments);
- },
-
- one: function() {},
- //newArguments = arguments
- //newArguments[0] = applyEventNamespace newArguments[0]
- //$module.one.apply $module, newArguments
- trigger: function(callbackName, context) {
- callbackName = callbackName[0].toUpperCase() + callbackName.slice(1);
- return settings[`on${callbackName}`].apply(context, ...Array.prototype.slice.call(arguments, 2));
- }
- };
-
- debug = function() {
- if (!settings.debug || settings.silent) {
- return;
- }
- return console.info.call(console, consoleText(arguments), headerCSS, messageCSS, "\n", element, ...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 = () => {
- debug('instantiate');
- module.prototype.beforeCreate();
- instance = new module({settings, $allModules, $module, element, listener, id});
- $module.data(moduleNamespace, instance);
- return instance.created();
- };
-
- observeChanges = () => {
- var observer;
- if (!'MutationObserver' in window) {
- return;
- }
- observer = new MutationObserver((mutations) => {
- return instance.updated();
- });
- return observer.observe(element, {
- childList: true,
- subtree: true
- });
- };
-
- initialize = (module) => {
- debug('initialize');
- if (settings.observeChanges) {
- observeChanges();
- }
- return instantiate();
- };
-
- destroy = () => {
- debug('destroy');
- instance.beforeDestroy();
- $module.off().removeData(moduleNamespace);
- return instance.destroyed(...queryArguments);
- };
-
- invoke = (query, passedArguments, context) => {
- var camelCaseQuery;
- camelCaseQuery = '';
-
- query.split(' ').forEach((word) => {
- return camelCaseQuery += word[0].toUpperCase() + word.slice(1);
- });
-
- if (camelCaseQuery === 'Destroy') {
- destroy();
- return void 0;
- }
-
- if (camelCaseQuery === 'Setting') {
- if (ts.isPlainObject(queryArguments[0])) {
- settings = ts.extend(settings, queryArguments[0]);
- instance.settings = settings;
- return void 0;
- } else {
- return instance.settings[queryArguments[0]];
- }
- }
-
- if (instance[camelCaseQuery] === void 0) {
- error('欲呼叫的方法並不存在', query);
- return void 0;
- }
-
- return instance[camelCaseQuery].apply(context, passedArguments);
- };
- if (methodInvoked) {
- if (instance === void 0) {
- initialize();
- }
- return returnedValue = invoke(query, queryArguments, instance);
- } else {
- if (instance !== void 0) {
- destroy();
- }
- return initialize();
- }
- });
- if (returnedValue === void 0 || returnedValue instanceof module) {
- return $allModules;
- }
- return returnedValue;
- }
- };
- };
- // 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;
- });
- }
- };
- // Parents
- // 回傳元素的所有父元素直至指定父元素。
- ts.fn.parents = {
- value: function(selector) {
- return this.collectSwap(function(self) {
- var matchedSelector, parents;
- parents = [];
- matchedSelector = false;
- while (self) {
- self = self.parentNode;
- if (self.nodeType === 9) {
- break;
- }
- parents.push(self);
- if (ts(self).is(selector)) {
- matchedSelector = true;
- break;
- }
- }
- if (selector && !matchedSelector) {
- return [];
- }
- return parents;
- });
- }
- };
- // 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 isInElements, ref;
- isInElements = false;
- if (selector instanceof HTMLElement) {
- return (ref = this.get(0)) != null ? ref.isSameNode(selector) : void 0;
- }
- this.each(function() {
- return ts(selector).each((compareElement) => {
- if (this === compareElement) {
- return isInElements = true;
- }
- });
- });
- return isInElements;
- }
- };
- // Contains
- // 是否擁有指定子元素。
- ts.fn.contains = {
- value: function(selector) {
- var ref;
- return (ref = this.get(0)) != null ? ref.contains(ts(selector).get()) : void 0;
- }
- };
- // Exists
- // 是否存在。
- ts.fn.exists = {
- value: function() {
- return this.length !== 0;
- }
- };
- // Not
- // 將指定元素從選擇器中剔除。
- ts.fn.not = {
- value: function(selector) {
- return ts(this.toArray().filter((element) => {
- return ts(selector).indexOf(element) === -1;
- }));
- }
- };
- // Filter
- // 將指定元素從選擇器中保留,簡單說就是 `Not` 的相反。
- ts.fn.filter = {
- 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(' ');
- }
- 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 r, ref;
- r = (ref = this.get(0)) != null ? ref.getBoundingClientRect() : void 0;
- return {
- top: r.top,
- right: r.right,
- bottom: r.bottom,
- left: r.left,
- width: r.width,
- height: r.height,
- x: r.x,
- y: r.y
- };
- }
- };
- // 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 (events[0] === '(' && events[events.length - 1] === ')') {
- if (this !== window) {
- return;
- }
- if (window.$media === void 0) {
- window.$media = {};
- }
- if (window.$media[events] === void 0) {
- window.$media[events] = [];
- window.matchMedia(events).addListener(function(mq) {
- var j, len, ref, results, single;
- ref = window.$media[events];
- results = [];
- for (j = 0, len = ref.length; j < len; j++) {
- single = ref[j];
- results.push(single.func.call(this, mq));
- }
- return results;
- });
- }
- window.$media[events].push({
- data: {},
- func: handler
- });
- return;
- }
- 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) {
- if (events !== void 0) {
- events = ts.helper.eventAlias(events);
- }
- return this.each(function() {
- if ((events != null ? events[0] : void 0) === '(' && events[events.length - 1] === ')') {
- if (this !== window) {
- return;
- }
- if (window.$media === void 0) {
- return;
- }
- if (window.$media[events] === void 0) {
- return;
- }
- switch (false) {
- case handler === void 0:
- window.$media[events].forEach((item, index) => {
- if (handler === item.func) {
- return window.$media[events].splice(index, 1);
- }
- });
- break;
- case handler !== void 0:
- window.$media[events] = [];
- }
- return;
- }
- if (this.$events === void 0) {
- return;
- }
- if (events === void 0) {
- this.$events = {};
- 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) {
- return setTimeout(() => {
- options = {...{
- 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
- };
- });
- }, 0);
- }
- };
- // 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);
- });
- }
- };
- // Unique ID
- // 取得為此元素而產生的獨立編號,若無則建立。
- ts.fn.uniqueID = {
- value: function() {
- var id;
- id = this.get(0).$uniqueID;
- if (id) {
- return id;
- }
- this.get(0).$uniqueID = (Math.random().toString(16) + '000000000').substr(2, 8);
- return this.get(0).$uniqueID;
- }
- };
- }).call(this);
|