tocas.js 47 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632
  1. // Generated by CoffeeScript 2.3.1
  2. (function() {
  3. // 主要的選擇器函式。
  4. var ts;
  5. ts = function(selector, context) {
  6. var nodes, ref, tag;
  7. nodes = [];
  8. // 如果選擇器是文字,但是是標籤(如:`<div>`)就建立新的元素
  9. if (typeof selector === 'string' && selector[0] === '<') {
  10. tag = selector.match(/<(.*)\/>|<(.*)>/);
  11. nodes = [document.createElement((ref = tag[1]) != null ? ref : tag[2])];
  12. // 如果選擇器是一般的文字,就選取元素。
  13. } else if (typeof selector === 'string' && context === void 0) {
  14. document.querySelectorAll(selector).forEach(function(element) {
  15. return nodes.push(element);
  16. });
  17. // 如果選擇器有上下文選擇器,就透過選擇器找出上下文元素。
  18. } else if (typeof context === 'string') {
  19. nodes = ts(selector).find(context).toArray();
  20. // 如果選擇器是 NodeList 就轉換成元素陣列然後取出來接著繼續。
  21. } else if (selector instanceof NodeList) {
  22. selector.forEach(function(element) {
  23. return nodes.push(element);
  24. });
  25. // 如果選擇器是陣列,就當作是元素陣列,取出來然後繼續。
  26. // 或傳入的是一個選擇器,就取出裡面的元素然後繼續。
  27. } else if (Array.isArray(selector) || (selector != null ? selector.isSelector : void 0) === true) {
  28. nodes = nodes.concat(selector);
  29. selector = selector.selector;
  30. context = selector != null ? selector.context : void 0;
  31. // 如果是單個 DOM 元素,就放入選擇器然後繼續。
  32. } else if (selector instanceof HTMLElement || selector instanceof HTMLDocument || selector instanceof HTMLBodyElement || selector === window) {
  33. nodes = [selector];
  34. }
  35. // 保存目前的選擇器文字與上下文選擇器文字。
  36. nodes.selector = typeof selector === 'string' ? selector : null;
  37. nodes.context = typeof context === 'string' ? context : null;
  38. // 將自訂的選擇器方法插入到節點陣列中,這樣才能夠串連使用。
  39. Object.defineProperties(nodes, ts.fn);
  40. // 將節點陣列標註為是選擇器,這樣才能判斷傳入的是不是我們自己的選擇器。
  41. Object.defineProperty(nodes, 'isSelector', {
  42. value: true
  43. });
  44. return nodes;
  45. };
  46. // 註冊到視窗上。
  47. window.ts = ts;
  48. // 函式鏈。
  49. ts.fn = {};
  50. // 輔助函式。
  51. ts.helper = {};
  52. // 事件輔助函式。
  53. ts.helper.eventAlias = function(event) {
  54. var alias, pair;
  55. pair = event.split('.');
  56. alias = pair[1] !== void 0 ? `.${pair[1]}` : '';
  57. switch (false) {
  58. case pair.indexOf('animationend') === -1:
  59. return `webkitAnimationEnd${alias} mozAnimationEnd${alias} MSAnimationEnd${alias} oanimationend${alias} animationend${alias}`;
  60. case pair.indexOf('transitionend') === -1:
  61. return `webkitTransitionEnd${alias} mozTransitionEnd${alias} oTransitionEnd${alias} msTransitionEnd${alias} transitionend${alias}`;
  62. default:
  63. return event;
  64. }
  65. };
  66. // 是否為物件。
  67. ts.isPlainObject = function(object) {
  68. return Object.prototype.toString.call(object) === '[object Object]';
  69. };
  70. // 是否為可觸控裝置。
  71. ts.isTouchDevice = function() {
  72. return 'ontouchstart' in window || navigator.maxTouchPoints;
  73. };
  74. // 取得裝置資料。
  75. ts.device = () => {
  76. var device;
  77. switch (false) {
  78. case !(window.innerWidth < 767):
  79. device = 'mobile';
  80. break;
  81. case !(window.innerWidth > 767 && window.innerWidth < 991):
  82. device = 'tablet';
  83. break;
  84. case !(window.innerWidth > 991 && window.innerWidth < 1199):
  85. device = 'computer';
  86. break;
  87. case !(window.innerWidth > 1199 && window.innerWidth < 1919):
  88. device = 'large';
  89. }
  90. return {
  91. device: device
  92. };
  93. };
  94. // 從指定坐標取得元素。
  95. ts.fromPoint = (x, y) => {
  96. return ts(document.elementFromPoint(x, y));
  97. };
  98. // 延展物件的函式,與 ES 的 `...` 不同之處在於 extend 並不會替換掉整個子物件,而會以補插的方式執行。
  99. // https://gomakethings.com/vanilla-javascript-version-of-jquery-extend/
  100. ts.extend = function() {
  101. var deep, extended, i, length, merge, obj;
  102. extended = {};
  103. deep = true;
  104. i = 0;
  105. length = arguments.length;
  106. if (Object.prototype.toString.call(arguments[0]) === '[object Boolean]') {
  107. deep = arguments[0];
  108. i++;
  109. }
  110. merge = function(obj) {
  111. var prop;
  112. for (prop in obj) {
  113. if (Object.prototype.hasOwnProperty.call(obj, prop)) {
  114. if (deep && Object.prototype.toString.call(obj[prop]) === '[object Object]') {
  115. extended[prop] = ts.extend(true, extended[prop], obj[prop]);
  116. } else {
  117. extended[prop] = obj[prop];
  118. }
  119. }
  120. }
  121. };
  122. while (i < length) {
  123. obj = arguments[i];
  124. merge(obj);
  125. i++;
  126. }
  127. return extended;
  128. };
  129. // 建立元素
  130. ts.createElement = (html) => {
  131. var div;
  132. div = document.createElement('div');
  133. div.innerHTML = html.trim();
  134. return div.firstChild;
  135. };
  136. // 註冊 Tocas 模塊
  137. ts.register = (module) => {
  138. var name;
  139. name = module.name.toLowerCase();
  140. return ts.fn[name] = {
  141. value: function() {
  142. var $allModules, consoleText, errorHeaderCSS, headerCSS, messageCSS, methodInvoked, moduleNamespace, query, queryArguments, returnedValue;
  143. $allModules = ts(this);
  144. moduleNamespace = `module-${name}`;
  145. query = arguments[0];
  146. queryArguments = Array.prototype.slice.call(arguments, 1);
  147. methodInvoked = typeof query === 'string';
  148. returnedValue = void 0;
  149. consoleText = (args) => {
  150. return `%c${name}%c ${args[0]}`;
  151. };
  152. headerCSS = "background : #EEE;\ncolor : #5A5A5A;\nfont-size : 1em;\npadding : 8px 8px;\nline-height : 5px;\nmargin : 5px 0 5px 0;\nborder-radius: 1000em;";
  153. errorHeaderCSS = `${headerCSS}\nbackground: #CE5F58;\ncolor: #FFF;`;
  154. messageCSS = "font-weight: bold;";
  155. $allModules.each(function(_, index) {
  156. var $module, applyEventNamespace, debug, destroy, element, error, eventNamespace, id, initialize, instance, instantiate, invoke, listener, observeChanges, settings;
  157. element = this;
  158. $module = ts(element);
  159. id = $module.uniqueID();
  160. instance = $module.data(moduleNamespace);
  161. eventNamespace = `.${name}-${id}`;
  162. settings = ts.extend(module.prototype.settings, {
  163. // 消音所有提示,甚至是錯誤訊息。
  164. silent: false,
  165. // 顯示除錯訊息。
  166. debug: true,
  167. // 監聽 DOM 結構異動並自動重整快取。
  168. observeChanges: true
  169. });
  170. settings = ts.isPlainObject(query) ? ts.extend(settings, query) : ts.extend(settings);
  171. applyEventNamespace = (events = '') => {
  172. var newEvents;
  173. newEvents = '';
  174. events.split(' ').forEach((event) => {
  175. return newEvents += `${event}${eventNamespace}`;
  176. });
  177. return newEvents;
  178. };
  179. listener = {
  180. on: function() {
  181. var callback, handlerIndex, newArguments;
  182. newArguments = arguments;
  183. newArguments[0] = applyEventNamespace(newArguments[0]);
  184. newArguments = Array.from(newArguments);
  185. handlerIndex = -1;
  186. newArguments.forEach((el, index) => {
  187. if (typeof el === 'function') {
  188. return handlerIndex = index;
  189. }
  190. });
  191. callback = newArguments[handlerIndex];
  192. newArguments[handlerIndex] = function() {
  193. var args, event, self;
  194. event = arguments[0];
  195. args = Array.prototype.slice.call(arguments, 1);
  196. self = this;
  197. return callback.call(self, self, event, ...args);
  198. };
  199. return $module.on.apply($module, newArguments);
  200. },
  201. off: function() {
  202. var newArguments;
  203. newArguments = arguments;
  204. newArguments[0] = applyEventNamespace(newArguments[0]);
  205. return $module.off.apply($module, newArguments);
  206. },
  207. one: function() {},
  208. //newArguments = arguments
  209. //newArguments[0] = applyEventNamespace newArguments[0]
  210. //$module.one.apply $module, newArguments
  211. trigger: function(callbackName, context) {
  212. callbackName = callbackName[0].toUpperCase() + callbackName.slice(1);
  213. return settings[`on${callbackName}`].apply(context, ...Array.prototype.slice.call(arguments, 2));
  214. }
  215. };
  216. debug = function() {
  217. if (!settings.debug || settings.silent) {
  218. return;
  219. }
  220. return console.info.call(console, consoleText(arguments), headerCSS, messageCSS, "\n", element, ...Array.prototype.slice.call(arguments).slice(1));
  221. };
  222. error = function() {
  223. if (settings.silent) {
  224. return;
  225. }
  226. error = Function.prototype.bind.call(console.error, console, consoleText(arguments), errorHeaderCSS, messageCSS);
  227. return error.apply(console, Array.prototype.slice.call(arguments, 1));
  228. };
  229. instantiate = () => {
  230. debug('instantiate');
  231. module.prototype.beforeCreate();
  232. instance = new module({settings, $allModules, $module, element, listener, id});
  233. $module.data(moduleNamespace, instance);
  234. return instance.created();
  235. };
  236. observeChanges = () => {
  237. var observer;
  238. if (!'MutationObserver' in window) {
  239. return;
  240. }
  241. observer = new MutationObserver((mutations) => {
  242. return instance.updated();
  243. });
  244. return observer.observe(element, {
  245. childList: true,
  246. subtree: true
  247. });
  248. };
  249. initialize = (module) => {
  250. debug('initialize');
  251. if (settings.observeChanges) {
  252. observeChanges();
  253. }
  254. return instantiate();
  255. };
  256. destroy = () => {
  257. debug('destroy');
  258. instance.beforeDestroy();
  259. $module.off().removeData(moduleNamespace);
  260. return instance.destroyed(...queryArguments);
  261. };
  262. invoke = (query, passedArguments, context) => {
  263. var camelCaseQuery;
  264. camelCaseQuery = '';
  265. query.split(' ').forEach((word) => {
  266. return camelCaseQuery += word[0].toUpperCase() + word.slice(1);
  267. });
  268. if (camelCaseQuery === 'Destroy') {
  269. destroy();
  270. return void 0;
  271. }
  272. if (camelCaseQuery === 'Setting') {
  273. if (ts.isPlainObject(queryArguments[0])) {
  274. settings = ts.extend(settings, queryArguments[0]);
  275. instance.settings = settings;
  276. return void 0;
  277. } else {
  278. return instance.settings[queryArguments[0]];
  279. }
  280. }
  281. if (instance[camelCaseQuery] === void 0) {
  282. error('欲呼叫的方法並不存在', query);
  283. return void 0;
  284. }
  285. return instance[camelCaseQuery].apply(context, passedArguments);
  286. };
  287. if (methodInvoked) {
  288. if (instance === void 0) {
  289. initialize();
  290. }
  291. return returnedValue = invoke(query, queryArguments, instance);
  292. } else {
  293. if (instance !== void 0) {
  294. destroy();
  295. }
  296. return initialize();
  297. }
  298. });
  299. if (returnedValue === void 0 || returnedValue instanceof module) {
  300. return $allModules;
  301. }
  302. return returnedValue;
  303. }
  304. };
  305. };
  306. // Get
  307. // 取得選擇器內的指定元素,並且回傳一個 DOM 元素而非選擇器。
  308. ts.fn.get = {
  309. value: function(index = 0) {
  310. return this[index];
  311. }
  312. };
  313. // ToArray
  314. // 將選擇器轉換成帶有節點的一般陣列。
  315. ts.fn.toArray = {
  316. value: function() {
  317. var array;
  318. array = [];
  319. this.forEach(function(element) {
  320. return array.push(element);
  321. });
  322. return array;
  323. }
  324. };
  325. // Each
  326. // 遍歷整個選擇器陣列。
  327. ts.fn.each = {
  328. value: function(callback) {
  329. this.forEach(function(element, index) {
  330. return callback.call(element, element, index);
  331. });
  332. return this;
  333. }
  334. };
  335. // CollectSwap
  336. // 將收集到的元素替換掉目前選擇器內的所有元素。
  337. ts.fn.collectSwap = {
  338. value: function(callback) {
  339. var collection, newSelector;
  340. collection = [];
  341. this.each(function(element, index) {
  342. var result;
  343. result = callback.call(element, element, index);
  344. if (result === void 0 || result === null) {
  345. return;
  346. }
  347. if (result instanceof NodeList) {
  348. return result.forEach(function(el) {
  349. return collection.push(el);
  350. });
  351. } else if (Array.isArray(result)) {
  352. return collection = collection.concat(result);
  353. } else {
  354. if (collection.indexOf(result) === -1) {
  355. return collection.push(result);
  356. }
  357. }
  358. });
  359. // 透過 Set 型態移除重複的節點。
  360. collection = new Set(collection);
  361. // 然後將 Set 轉換成陣列,建立新的選擇器。
  362. newSelector = ts([...collection]);
  363. // 保存選擇器之前的所有節點。
  364. Object.defineProperty(newSelector, 'prevObject', {
  365. value: this
  366. });
  367. // 回傳這個新的選擇器。
  368. return newSelector;
  369. }
  370. };
  371. // Eq
  372. // 取得選擇器的指定元素,然後繼續回傳僅帶有該元素的選擇器。
  373. ts.fn.eq = {
  374. value: function(index) {
  375. return ts(this.get(index));
  376. }
  377. };
  378. // Parent
  379. // 回傳元素的父元素選擇器。
  380. ts.fn.parent = {
  381. value: function() {
  382. return this.collectSwap(function() {
  383. return this.parentNode;
  384. });
  385. }
  386. };
  387. // Parents
  388. // 回傳元素的所有父元素直至指定父元素。
  389. ts.fn.parents = {
  390. value: function(selector) {
  391. return this.collectSwap(function(self) {
  392. var matchedSelector, parents;
  393. parents = [];
  394. matchedSelector = false;
  395. while (self) {
  396. self = self.parentNode;
  397. if (self.nodeType === 9) {
  398. break;
  399. }
  400. parents.push(self);
  401. if (ts(self).is(selector)) {
  402. matchedSelector = true;
  403. break;
  404. }
  405. }
  406. if (selector && !matchedSelector) {
  407. return [];
  408. }
  409. return parents;
  410. });
  411. }
  412. };
  413. // Closest
  414. // 回傳最接近指定的父元素選擇器。
  415. ts.fn.closest = {
  416. value: function(selector) {
  417. return this.collectSwap(function() {
  418. return this.closest(selector);
  419. });
  420. }
  421. };
  422. // Find
  423. // 在目前元素中搜尋指定元素並回傳其選擇器。
  424. ts.fn.find = {
  425. value: function(selector) {
  426. return this.collectSwap(function() {
  427. return this.querySelectorAll(selector);
  428. });
  429. }
  430. };
  431. // Insert Before
  432. // 將選擇器元素安插在指定元素前。
  433. ts.fn.insertBefore = {
  434. value: function(target) {
  435. return this.each(function() {
  436. return ts(target).each((element) => {
  437. return element.parentNode.insertBefore(this, element);
  438. });
  439. });
  440. }
  441. };
  442. // Insert After
  443. // 將選擇器元素安插在指定元素後。
  444. ts.fn.insertAfter = {
  445. value: function(target) {
  446. return this.each(function() {
  447. return ts(target).each((element) => {
  448. return element.parentNode.insertBefore(this, element.nextSibling);
  449. });
  450. });
  451. }
  452. };
  453. // Wrap
  454. // 將元素用指定元素包覆起來。
  455. ts.fn.wrap = {
  456. value: function(element) {
  457. return this.each(function() {
  458. if (this.nextSibling) {
  459. this.parentNode.insertBefore(element, this.nextSibling);
  460. } else {
  461. this.parentNode.appendChild(element);
  462. }
  463. return element.appendChild(this);
  464. });
  465. }
  466. };
  467. // Clone
  468. // 複製元素。
  469. ts.fn.clone = {
  470. value: function() {
  471. return this.collectSwap(function() {
  472. return this.cloneNode(true);
  473. });
  474. }
  475. };
  476. // Append
  477. // 將元素插入在目前選擇器元素的內部最後面。
  478. ts.fn.append = {
  479. value: function(element) {
  480. var shouldClone;
  481. shouldClone = this.length !== 1;
  482. if (element.isSelector !== void 0) {
  483. return this.each(function() {
  484. return element.each((e) => {
  485. return this.appendChild(shouldClone ? e.cloneNode(true) : e);
  486. });
  487. });
  488. } else if (typeof element === 'string') {
  489. return this.each(function() {
  490. return this.insertAdjacentHTML('beforeend', element);
  491. });
  492. } else {
  493. return this.each(function() {
  494. return this.appendChild(shouldClone ? element.cloneNode(true) : element);
  495. });
  496. }
  497. }
  498. };
  499. // AppendTo
  500. // 將目前選擇器元素插入到指定元素的內部最後面。
  501. ts.fn.appendTo = {
  502. value: function(selector) {
  503. return this.each(function() {
  504. return ts(selector).append(this);
  505. });
  506. }
  507. };
  508. // Prepend
  509. // 將元素插入在目前選擇器元素的內部最前面。
  510. ts.fn.prepend = {
  511. value: function(element) {
  512. var shouldClone;
  513. shouldClone = this.length !== 1;
  514. if (element.isSelector !== void 0) {
  515. return this.each(function() {
  516. return element.each((e) => {
  517. return this.prepend(shouldClone ? e.cloneNode(true) : e);
  518. });
  519. });
  520. } else if (typeof element === 'string') {
  521. return this.each(function() {
  522. return this.insertAdjacentHTML('afterbegin', element);
  523. });
  524. } else {
  525. return this.each(function() {
  526. return this.prepend(shouldClone ? element.cloneNode(true) : element);
  527. });
  528. }
  529. }
  530. };
  531. // PrependTo
  532. // 將目前選擇器元素插入到指定元素的內部最前面。
  533. ts.fn.prependTo = {
  534. value: function(selector) {
  535. return this.each(function() {
  536. return ts(selector).prepend(this);
  537. });
  538. }
  539. };
  540. // Remove
  541. // 將選擇器元素從頁面上中移除。
  542. ts.fn.remove = {
  543. value: function() {
  544. return this.each(function() {
  545. var ref;
  546. return (ref = this.parentNode) != null ? ref.removeChild(this) : void 0;
  547. });
  548. }
  549. };
  550. // Is
  551. // 選擇一些元素,然後用來比對目前的選擇器元素是否在這群當中。
  552. ts.fn.is = {
  553. value: function(selector) {
  554. var isInElements, ref;
  555. isInElements = false;
  556. if (selector instanceof HTMLElement) {
  557. return (ref = this.get(0)) != null ? ref.isSameNode(selector) : void 0;
  558. }
  559. this.each(function() {
  560. return ts(selector).each((compareElement) => {
  561. if (this === compareElement) {
  562. return isInElements = true;
  563. }
  564. });
  565. });
  566. return isInElements;
  567. }
  568. };
  569. // Contains
  570. // 是否擁有指定子元素。
  571. ts.fn.contains = {
  572. value: function(selector) {
  573. var ref;
  574. return (ref = this.get(0)) != null ? ref.contains(ts(selector).get()) : void 0;
  575. }
  576. };
  577. // Exists
  578. // 是否存在。
  579. ts.fn.exists = {
  580. value: function() {
  581. return this.length !== 0;
  582. }
  583. };
  584. // Not
  585. // 將指定元素從選擇器中剔除。
  586. ts.fn.not = {
  587. value: function(selector) {
  588. return ts(this.toArray().filter((element) => {
  589. return ts(selector).indexOf(element) === -1;
  590. }));
  591. }
  592. };
  593. // Filter
  594. // 將指定元素從選擇器中保留,簡單說就是 `Not` 的相反。
  595. ts.fn.filter = {
  596. value: function(selector) {
  597. return ts(this.toArray().filter((element) => {
  598. return ts(selector).indexOf(element) !== -1;
  599. }));
  600. }
  601. };
  602. // Slice
  603. // 替元素陣列進行切分。
  604. ts.fn.slice = {
  605. value: function(from, to) {
  606. return ts(this.toArray().slice(from, to));
  607. }
  608. };
  609. // Children
  610. // 取得容器裡的第一層子節點。
  611. ts.fn.children = {
  612. value: function(selector) {
  613. return this.collectSwap(function() {
  614. return this.querySelectorAll(selector != null ? `:scope > ${selector}` : ':scope > *');
  615. });
  616. }
  617. };
  618. // Replace With
  619. // 將元素替換為指定選擇器元素。
  620. ts.fn.replaceWith = {
  621. value: function(selector) {
  622. var element;
  623. element = ts(selector).get();
  624. return this.each(function() {
  625. return this.replaceWith(element);
  626. });
  627. }
  628. };
  629. // Last
  630. // 選擇器中的最後一個元素。
  631. ts.fn.last = {
  632. value: function() {
  633. return this.eq(this.length - 1);
  634. }
  635. };
  636. // Next
  637. // 下一個元素。
  638. ts.fn.next = {
  639. value: function() {
  640. return this.collectSwap(function() {
  641. return this.nextElementSibling;
  642. });
  643. }
  644. };
  645. // Prev
  646. // 上一個元素。
  647. ts.fn.prev = {
  648. value: function() {
  649. return this.collectSwap(function() {
  650. return this.previousElementSibling;
  651. });
  652. }
  653. };
  654. // NextAll
  655. // 這個元素之後的所有同階層元素。
  656. ts.fn.nextAll = {
  657. value: function(selector) {
  658. return this.collectSwap(function() {
  659. var $children, $parent, $self, index;
  660. $self = ts(this);
  661. $parent = $self.parent();
  662. $children = selector != null ? $parent.find(`:scope > ${selector}`) : $parent.find(':scope > *');
  663. index = $self.index();
  664. return $children.slice(index + 1);
  665. });
  666. }
  667. };
  668. // PrevAll
  669. // 這個元素之前的所有同階層元素。
  670. ts.fn.prevAll = {
  671. value: function(selector) {
  672. return this.collectSwap(function() {
  673. var $children, $parent, $self, index;
  674. $self = ts(this);
  675. $parent = $self.parent();
  676. $children = selector != null ? $parent.find(`:scope > ${selector}`) : $parent.find(':scope > *');
  677. index = $self.index();
  678. return $children.slice(0, index);
  679. });
  680. }
  681. };
  682. // AddBack
  683. // 在目前的選擇器節點陣列中加上先前選擇的所有節點。
  684. ts.fn.addBack = {
  685. value: function() {
  686. if (this.prevObject) {
  687. this.prevObject.toArray().forEach((element) => {
  688. return this.push(element);
  689. });
  690. }
  691. return this;
  692. }
  693. };
  694. // Index
  695. // 該元素在容器內的索引。
  696. ts.fn.index = {
  697. value: function() {
  698. var index, node;
  699. node = this.get(0);
  700. index = 0;
  701. if (node == null) {
  702. return -1;
  703. }
  704. while ((node = node.previousElementSibling)) {
  705. index++;
  706. }
  707. return index;
  708. }
  709. };
  710. // Attr
  711. // 取得或是建立新的標籤到目前的選擇器元素。
  712. ts.fn.attr = {
  713. value: function(name, value) {
  714. var ref;
  715. // 如果有 value 就設置簡單鍵值資料。
  716. if (value !== void 0) {
  717. return this.each(function() {
  718. return this.setAttribute(name, value);
  719. });
  720. // 如果傳入的是物件就設置多重資料。
  721. } else if (typeof name === 'object') {
  722. return this.each(function() {
  723. var key, results;
  724. results = [];
  725. for (key in name) {
  726. results.push(this.setAttribute(key, name[key]));
  727. }
  728. return results;
  729. });
  730. } else {
  731. // 不然就取得資料。
  732. return (ref = this.get()) != null ? ref.getAttribute(name) : void 0;
  733. }
  734. }
  735. };
  736. // RemoveAttr
  737. // 移除目前選擇器元素的指定標籤。
  738. ts.fn.removeAttr = {
  739. value: function(name) {
  740. return this.each(function() {
  741. return this.removeAttribute(name);
  742. });
  743. }
  744. };
  745. // AddClass
  746. // 在目前選擇器元素插入新的樣式類別名稱。
  747. ts.fn.addClass = {
  748. value: function(names) {
  749. var name, newNames;
  750. if (typeof names === 'object') {
  751. newNames = '';
  752. for (name in names) {
  753. if (names[name] === true) {
  754. newNames += ` ${name}`;
  755. }
  756. }
  757. names = newNames;
  758. } else {
  759. names = Array.prototype.slice.call(arguments).join(' ');
  760. }
  761. return this.each(function() {
  762. return DOMTokenList.prototype.add.apply(this.classList, names.split(' ').filter(Boolean));
  763. });
  764. }
  765. };
  766. // RemoveClass
  767. // 移除目前選擇器元素的指定樣式類別。
  768. ts.fn.removeClass = {
  769. value: function(names) {
  770. var name, newNames;
  771. if (typeof names === 'object') {
  772. newNames = '';
  773. for (name in names) {
  774. if (names[name] === true) {
  775. newNames += ` ${name}`;
  776. }
  777. }
  778. names = newNames;
  779. } else {
  780. names = Array.prototype.slice.call(arguments).join(' ');
  781. }
  782. return this.each(function() {
  783. return DOMTokenList.prototype.remove.apply(this.classList, names.split(' ').filter(Boolean));
  784. });
  785. }
  786. };
  787. // ToggleClass
  788. // 切換目前選擇器元素的樣式。
  789. ts.fn.toggleClass = {
  790. value: function(names) {
  791. return this.each(function() {
  792. return names.split(' ').forEach(function(name) {
  793. return this.classList.toggle(name);
  794. }, this);
  795. });
  796. }
  797. };
  798. // HasClass
  799. // 回傳選擇器元素是否帶有指定樣式類別,是布林值。
  800. ts.fn.hasClass = {
  801. value: function(name) {
  802. var ref;
  803. return (ref = this.get(0)) != null ? ref.classList.contains(name) : void 0;
  804. }
  805. };
  806. // CSS
  807. // 將選擇器元素套用指定的 CSS 樣式。
  808. ts.fn.css = {
  809. value: function(name, value) {
  810. var key;
  811. // 有 name 也有 value 就設置樣式。
  812. if (typeof name === 'string' && value !== void 0) {
  813. return this.each(function() {
  814. return this.style[name] = value;
  815. });
  816. // 有 name 但沒有 value 就取得樣式。
  817. } else if (typeof name === 'string' && value === void 0) {
  818. if (this.get() != null) {
  819. return document.defaultView.getComputedStyle(this.get(), null).getPropertyValue(name);
  820. } else {
  821. return null;
  822. }
  823. // 有 name 但他是 object,就設置多重樣式。
  824. } else if (typeof name === 'object') {
  825. for (key in name) {
  826. this.each(function() {
  827. return this.style[key] = name[key];
  828. });
  829. }
  830. return this;
  831. }
  832. }
  833. };
  834. // Rect
  835. // 回傳選擇器元素的渲染形狀。
  836. ts.fn.rect = {
  837. value: function() {
  838. var r, ref;
  839. r = (ref = this.get(0)) != null ? ref.getBoundingClientRect() : void 0;
  840. return {
  841. top: r.top,
  842. right: r.right,
  843. bottom: r.bottom,
  844. left: r.left,
  845. width: r.width,
  846. height: r.height,
  847. x: r.x,
  848. y: r.y
  849. };
  850. }
  851. };
  852. // On
  853. // 綁定並註冊一個事件監聽器。
  854. ts.fn.on = {
  855. value: function() {
  856. var data, events, handler, options, selector;
  857. switch (arguments.length) {
  858. // Event 與 Handler。
  859. case 2:
  860. events = arguments[0];
  861. handler = arguments[1];
  862. break;
  863. // Event 與 Selector 與 Handler。
  864. // Event 與 Data 與 Handler。
  865. // Event 與 Handler 與 Options。
  866. case 3:
  867. events = arguments[0];
  868. handler = arguments[2];
  869. switch (typeof arguments[1]) {
  870. case "string":
  871. selector = arguments[1];
  872. break;
  873. case "function":
  874. handler = arguments[1];
  875. options = arguments[2];
  876. break;
  877. default:
  878. data = arguments[1];
  879. }
  880. break;
  881. // Event 與 Selector 與 Data 與 Handler。
  882. // Event 與 Selector 與 Handler 與 Options。
  883. case 4:
  884. events = arguments[0];
  885. selector = arguments[1];
  886. handler = arguments[3];
  887. switch (typeof arguments[2]) {
  888. case "function":
  889. handler = arguments[2];
  890. options = arguments[3];
  891. break;
  892. default:
  893. data = arguments[2];
  894. }
  895. break;
  896. // Event 與 Selector 與 Data 與 Handler 與 Options。
  897. case 5:
  898. events = arguments[0];
  899. selector = arguments[1];
  900. data = arguments[2];
  901. handler = arguments[3];
  902. options = arguments[4];
  903. }
  904. events = ts.helper.eventAlias(events);
  905. // $events.click =
  906. // {
  907. // anonymous: [
  908. // {
  909. // once : true,
  910. // selector: ".button",
  911. // data : {},
  912. // func : func()
  913. // }
  914. // ]
  915. // alias1: [
  916. // {
  917. // once : true,
  918. // selector: ".button",
  919. // data : {},
  920. // func : func()
  921. // }
  922. // ]
  923. // }
  924. return this.each(function() {
  925. if (events[0] === '(' && events[events.length - 1] === ')') {
  926. if (this !== window) {
  927. return;
  928. }
  929. if (window.$media === void 0) {
  930. window.$media = {};
  931. }
  932. if (window.$media[events] === void 0) {
  933. window.$media[events] = [];
  934. window.matchMedia(events).addListener(function(mq) {
  935. var j, len, ref, results, single;
  936. ref = window.$media[events];
  937. results = [];
  938. for (j = 0, len = ref.length; j < len; j++) {
  939. single = ref[j];
  940. results.push(single.func.call(this, mq));
  941. }
  942. return results;
  943. });
  944. }
  945. window.$media[events].push({
  946. data: {},
  947. func: handler
  948. });
  949. return;
  950. }
  951. if (this.addEventListener === void 0) {
  952. return;
  953. }
  954. if (this.$events === void 0) {
  955. this.$events = {};
  956. }
  957. return events.split(' ').forEach(function(eventName) {
  958. var event, eventAlias, hasAlias;
  959. event = eventName.split('.');
  960. // 透過事件的「event.alias」取得「點」後面的別名。
  961. hasAlias = event.length > 1;
  962. eventName = event[0];
  963. eventAlias = hasAlias ? event[1] : null;
  964. // 如果事件還沒在這個物件內產生過,就初始化一個事件結構。
  965. if (this.$events[eventName] === void 0) {
  966. this.$events[eventName] = {
  967. anonymous: []
  968. };
  969. // 然後建立一個管理多個事件的事件管理處理程式。
  970. this.addEventListener(eventName, function(event) {
  971. var alias, calledAlias, closest, context, hasArgs, index, ref, ref1, ref2, results, single;
  972. // 是否有自訂參數。
  973. hasArgs = ((ref = event.detail) != null ? (ref1 = ref.args) != null ? ref1.length : void 0 : void 0) > 0;
  974. // 是否有呼叫事件別名。
  975. calledAlias = (ref2 = event.detail) != null ? ref2.alias : void 0;
  976. // 如果該事件已經被移除則停止後續的反應。
  977. if (this.$events[eventName] === void 0) {
  978. return;
  979. }
  980. // 將被觸發的事件裡面的所有處理程式全部呼叫一次。
  981. results = [];
  982. for (alias in this.$events[eventName]) {
  983. if (calledAlias && calledAlias !== alias) {
  984. continue;
  985. }
  986. index = this.$events[eventName][alias].length;
  987. results.push((function() {
  988. var results1;
  989. results1 = [];
  990. while (index--) {
  991. if (this.$events[eventName] === void 0) {
  992. continue;
  993. }
  994. if (this.$events[eventName][alias] === void 0) {
  995. continue;
  996. }
  997. single = this.$events[eventName][alias][index];
  998. // 設置事件的上下文。
  999. context = this;
  1000. // 如果這個事件有選擇器的話,則使用該選擇器為主。
  1001. if (single.selector !== void 0) {
  1002. selector = single.selector;
  1003. closest = ts(event.target).closest(selector);
  1004. // 如果找不到指定選擇棄的元素,就不要觸發此事件。
  1005. if (closest.length === 0) {
  1006. continue;
  1007. } else {
  1008. // 替換上下文為選擇器元素。
  1009. context = closest.get();
  1010. }
  1011. }
  1012. // 將事件預資料放入事件中供處理函式取得。
  1013. event.data = single.data;
  1014. if (hasArgs) {
  1015. single.func.call(context, event, ...event.detail.args);
  1016. } else {
  1017. single.func.call(context, event);
  1018. }
  1019. // 如果這個程式只能被呼叫一次就在處理程式呼叫後移除。
  1020. if (single.once === true) {
  1021. results1.push(this.$events[eventName][alias].splice(index, 1));
  1022. } else {
  1023. results1.push(void 0);
  1024. }
  1025. }
  1026. return results1;
  1027. }).call(this));
  1028. }
  1029. return results;
  1030. });
  1031. }
  1032. // 將新的事件處理程式註冊到事件清單中。
  1033. // 如果有別名,就不要推送到匿名陣列中,我們替這個別名另開物件。
  1034. if (hasAlias) {
  1035. if (this.$events[eventName][eventAlias] === void 0) {
  1036. this.$events[eventName][eventAlias] = [];
  1037. }
  1038. return this.$events[eventName][eventAlias].push({
  1039. func: handler,
  1040. selector: selector,
  1041. data: data,
  1042. once: options != null ? options.once : void 0
  1043. });
  1044. } else {
  1045. // 如果沒有,就照常推進匿名陣列中。
  1046. return this.$events[eventName].anonymous.push({
  1047. func: handler,
  1048. selector: selector,
  1049. data: data,
  1050. once: options != null ? options.once : void 0
  1051. });
  1052. }
  1053. }, this);
  1054. });
  1055. }
  1056. };
  1057. // One
  1058. // 綁定一次性的事件監聽器,當被觸發之後就會被移除。
  1059. ts.fn.one = {
  1060. value: function(events, handler) {
  1061. events = ts.helper.eventAlias(events);
  1062. return this.each(function() {
  1063. return ts(this).on(events, handler, {
  1064. once: true
  1065. });
  1066. });
  1067. }
  1068. };
  1069. // Off
  1070. // 註銷事件監聽器。
  1071. ts.fn.off = {
  1072. value: function(events, handler) {
  1073. if (events !== void 0) {
  1074. events = ts.helper.eventAlias(events);
  1075. }
  1076. return this.each(function() {
  1077. if ((events != null ? events[0] : void 0) === '(' && events[events.length - 1] === ')') {
  1078. if (this !== window) {
  1079. return;
  1080. }
  1081. if (window.$media === void 0) {
  1082. return;
  1083. }
  1084. if (window.$media[events] === void 0) {
  1085. return;
  1086. }
  1087. switch (false) {
  1088. case handler === void 0:
  1089. window.$media[events].forEach((item, index) => {
  1090. if (handler === item.func) {
  1091. return window.$media[events].splice(index, 1);
  1092. }
  1093. });
  1094. break;
  1095. case handler !== void 0:
  1096. window.$media[events] = [];
  1097. }
  1098. return;
  1099. }
  1100. if (this.$events === void 0) {
  1101. return;
  1102. }
  1103. if (events === void 0) {
  1104. this.$events = {};
  1105. return;
  1106. }
  1107. return events.split(' ').forEach((eventName) => {
  1108. var alias, aliasName, event, hasAlias, isAlias, results;
  1109. // 將事件名稱由中間的「.」切成兩半。
  1110. event = eventName.split('.');
  1111. // 如果事件開頭是「.」符號,表示這是個別名,不是事件名稱。
  1112. isAlias = eventName[0] === '.';
  1113. // 如果事件分切後有兩個項目,表示這個事件有別名。
  1114. hasAlias = event.length === 2 && event[0] !== '';
  1115. if (hasAlias || isAlias) {
  1116. // 如果有別名的話,取得別名。
  1117. aliasName = event[1];
  1118. }
  1119. // 如果此事件不是只有別名的話,取得事件名稱。
  1120. eventName = !isAlias ? event[0] : void 0;
  1121. switch (false) {
  1122. // 當有指定監聽函式時。
  1123. case !(handler !== void 0 && this.$events[eventName] !== void 0):
  1124. return this.$events[eventName].anonymous.forEach((item, index) => {
  1125. if (handler === item.func) {
  1126. return this.$events[eventName].anonymous.splice(index, 1);
  1127. }
  1128. });
  1129. // 當本事件名稱不僅是別名時。
  1130. case !(!isAlias && hasAlias && this.$events[eventName] !== void 0):
  1131. // 移除指定事件的別名監聽函式。
  1132. return delete this.$events[eventName][aliasName];
  1133. // 當僅有指定別名時。
  1134. case !(isAlias && !hasAlias):
  1135. // 移除所有與此別名有關的事件監聽器。
  1136. results = [];
  1137. for (event in this.$events) {
  1138. results.push((function() {
  1139. var results1;
  1140. results1 = [];
  1141. for (alias in this.$events[event]) {
  1142. if (aliasName === alias) {
  1143. results1.push(delete this.$events[event][aliasName]);
  1144. } else {
  1145. results1.push(void 0);
  1146. }
  1147. }
  1148. return results1;
  1149. }).call(this));
  1150. }
  1151. return results;
  1152. break;
  1153. // 當僅有指定事件名稱時。
  1154. case this.$events[eventName] === void 0:
  1155. // 清空該事件的所有事件監聽器。
  1156. return delete this.$events[eventName];
  1157. }
  1158. }, this);
  1159. });
  1160. }
  1161. };
  1162. // Trigger
  1163. // 觸發指定事件。
  1164. ts.fn.trigger = {
  1165. value: function(events) {
  1166. var customArguments;
  1167. events = ts.helper.eventAlias(events);
  1168. customArguments = [].slice.call(arguments, 1);
  1169. return this.each(function() {
  1170. return events.split(' ').forEach((eventName) => {
  1171. var alias, event, name;
  1172. event = eventName.split('.');
  1173. name = event[0];
  1174. alias = event.length > 1 ? event[1] : null;
  1175. event = new CustomEvent(name, {
  1176. detail: {
  1177. args: customArguments,
  1178. alias: alias
  1179. }
  1180. });
  1181. return this.dispatchEvent(event);
  1182. });
  1183. });
  1184. }
  1185. };
  1186. // Emulate
  1187. // 在指定的秒數過後觸發指定事件,若已被觸發則不再次觸發。
  1188. // 這能用以強迫讓某個事件發生。
  1189. ts.fn.emulate = {
  1190. value: function(event, duration) {
  1191. return this.each(function() {
  1192. var called;
  1193. called = false;
  1194. ts(this).one(event, function() {
  1195. return called = true;
  1196. });
  1197. return setTimeout(() => {
  1198. if (!called) {
  1199. return ts(this).trigger(event);
  1200. }
  1201. }, duration);
  1202. });
  1203. }
  1204. };
  1205. // Text
  1206. // 變更或取得選擇器元素的內容文字。
  1207. ts.fn.text = {
  1208. value: function(text) {
  1209. var ref;
  1210. if (text !== void 0) {
  1211. return this.each(function() {
  1212. return this.innerText = text;
  1213. });
  1214. } else {
  1215. return (ref = this.get()) != null ? ref.innerText : void 0;
  1216. }
  1217. }
  1218. };
  1219. // Val
  1220. // 變更或取得選擇器元素的值。
  1221. ts.fn.val = {
  1222. value: function(value) {
  1223. var ref;
  1224. if (value !== void 0) {
  1225. return this.each(function() {
  1226. return this.value = value;
  1227. });
  1228. } else {
  1229. return (ref = this.get()) != null ? ref.value : void 0;
  1230. }
  1231. }
  1232. };
  1233. // HTML
  1234. // 變更或取得選擇器元素的 HTML。
  1235. ts.fn.html = {
  1236. value: function(html) {
  1237. var ref;
  1238. if (html !== void 0) {
  1239. return this.each(function() {
  1240. return this.innerHTML = html;
  1241. });
  1242. } else {
  1243. return (ref = this.get()) != null ? ref.innerHTML : void 0;
  1244. }
  1245. }
  1246. };
  1247. // Empty
  1248. // 將選擇器元素的內容清除,例如值或文字。
  1249. ts.fn.empty = {
  1250. value: function() {
  1251. return this.each(function() {
  1252. if (this.value !== void 0) {
  1253. this.value = null;
  1254. }
  1255. if (this.innerHTML !== void 0) {
  1256. this.innerHTML = null;
  1257. }
  1258. if (this.innerText !== void 0) {
  1259. return this.innerText = null;
  1260. }
  1261. });
  1262. }
  1263. };
  1264. // Prop
  1265. // 變更或取得選擇器元素的屬性,例如 `.src`、`.width`。
  1266. ts.fn.prop = {
  1267. value: function(name, value) {
  1268. var key, ref;
  1269. // 有 name 也有 value 就設置屬性。
  1270. if (typeof name === 'string' && value !== void 0) {
  1271. return this.each(function() {
  1272. return this[name] = value;
  1273. });
  1274. // 有 name 但沒有 value 就取得屬性。
  1275. } else if (typeof name === 'string' && value === void 0) {
  1276. return (ref = this.get()) != null ? ref[name] : void 0;
  1277. // 有 name 但他是 object,就設置多重屬性。
  1278. } else if (typeof name === 'object') {
  1279. for (key in name) {
  1280. this.each(function() {
  1281. return this[key] = name[key];
  1282. });
  1283. }
  1284. return this;
  1285. }
  1286. }
  1287. };
  1288. // Data
  1289. // 在選擇器元素中存放資料,類似 Attr 但頁面不可見。
  1290. ts.fn.data = {
  1291. value: function(name, value) {
  1292. var key, ref, ref1;
  1293. // 有 name 也有 value 就設置資料。
  1294. if (typeof name === 'string' && value !== void 0) {
  1295. return this.each(function() {
  1296. if (this.$data === void 0) {
  1297. this.$data = {};
  1298. }
  1299. return this.$data[name] = value;
  1300. });
  1301. // 有 name 但沒有 value 就取得資料。
  1302. } else if (typeof name === 'string' && value === void 0) {
  1303. return (ref = this.get()) != null ? (ref1 = ref.$data) != null ? ref1[name] : void 0 : void 0;
  1304. // 有 name 但他是 object,就設置多重樣式。
  1305. } else if (typeof name === 'object') {
  1306. for (key in name) {
  1307. this.each(function() {
  1308. if (this.$data === void 0) {
  1309. this.$data = {};
  1310. }
  1311. return this.$data[key] = name[key];
  1312. });
  1313. }
  1314. return this;
  1315. }
  1316. }
  1317. };
  1318. // Remove Data
  1319. // 移除指定的資料。
  1320. ts.fn.removeData = {
  1321. value: function(name) {
  1322. return this.each(function() {
  1323. if (this.$data[name] != null) {
  1324. return delete this.$data[name];
  1325. }
  1326. });
  1327. }
  1328. };
  1329. // Has Timer
  1330. // 確認是否有指定的計時器。
  1331. ts.fn.hasTimer = {
  1332. value: function(name) {
  1333. var ref, ref1;
  1334. return ((ref = this.get(0)) != null ? (ref1 = ref.$timers) != null ? ref1[name] : void 0 : void 0) != null;
  1335. }
  1336. };
  1337. // Get Timer
  1338. // 取得計時器內容。
  1339. ts.fn.getTimer = {
  1340. value: function(name) {
  1341. var ref, ref1;
  1342. return (ref = this.get(0)) != null ? (ref1 = ref.$timers) != null ? ref1[name] : void 0 : void 0;
  1343. }
  1344. };
  1345. // Set Timer
  1346. // 設置一個新的計時器。
  1347. ts.fn.setTimer = {
  1348. value: function(options) {
  1349. return setTimeout(() => {
  1350. options = {...{
  1351. name: '',
  1352. callback: function() {},
  1353. interval: 0,
  1354. looping: false,
  1355. visible: false
  1356. }, ...options};
  1357. return this.each(function() {
  1358. var timer;
  1359. if (this.$timers === void 0) {
  1360. this.$timers = {};
  1361. }
  1362. if (this.$timers[options.name] !== void 0) {
  1363. clearInterval(this.$timers[options.name].timer);
  1364. }
  1365. timer = () => {
  1366. var ref;
  1367. // 當設置有說明,頁面不可見的時候就不要繼續計時。
  1368. if (options.visible && document.hidden) {
  1369. return;
  1370. }
  1371. // 替計時器加上 10 毫秒。
  1372. this.$timers[options.name].passed += 10;
  1373. // 如果計時器的經過時間還不到使用者設定的時間
  1374. // 就返回而不要繼續執行。
  1375. if (this.$timers[options.name].passed < options.interval) {
  1376. return;
  1377. }
  1378. // 呼叫回呼函式。
  1379. options.callback();
  1380. // 如果要循環的話,就在計時器執行後重設時間即可。
  1381. if (options.looping) {
  1382. return this.$timers[options.name].passed = 0;
  1383. } else {
  1384. // 不然就移除計時器資訊。
  1385. return clearInterval((ref = this.$timers[options.name]) != null ? ref.timer : void 0);
  1386. }
  1387. };
  1388. // 移除在 DOM 元素內的這個計時器物件。
  1389. //delete @$timers[options.name]
  1390. // 在此元素內初始化計時器物件。
  1391. return this.$timers[options.name] = {
  1392. timer: setInterval(timer, 10),
  1393. passed: 0,
  1394. callback: options.callback,
  1395. interval: options.interval,
  1396. looping: options.looping,
  1397. visible: options.visible,
  1398. initializer: timer,
  1399. paused: false
  1400. };
  1401. });
  1402. }, 0);
  1403. }
  1404. };
  1405. // Pause Timer
  1406. // 暫停一個計時器。
  1407. ts.fn.pauseTimer = {
  1408. value: function(name) {
  1409. return this.each(function() {
  1410. var ref;
  1411. if (((ref = this.$timers) != null ? ref[name] : void 0) == null) {
  1412. return;
  1413. }
  1414. // 清除計數計時器達到暫停效果。
  1415. clearInterval(this.$timers[name].timer);
  1416. // 表示暫停。
  1417. return this.$timers[name].paused = true;
  1418. });
  1419. }
  1420. };
  1421. // Play Timer
  1422. // 重啟一個計時器。
  1423. ts.fn.playTimer = {
  1424. value: function(name) {
  1425. return this.each(function() {
  1426. var ref;
  1427. if (((ref = this.$timers) != null ? ref[name] : void 0) == null) {
  1428. return;
  1429. }
  1430. if (!this.$timers[name].paused) {
  1431. return;
  1432. }
  1433. // 重新初始化計數計時器來達到繼續的效果。
  1434. this.$timers[name].timer = setInterval(this.$timers[name].initializer, 10);
  1435. // 表示重新啟動。
  1436. return this.$timers[name].paused = false;
  1437. });
  1438. }
  1439. };
  1440. // Remove Timer
  1441. // 移除一個計時器。
  1442. ts.fn.removeTimer = {
  1443. value: function(name) {
  1444. return this.each(function() {
  1445. var ref;
  1446. if (((ref = this.$timers) != null ? ref[name] : void 0) == null) {
  1447. return;
  1448. }
  1449. // 清除計數計時器。
  1450. clearInterval(this.$timers[name].timer);
  1451. // 移除在 DOM 元素內的計時器物件。
  1452. return delete this.$timers[name];
  1453. });
  1454. }
  1455. };
  1456. // Repaint
  1457. // 讓瀏覽器重繪元素。
  1458. ts.fn.repaint = {
  1459. value: function() {
  1460. return this.each(function() {
  1461. return void(this.offsetHeight);
  1462. });
  1463. }
  1464. };
  1465. // Unique ID
  1466. // 取得為此元素而產生的獨立編號,若無則建立。
  1467. ts.fn.uniqueID = {
  1468. value: function() {
  1469. var id;
  1470. id = this.get(0).$uniqueID;
  1471. if (id) {
  1472. return id;
  1473. }
  1474. this.get(0).$uniqueID = (Math.random().toString(16) + '000000000').substr(2, 8);
  1475. return this.get(0).$uniqueID;
  1476. }
  1477. };
  1478. }).call(this);