CKTools

A library by CKylinMC combined all usually-used script segments.

此脚本不应直接安装,它是一个供其他脚本使用的外部库。如果您需要使用该库,请在脚本元属性加入:// @require https://update.gf.qytechs.cn/scripts/429720/1082330/CKTools.js

  1. // ==UserScript==
  2. // @name CKTools
  3. // @namespace ckylin-script-lib-combined-tools
  4. // @version 1.6.1
  5. // @match http://*
  6. // @match https://*
  7. // @author CKylinMC
  8. // @license GPLv3 License
  9. // ==/UserScript==
  10. (function () {
  11. const VERSION = 1.6;
  12. if ('CKTools' in window) {
  13. if (!window.CKTools.ver) console.warn('Unrecognized version of CKTools is already loaded, overwriting...');
  14. else if (window.CKTools.ver > VERSION) throw new Error("You have newer version CKTools loaded. Aborting loading version " + VERSION);
  15. else console.warn(`You have older version of CKTools (${window.CKTools.ver}) was loaded, and now upgrading to newer version ${VERSION}.`);
  16. }
  17. class CKTools {
  18. static ver = VERSION
  19. static get(q, base = document) {
  20. return base.querySelector(q);
  21. }
  22. static getAll(q, base = document) {
  23. return [...base.querySelectorAll(q)];
  24. }
  25. static domHelper(options = {}, compatibleParm2 = {}) {
  26. let tagName = 'div';
  27. if (typeof (options) == 'string') {
  28. /* Migrate from version 1 */
  29. tagName = options;
  30. /* Migrate from makeDom */
  31. if (compatibleParm2.constructor.name == 'Object') options = compatibleParm2;
  32. else if (compatibleParm2.constructor.name == 'AsyncFunction') options = {
  33. initAsync: compatibleParm2
  34. };
  35. else if (compatibleParm2.constructor.name == 'Function') options = {
  36. init: compatibleParm2
  37. };
  38. else options = {};
  39. }
  40. if (options.listeners) {
  41. /* Migrate from version 1 */
  42. if (!options.on) options.on = {};
  43. Object.assign(options.on, options.listeners);
  44. }
  45. if (options.classnames) {
  46. /* Migrate from version 1 */
  47. if (!options.classList) options.classList = [];
  48. options.classList.concat(options.classnames);
  49. }
  50. if (options.tag) tagName = options.tag;
  51. let el;
  52. if (options.from) {
  53. if (options.from instanceof HTMLElement) {
  54. el = options.from;
  55. } else if (typeof (options.from) == "string") {
  56. els = domHelper(tagName, {
  57. html: options.from
  58. });
  59. if (els.childElementCount === 0) {
  60. el = document.createElement(tagName);
  61. } else if (els.childElementCount === 1) {
  62. el = els.firstElementChild;
  63. } else {
  64. el = els;
  65. }
  66. }
  67. } else if (options.query) {
  68. const query = document.querySelector(options.query);
  69. if (query) el = query;
  70. else return null;
  71. } else el = document.createElement(tagName);
  72. if (options.id) el.id = options.id;
  73. if (options.html) el.innerHTML = options.html;
  74. if (options.text) el.innerText = options.text;
  75. if (options.attr) {
  76. for (const ak of Object.keys(options.attr)) {
  77. el.setAttribute(ak, options.attr[ak]);
  78. }
  79. }
  80. if (options.cssText) el.style.cssText = options.cssText;
  81. if (options.style) Object.assign(el.style, options.style);
  82. if (options.css) Object.assign(el.style, options.css);
  83. if (options.childs) {
  84. if (options.childs instanceof Array) options.childs.filter(el => !!el).forEach(child => {
  85. if (child instanceof HTMLElement) el.appendChild(child);
  86. else if (child.hasOwnProperty('type') && child.hasOwnProperty('content')) {
  87. switch (child.type) {
  88. case 'html': {
  89. arguments.callee('span', {
  90. from: child.content,
  91. append: el
  92. });
  93. }
  94. break;
  95. case 'style': {
  96. const scoped = child.hasOwnProperty('scoped') && !!child.scoped;
  97. arguments.callee('style', {
  98. html: child.content,
  99. append: el,
  100. attr: {
  101. scoped
  102. }
  103. });
  104. }
  105. break;
  106. default:
  107. el.appendChild(arguments.callee(child.type, child.content));
  108. }
  109. } else el.appendChild(document.createTextNode(child));
  110. });
  111. else if (options.childs instanceof HTMLElement) el.appendChild(options.childs);
  112. else el.appendChild(document.createTextNode(options.childs));
  113. }
  114. if (options.classlist) {
  115. if (options.classlist instanceof Array) options.classlist.forEach(classname => {
  116. el.classList.add(classname);
  117. });
  118. else el.classList.add(...options.classlist.split(" "));
  119. }
  120. if (options.classList) {
  121. if (options.classList instanceof Array) options.classList.forEach(classname => {
  122. el.classList.add(classname);
  123. });
  124. else el.classList.add(...options.classList.split(" "));
  125. }
  126. if (options.on) {
  127. for (let listenerName of Object.keys(options.on)) {
  128. el.addEventListener(listenerName, options.on[listenerName]);
  129. }
  130. }
  131. if (options.off) {
  132. for (let listenerName of Object.keys(options.of)) {
  133. el.removeEventListener(listenerName, options.off[listenerName]);
  134. }
  135. }
  136. if (options.bind) {
  137. const serverName = "$bindingserver" + Math.floor(Math.random() * 100000);
  138. const bindings = CKTools.deepClone(options.bind);
  139. const unbindProperty = (prop) => bindings[prop] = undefined;
  140. const unbindAllProperties = () => el[serverName].disconnect();
  141. el[serverName] = new MutationObserver(mutations => {
  142. for (const mutation in mutations) {
  143. if (bindings.hasOwnProperty(mutation.attributeName)) {
  144. try {
  145. bindings[mutation.attributeName]({
  146. target: mutation.target,
  147. attributeName: mutation.attributeName,
  148. attributeNamespace: mutation.attributeNamespace,
  149. oldValue: mutation.oldValue,
  150. newValue: mutation.target.getAttribute(mutation.attributeName) || undefined,
  151. unbind: () => unbindProperty(mutation.attributeName),
  152. stopListen: () => (unbindAllProperties(), el[serverName] = undefined)
  153. });
  154. } catch (e) {}
  155. }
  156. }
  157. });
  158. el.addEventListener('DOMNodeRemoved', () => (unbindAllProperties(), el[serverName] = undefined));
  159. el[serverName].observe(el, {
  160. attributes: true,
  161. attributeOldValue: true
  162. });
  163. }
  164. if (options.append && options.append instanceof HTMLElement) options.append.appendChild(el);
  165. if (options.insertBefore && insertBefore instanceof HTMLElement) options.insertBefore.parentNode.insertBefore(el, options.insertBefore);
  166. if (options.insertAfter && insertAfter instanceof HTMLElement) options.insertAfter.parentNode.insertAfter(el, options.insertAfter);
  167. if (options.init && options.init instanceof Function) options.init(el);
  168. if (options.initAsync && options.initAsync instanceof Function) {
  169. return options.initAsync(el).then(() => el);
  170. }
  171. return el;
  172. }
  173. static makeDom() {
  174. console.warn('"makeDom" has been deprecated. Redirecting to "domHelper"...');
  175. return CKTools.domHelper(...arguments);
  176. }
  177. static addDom(item) {
  178. const make = (tag = 'div') => document.createElement(tag);
  179. const txt = (it = '') => document.createTextNode(it);
  180. class DOMItem {
  181. constructor(it = '') {
  182. this.setItem(it);
  183. }
  184. setItem(it = '') {
  185. if (typeof it === 'string' || it instanceof String) {
  186. this.el = txt(it);
  187. } else if (it instanceof HTMLElement) {
  188. this.el = it;
  189. } else this.el = txt(it.toString());
  190. if (!this.target) this.target = document.body;
  191. this.mode = 'child';
  192. return this;
  193. }
  194. inside(q = document.body) {
  195. this.mode = 'child';
  196. if (q instanceof HTMLElement) {
  197. this.target = q;
  198. } else if (typeof q === 'string' || q instanceof String) {
  199. const ql = this.target.querySelector(q);
  200. if (ql) this.target = ql;
  201. }
  202. return this;
  203. }
  204. after(a = null) {
  205. this.mode = 'child-after';
  206. if (a instanceof HTMLElement) {
  207. this.after = a;
  208. } else if (typeof a === 'string' || a instanceof String) {
  209. const al = this.target.querySelector(a);
  210. if (al) this.after = al;
  211. }
  212. return this;
  213. }
  214. before(a = null) {
  215. this.mode = 'child-before';
  216. if (a instanceof HTMLElement) {
  217. this.before = a;
  218. } else if (typeof a === 'string' || a instanceof String) {
  219. const al = this.target.querySelector(a);
  220. if (al) this.before = al;
  221. }
  222. return this;
  223. }
  224. done() {
  225. switch (this.mode) {
  226. case "child": {
  227. if (this.el && this.target)
  228. this.target.appendChild(this.el);
  229. }
  230. break;
  231. case "child-before": {
  232. if (this.el && this.target && this.before)
  233. this.target.insertBefore(this.el, this.before);
  234. }
  235. break;
  236. case "child-after": {
  237. if (this.el && this.target && this.after)
  238. this.target.insertBefore(this.el, this.after.nextSibling);
  239. }
  240. break;
  241. }
  242. }
  243. }
  244. return new DOMItem(item);
  245. }
  246. static deepClone(obj) {
  247. let newObject = {};
  248. if (Array.isArray(obj)) {
  249. newObject = [];
  250. for (let i = 0; i < obj.length; i++) {
  251. newObject.push(CKTools.deepClone(obj[i]));
  252. }
  253. return newObject;
  254. }
  255. Object.keys(obj).map(key => {
  256. if (typeof obj[key] === 'object') {
  257. newObject[key] = CKTools.deepClone(obj[key]);
  258. } else {
  259. newObject[key] = obj[key];
  260. }
  261. });
  262. return newObject;
  263. }
  264. static getCookie(name) {
  265. const value = `; ${document.cookie}`;
  266. const parts = value.split(`; ${name}=`);
  267. if (parts.length === 2) return parts.pop().split(';').shift();
  268. }
  269. static clearAllCookies() {
  270. return document.cookie.split(';').forEach(cookie => document.cookie = cookie.replace(/^ +/, '').replace(/=.*/, `=;expires=${new Date(0).toUTCString()};path=/`));
  271. }
  272. static getUrlParam(key) {
  273. return (new URL(location.href)).searchParams.get(key);
  274. }
  275. static wait(ms) {
  276. return new Promise(r => setTimeout(r, ms));
  277. }
  278. static async waitForDom(query, domparent = document, maxRetries = 20, gagms = 200) {
  279. let i = maxRetries;
  280. while (--i > 0) {
  281. if (domparent.querySelector(query)) return true;
  282. await CKTools.wait(gagms);
  283. }
  284. return false;
  285. }
  286. static async waitForAttribute(q, attr) {
  287. let i = 50;
  288. let value;
  289. while (--i >= 0) {
  290. if ((attr in q) &&
  291. q[attr] != null) {
  292. value = q[attr];
  293. break;
  294. }
  295. await wait(100);
  296. }
  297. return value;
  298. }
  299. static async waitForPageVisible() {
  300. if (document.hidden) return true;
  301. return new Promise(r => {
  302. const handler = () => {
  303. r(true);
  304. document.removeEventListener('visibilitychange', handler);
  305. };
  306. document.addEventListener("visibilitychange", handler)
  307. });
  308. }
  309. static clearStyles(className = "injectedStyle") {
  310. let dom = document.querySelectorAll("style." + className);
  311. if (dom)[...dom].forEach(e => e.remove());
  312. }
  313. static addStyle(s, className = "injectedStyle", mode = "append", injectBase = document.head) {
  314. switch (mode) {
  315. default:
  316. case "append":
  317. break;
  318. case "unique":
  319. if (document.querySelector("style." + className)) return;
  320. break;
  321. case "update":
  322. CKTools.clearStyles(className);
  323. break;
  324. }
  325. let style = document.createElement("style");
  326. style.classList.add(className);
  327. style.innerHTML = s;
  328. injectBase.appendChild(style);
  329. }
  330. // stackoverflow
  331. static debounce(func, timeout = 300) {
  332. let timer;
  333. return (...args) => {
  334. clearTimeout(timer);
  335. timer = setTimeout(() => {
  336. func.apply(this, args);
  337. }, timeout);
  338. };
  339. }
  340. static throttle(callback, limit) {
  341. var waiting = false;
  342. return function () {
  343. if (!waiting) {
  344. callback.apply(this, arguments);
  345. waiting = true;
  346. setTimeout(function () {
  347. waiting = false;
  348. }, limit);
  349. }
  350. }
  351. }
  352. static domContains(selector, text) {
  353. var elements = document.querySelectorAll(selector);
  354. return [].filter.call(elements, function (element) {
  355. return RegExp(text).test(element.textContent);
  356. });
  357. }
  358. static mapReplace(str, map) {
  359. //reference: https://segmentfault.com/q/1010000023489916 answer-2
  360. const replace = ({
  361. str,
  362. reg,
  363. replacer
  364. }) =>
  365. str.replace(new RegExp(reg, 'g'), replacer);
  366. return Object.keys(map).reduce((str, reg) => replace({
  367. str,
  368. reg,
  369. replacer: map[reg]
  370. }), str);
  371. }
  372. static padStart(num, count = 2) {
  373. return (('' + Math.pow(10, count)).substr(1) + num).slice(-1 * Math.max(count, ('' + num).length));
  374. }
  375. static fixNum(num, fix = 0) {
  376. return Math.floor(num * (Math.pow(10, fix))) / (Math.pow(10, fix));
  377. }
  378. static random = class {
  379. static hex() {
  380. return `#${Math.floor(Math.random() * 0xffffff).toString(16).padEnd(6, "0")}`;
  381. }
  382. static shuffleArray(arr) {
  383. return arr.sort(() => 0.5 - Math.random());
  384. }
  385. static num(min, max) {
  386. return Math.random() * (max - min) + min;
  387. }
  388. static fromArray(arr = []) {
  389. return arr[Math.floor(CKTools.random.num(0, arr.length))];
  390. }
  391. static from(...args) {
  392. return CKTools.random.fromArray(args);
  393. }
  394. }
  395. static is = class {
  396. static str(s) {
  397. return (s != null && (typeof s === "string" || s instanceof String));
  398. }
  399. static elementInViewport(el) {
  400. var rect = el.getBoundingClientRect();
  401. return (
  402. rect.top >= 0 &&
  403. rect.left >= 0 &&
  404. rect.bottom <= (window.innerHeight || document.documentElement.clientHeight) &&
  405. rect.right <= (window.innerWidth || document.documentElement.clientWidth)
  406. );
  407. }
  408. static asyncFn(fn) {
  409. return fn.constructor.name === "AsyncFunction";
  410. }
  411. static darkMode() {
  412. return window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches;
  413. }
  414. }
  415. static modal = class {
  416. static openModal(title = '', content) {
  417. CKTools.modal.blockWindow();
  418. let modal = CKTools.get("#CKTOOLS-modal");
  419. if (!modal) modal = CKTools.modal.initModal();
  420. modal.setTitle(title);
  421. modal.setContent(content);
  422. modal.show();
  423. }
  424. static isModalShowing() {
  425. let modal = CKTools.get("#CKTOOLS-modal");
  426. if (modal) return modal.classList.contains("show");
  427. else return false;
  428. }
  429. static hideModal() {
  430. CKTools.modal.blockWindow(false);
  431. let modal = CKTools.get("#CKTOOLS-modal");
  432. if (modal) modal.hide();
  433. }
  434. static initModal() {
  435. CKTools.addStyle(`
  436. #CKTOOLS-modal{
  437. position: fixed;
  438. z-index: 99010;
  439. top: 50%;
  440. left: 50%;
  441. width: 300px;
  442. width: 30vw;
  443. /*height: 300px;
  444. height: 50vh;*/
  445. background: white;
  446. border-radius: 8px;
  447. padding: 12px;
  448. transform: translate(-50%,-50%);
  449. transition: all .3s;
  450. box-shadow: 0 2px 8px grey;
  451. }
  452. #CKTOOLS-modal.show{
  453. opacity: 1;
  454. transform: translate(-50%,-50%) scale(1);
  455. }
  456. #CKTOOLS-modal.hide{
  457. opacity: 0;
  458. pointer-events: none;
  459. transform: translate(-50%,-50%) scale(0.9);
  460. }
  461. .CKTOOLS-modal-title{
  462. font-size: large;
  463. }
  464. .CKTOOLS-modal-content{
  465. font-size: medium;
  466. }
  467. .CKTOOLS-modal-content>div{
  468. display: flex;
  469. margin: 6px 10px;
  470. flex-wrap: wrap;
  471. flex-direction: column;
  472. align-content: space-around;
  473. justify-content: space-between;
  474. align-items: center;
  475. }
  476. .CKTOOLS-toolbar-btns{
  477. flex: 1;
  478. border: none;
  479. background: #2196f3;
  480. border-radius: 3px;
  481. margin: 0 6px;
  482. padding: 3px;
  483. color: white;
  484. box-shadow: 0 2px 3px grey;
  485. min-width: 60px;
  486. }
  487. .CKTOOLS-toolbar-btns:hover{
  488. filter: brightness(0.85);
  489. }
  490. `, "CKTOOLS-modal-css", "unique");
  491. const modal = document.createElement("div");
  492. modal.id = "CKTOOLS-modal";
  493. modal.className = "hide";
  494.  
  495. const header = document.createElement("h2");
  496. header.className = "CKTOOLS-modal-title"
  497. modal.appendChild(header);
  498.  
  499. modal.setTitle = (t = '') => {
  500. header.innerHTML = t;
  501. }
  502.  
  503. const contents = document.createElement("div");
  504. contents.className = "CKTOOLS-modal-content";
  505. modal.appendChild(contents);
  506.  
  507. modal.setContent = async (c) => {
  508. let ct = c;
  509. if (ct instanceof Function) {
  510. ct = await ct();
  511. }
  512. if (ct instanceof HTMLElement) {
  513. contents.innerHTML = '';
  514. contents.appendChild(ct);
  515. return;
  516. }
  517. if (typeof (ct) === "string") {
  518. contents.innerHTML = ct;
  519. return;
  520. }
  521. console.log("unknown: ", ct);
  522. }
  523. modal.addContent = async (c) => {
  524. let ct = c;
  525. if (ct instanceof Function) {
  526. ct = await ct();
  527. }
  528. if (ct instanceof HTMLElement) {
  529. contents.appendChild(ct);
  530. return;
  531. }
  532. if (ct instanceof String) {
  533. contents.innerHTML += ct;
  534. return;
  535. }
  536. console.log("unknown: ", ct);
  537. }
  538.  
  539. modal.close = CKTools.modal.closeModal;
  540. modal.open = CKTools.modal.openModal;
  541. modal.show = () => {
  542. modal.className = "show";
  543. }
  544. modal.hide = () => {
  545. modal.className = "hide";
  546. }
  547.  
  548. document.body.appendChild(modal);
  549. return modal;
  550. }
  551. static closeModal() {
  552. CKTools.modal.blockWindow(false);
  553. let modal = CKTools.get("#CKTOOLS-modal");
  554. if (modal) modal.remove();
  555. }
  556. static async alertModal(title = "", content = "", okbtn = null) {
  557. if (CKTools.modal.isModalShowing()) {
  558. CKTools.modal.hideModal();
  559. await CKTools.wait(200);
  560. }
  561. CKTools.modal.openModal(title, await CKTools.domHelper("div", async container => {
  562. container.appendChild(await CKTools.domHelper("div", tip => {
  563. tip.innerHTML = content;
  564. }))
  565. if (okbtn !== null)
  566. container.appendChild(await CKTools.domHelper("div", async btns => {
  567. btns.style.display = "flex";
  568. btns.appendChild(await CKTools.domHelper("button", btn => {
  569. btn.className = "CKTOOLS-toolbar-btns";
  570. btn.innerHTML = okbtn;
  571. btn.onclick = e => CKTools.modal.hideModal();
  572. }))
  573. }))
  574. }))
  575. await CKTools.wait(300);
  576. }
  577. static blockWindow(block = true) {
  578. CKTools.addStyle(`
  579. #CKTOOLS-blockWindow{
  580. z-index: 99005;
  581. display: block;
  582. background: #00000080;
  583. opacity: 0;
  584. transition: all .3s;
  585. position: fixed;
  586. left: 0;
  587. top: 0;
  588. width: 100vw;
  589. height: 100vh;
  590. }
  591. #CKTOOLS-blockWindow.hide{
  592. pointer-events: none;
  593. opacity: 0;
  594. }
  595. #CKTOOLS-blockWindow.show{
  596. opacity: 1;
  597. }
  598. `, "CKTOOLS-blockWindow-css", "unique");
  599. let dom = CKTools.get("#CKTOOLS-blockWindow");
  600. if (!dom) {
  601. dom = document.createElement("div");
  602. dom.id = "CKTOOLS-blockWindow";
  603. dom.className = "hide";
  604. document.body.appendChild(dom);
  605. }
  606. if (block) {
  607. dom.className = "show";
  608. } else {
  609. dom.className = "hide";
  610. }
  611. }
  612. }
  613. static bili = class {
  614. static getCSRFToken() {
  615. return CKTools.getCookie("bili_jct");
  616. }
  617. static async playerReady() {
  618. let i = 50;
  619. while (--i >= 0) {
  620. await CKTools.wait(100);
  621. if (!('player' in window)) continue;
  622. if (!('isInitialized' in window.player)) continue;
  623. if (!window.player.isInitialized()) continue;
  624. }
  625. if (i < 0) return false;
  626. await CKTools.waitForPageVisible();
  627. while (1) {
  628. await CKTools.wait(200);
  629. if (document.querySelector(".bilibili-player-video-control-wrap, .bpx-player-control-wrap")) return true;
  630. }
  631. }
  632. static getTotalTime() {
  633. return waitForAttribute(CKTools.get('video, bwp-video'), 'duration')||unsafeWindow.player?.getDuration();
  634. }
  635. static getCurrentTime() {
  636. return CKTools.get('video, bwp-video').currentTime||unsafeWindow.player?.getCurrentTime();
  637. }
  638. static setTime(t) {
  639. return window.player.seek(t);
  640. }
  641. static play() {
  642. return window.player.play();
  643. }
  644. static pause() {
  645. return window.player.pause();
  646. }
  647. static getInfoByBvid(bvid) {
  648. return fetch('https://api.bilibili.com/x/web-interface/view?bvid=' + bvid).then(raw => raw.json());
  649. }
  650. static getInfoByAid(aid) {
  651. return fetch('https://api.bilibili.com/x/web-interface/view?aid=' + aid).then(raw => raw.json());
  652. }
  653. }
  654. static EventEmitter = class {
  655. handlers = {};
  656. on(name, func) {
  657. if (!(func instanceof Function)) throw "Param must be func!";
  658. if (!(name in this.handlers)) {
  659. this.handlers[name] = [];
  660. }
  661. this.handlers[name].push(func);
  662. }
  663. off(name, func) {
  664. if (!(func instanceof Function)) throw "Param must be func!";
  665. if (name in this.handlers) {
  666. for (let i = 0; i < this.handlers[name].length; i++) {
  667. if (this.handlers[name][i] === func) {
  668. this.handlers[name].splice(i, 1);
  669. i--;
  670. }
  671. }
  672. }
  673. }
  674. clean(name) {
  675. if (name in this.handlers) {
  676. this.handlers[name] = [];
  677. }
  678. }
  679. emit(name, ...args) {
  680. if (name in this.handlers) {
  681. for (let func of this.handlers[name]) {
  682. try {
  683. func(...args);
  684. } catch (e) {
  685. console.error('ERROR:', e);
  686. }
  687. }
  688. }
  689. }
  690. }
  691. static HoldClick = class {
  692. dom;
  693. emitter = new CKTools.EventEmitter;
  694. downTime = 0;
  695. holdingTime = 250;
  696. mouseDown = false;
  697.  
  698. constructor(dom, holdingTime = 250) {
  699. this.bind(dom);
  700. this.holdingTime = holdingTime;
  701. }
  702.  
  703. bind(dom) {
  704. if (this.dom) {
  705. this.unregListeners();
  706. }
  707. if (dom instanceof HTMLElement) {
  708. this.dom = dom;
  709. this.initListener();
  710. }
  711. }
  712.  
  713. onclick(func) {
  714. this.emitter.on("click", func);
  715. return this;
  716. }
  717.  
  718. onhold(func) {
  719. this.emitter.on("hold", func);
  720. return this;
  721. }
  722.  
  723. onup(func) {
  724. this.emitter.on("up", func);
  725. return this;
  726. }
  727.  
  728. offclick(func) {
  729. this.emitter.off("click", func);
  730. return this;
  731. }
  732.  
  733. offhold(func) {
  734. this.emitter.off("hold", func);
  735. return this;
  736. }
  737.  
  738. offup(func) {
  739. this.emitter.off("up", func);
  740. return this;
  741. }
  742.  
  743. resetCallback(name = "all") {
  744. const allEv = ["click", "hold", "up"];
  745. if (name === "all") {
  746. allEv.forEach(e => this.emitter.clean(e));
  747. } else if (allEv.includes(name)) {
  748. this.emitter.clean(name);
  749. }
  750. }
  751.  
  752. unregListeners() {
  753. this.dom.removeEventListener("mouseup", this.handleMouseUp.bind(this));
  754. this.dom.removeEventListener("mousedown", this.handleMouseDown.bind(this));
  755. this.dom.removeEventListener("mouseout", this.handleMouseOut.bind(this));
  756. }
  757.  
  758. uninstall() {
  759. this.resetCallback();
  760. this.unregListeners();
  761. }
  762.  
  763. handleMouseDown(e) {
  764. if (e.button !== 0 && e.button !== 1) return;
  765. e.preventDefault();
  766. this.mouseDown = true;
  767. this.downTime = (new Date()).getTime();
  768. setTimeout(() => {
  769. if (this.mouseDown) {
  770. console.log(this);
  771. this.mouseDown = false;
  772. this.downTime = 0;
  773. this.emitter.emit("hold", e);
  774. }
  775. }, this.holdingTime)
  776. }
  777.  
  778. handleMouseUp(e) {
  779. if (e.button !== 0 && e.button !== 1) return;
  780. e.preventDefault();
  781. if (this.mouseDown) {
  782. this.mouseDown = false;
  783. const currTime = (new Date).getTime();
  784. if ((currTime - this.downTime) >= this.holdingTime) {
  785. this.emitter.emit("hold", e);
  786. } else {
  787. this.emitter.emit("click", e);
  788. }
  789. this.downTime = 0;
  790. }
  791. this.emitter.emit("up", e);
  792. }
  793.  
  794. handleMouseOut(e) {
  795. e.preventDefault();
  796. if (this.mouseDown) {
  797. this.mouseDown = false;
  798. this.downTime = 0;
  799. this.emitter.emit("hold", e);
  800. }
  801. }
  802.  
  803. initListener() {
  804. this.dom.addEventListener("mouseup", this.handleMouseUp.bind(this))
  805. this.dom.addEventListener("mousedown", this.handleMouseDown.bind(this))
  806. this.dom.addEventListener("mouseout", this.handleMouseOut.bind(this))
  807. }
  808. }
  809. static dragger = class {
  810. static defaultHandler(val) {
  811. return console.log("DRAG:", val);
  812. }
  813. static async waitForDragger(waitStatus = true) {
  814. while (CKTools.dragger.dragging !== waitStatus) await CKTools.wait(10);
  815. return CKTools.dragger;
  816. }
  817. static async regHandler(func) {
  818. if (!(func instanceof Function)) throw "Param must be a func!";
  819. await CKTools.dragger.waitForDragger(false);
  820. CKTools.dragger.handler = func;
  821. return CKTools.dragger;
  822. }
  823. static handler() {}
  824. static dragging = false;
  825. static initialDragData = {
  826. x: 0,
  827. y: 0
  828. }
  829. static lastDragData = {
  830. x: 0,
  831. y: 0
  832. }
  833. static startDrag(e) {
  834. if (CKTools.dragger.dragging) return;
  835. CKTools.dragger.dragging = true;
  836. console.log(CKTools.dragger.initialDragData);
  837. CKTools.dragger.initialDragData.x = e.screenX;
  838. CKTools.dragger.initialDragData.y = e.screenY;
  839. CKTools.dragger.lastDragData.x = e.screenX;
  840. CKTools.dragger.lastDragData.y = e.screenY;
  841. document.body.addEventListener("mouseup", CKTools.dragger.stopDrag);
  842. document.body.addEventListener("mousemove", CKTools.dragger.handleDrag);
  843. console.info("DRAG:", "Start Drag");
  844. return CKTools.dragger;
  845. }
  846. static handleDrag(e) {
  847. const currPos = {
  848. x: e.screenX,
  849. y: e.screenY
  850. };
  851. const initPos = CKTools.dragger.initialDragData;
  852. const delta = {
  853. x: initPos.x - currPos.x,
  854. y: initPos.y - currPos.y
  855. }
  856. const lastdelta = {
  857. x: CKTools.dragger.lastDragData.x - currPos.x,
  858. y: CKTools.dragger.lastDragData.y - currPos.y
  859. }
  860. CKTools.dragger.lastDragData = currPos;
  861. CKTools.dragger.handler(delta, lastdelta);
  862. }
  863. static stopDrag() {
  864. document.body.removeEventListener("mouseup", CKTools.dragger.stopDrag);
  865. document.body.removeEventListener("mousemove", CKTools.dragger.handleDrag);
  866. CKTools.dragger.handler = CKTools.dragger.defaultHandler;
  867. console.info("DRAG:", "Stop Drag");
  868. CKTools.dragger.dragging = false;
  869. return CKTools.dragger;
  870. }
  871. }
  872. static GUID = class {
  873. static S4() {
  874. return (((1 + Math.random()) * 0x10000) | 0).toString(16).substring(1);
  875. }
  876. static get() {
  877. let S4 = CKTools.GUID.S4;
  878. return (S4() + S4() + "-" + S4() + "-" + S4() + "-" + S4() + "-" + S4() + S4() + S4());
  879. }
  880. static getShort() {
  881. let S4 = CKTools.GUID.S4;
  882. return (S4() + S4() + S4() + S4());
  883. }
  884. }
  885. }
  886. window.CKTools = CKTools;
  887. })();

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址