JMUL

utilities for monkey scripts

此腳本不應該直接安裝,它是一個供其他腳本使用的函式庫。欲使用本函式庫,請在腳本 metadata 寫上: // @require https://update.cn-greasyfork.org/scripts/31793/209567/JMUL.js

  1. // ==UserScript==
  2. // @name JMUL
  3. // @name:zh-CN 自用脚本工具库
  4. // @namespace https://greasyfork.org/users/34556
  5. // @version 0.1.2
  6. // @description utilities for monkey scripts
  7. // @description:zh-CN 工具库
  8. // @author jferroal
  9. // @grant GM_xmlhttpRequest
  10. // ==/UserScript==
  11.  
  12. (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){
  13. function selectable(je) {
  14. je.select = select;
  15. je.getSelection = getSelection;
  16. je.copyToClipboard = copyToClipboard;
  17. return je;
  18. function select(start, end) {
  19. if (!je.element.focus) {
  20. console.error('this element can not be selected.');
  21. }
  22. je.element.focus();
  23. start = !!start ? start : 0;
  24. end = !!end ? end : -1;
  25. je.element.setSelectionRange(start, end);
  26. }
  27.  
  28. function getSelection(start, end) {
  29. start = !start ? 0 : start;
  30. // default will get the selected text
  31. let result = String.prototype.slice.apply(document.getSelection(), [start, end]);
  32. // if not selected, get current element's text
  33. if (!result) {
  34. this.select(start, end);
  35. result = String.prototype.slice.apply(document.getSelection(), [start, end === -1 ? end += 1 : end]);
  36. }
  37. return result;
  38. }
  39.  
  40. function copyToClipboard(start, end) {
  41. start = !start ? 0 : start;
  42. document.getSelection().removeAllRanges();
  43. const range = document.createRange();
  44. range.setStart(je.element, start);
  45. range.setEnd(je.element, end);
  46. range.selectNode(je.element);
  47. document.getSelection().addRange(range);
  48. try {
  49. document.execCommand('copy');
  50. } catch (err) {
  51. console.error('Oops, unable to copy');
  52. }
  53. document.getSelection().removeAllRanges();
  54. }
  55. }
  56.  
  57. function addParser(request, parser) {
  58. request.parse = parse;
  59. request.sendAndParse = function () {
  60. return request.send().then((responseText) => {
  61. return parse(responseText);
  62. });
  63. };
  64. return request;
  65.  
  66. function parse(responseText) {
  67. return new Promise((resolve) => {
  68. const result = {};
  69. for (const key of Object.keys(parser.rules)) {
  70. result[key] = parser.rules[key](responseText);
  71. }
  72. resolve(result);
  73. });
  74. }
  75. }
  76.  
  77. module.exports = {
  78. selectable: selectable,
  79. addParser: addParser,
  80. };
  81. },{}],2:[function(require,module,exports){
  82. function toArray(s) {
  83. return Array.from(s, (v) => v);
  84. }
  85.  
  86. class JMElement {
  87. constructor(tagOrElement) {
  88. this.element = tagOrElement;
  89. if (typeof tagOrElement === 'string') {
  90. this.element = document.createElement(tagOrElement);
  91. }
  92. }
  93.  
  94. setAttribute(attrName, value) {
  95. this.element.setAttribute(attrName, value);
  96. }
  97.  
  98. getAttribute(attrName) {
  99. return this.element.getAttribute(attrName);
  100. }
  101.  
  102. setStyle(styleName, value) {
  103. this.element.style[styleName] = value;
  104. }
  105.  
  106. setCss(styles) {
  107. if (!styles) return;
  108. for (const styleName in styles) {
  109. if (!styles.hasOwnProperty(styleName)) return;
  110. this.setStyle(styleName, styles[styleName]);
  111. }
  112. }
  113.  
  114. setInnerHTML(value) {
  115. this.element.innerHTML = value;
  116. }
  117. setInnerText(value) {
  118. this.element.innerText = value;
  119. }
  120.  
  121. setId(id) {
  122. this.setAttribute('id', id);
  123. }
  124.  
  125. _setClass(_class) {
  126. this.setAttribute('class', _class);
  127. }
  128.  
  129. addClass(newClass) {
  130. const oldClassStr = this.getAttribute('class');
  131. if (oldClassStr.indexOf(newClass) < 0) {
  132. this._setClass(oldClassStr + ' ' + newClass);
  133. }
  134. return this;
  135. }
  136.  
  137. removeClass(className) {
  138. const oldClassStr = this.getAttribute('class');
  139. const idx = oldClassStr.indexOf(className);
  140. if (idx > -1) {
  141. const tmp = toArray(oldClassStr);
  142. tmp.splice(idx, className.length);
  143. this._setClass(tmp.join(''));
  144. }
  145. return this;
  146. }
  147.  
  148. get innerHTML() {
  149. return this.element.innerHTML;
  150. }
  151.  
  152. get innerText() {
  153. return this.element.innerText;
  154. }
  155.  
  156. setValue(value) {
  157. this.element.value = value;
  158. }
  159.  
  160. position(type) {
  161. const rect = this.element.getBoundingClientRect();
  162. switch (type) {
  163. case 'left-top':
  164. return {x: rect.left, y: rect.top};
  165. case 'right-top':
  166. return {x: rect.right, y: rect.top};
  167. case 'left-bottom':
  168. return {x: rect.left, y: rect.bottom};
  169. case 'right-bottom':
  170. return {x: rect.right, y: rect.bottom};
  171. case 'center':
  172. return {x: rect.left + rect.height / 2, y: rect.top + rect.height / 2};
  173. }
  174. }
  175.  
  176. appendTo(parent) {
  177. parent.appendChild(this.element);
  178. }
  179.  
  180. appendChild(child) {
  181. this.element.appendChild(child.element || child);
  182. }
  183.  
  184. listen(eventName, fn) {
  185. JMElement.addEvent(this.element, eventName, fn);
  186. }
  187.  
  188. toString() {
  189. return this.element.toString();
  190. }
  191.  
  192. valueOf() {
  193. return this.element;
  194. }
  195.  
  196. get value() {
  197. return this.element.value;
  198. }
  199.  
  200. static query(selector, index) {
  201. const els = document.querySelectorAll(selector);
  202. if (!els) throw new Error('element not found. ');
  203. if (index === -1) return els.map((el) => new JMElement(el));
  204. if (index === undefined) return new JMElement(els[0]);
  205. if (els.length < index + 1) throw new Error('index element not found. ');
  206. return new JMElement(els[index]);
  207. }
  208.  
  209. static addEvent(element, eventName, fn) {
  210. element.addEventListener(eventName, fn, false);
  211. }
  212.  
  213. static getSelectedPosition(type = 'left-top') {
  214. const focusNode = document.getSelection().focusNode;
  215. if (!focusNode) throw new Error('no selection, should not create node');
  216. const focusParentElement = focusNode.parentElement;
  217. return (new JMElement(focusParentElement)).position(type);
  218. }
  219. }
  220.  
  221. module.exports = JMElement;
  222.  
  223.  
  224. },{}],3:[function(require,module,exports){
  225. (function() {
  226. window.JMUL = {
  227. Element: require('./element'),
  228. Decorator: require('./decorator'),
  229. Request: require('./request').Request,
  230. Header: require('./request').Header,
  231. Parser: require('./parser'),
  232. UI: require('./ui/main'),
  233. };
  234. })();
  235. },{"./decorator":1,"./element":2,"./parser":4,"./request":5,"./ui/main":7}],4:[function(require,module,exports){
  236.  
  237. const helper = {
  238. isEmpty: a => !a || !a.length,
  239. toArray: s => Array.from(s, (v) => v),
  240. };
  241.  
  242. class JMXMLResult {
  243. constructor(tagName, innerText, matches) {
  244. this.tagName = tagName;
  245. this.innerText = innerText;
  246. this.matches = matches;
  247. }
  248. }
  249.  
  250. class JMParser {
  251. constructor() {
  252. this.rules = {};
  253. this.filters = {};
  254. }
  255.  
  256. addRule(key, pattern) {
  257. const tmp = {
  258. tagName: '',
  259. attrName: '',
  260. attrValue: '',
  261. prevCh: '',
  262. filterName: '',
  263. filterParams: [],
  264. currentFilterParams: ''
  265. };
  266. this.rules[key] = helper.toArray(pattern).reduce((res, ch, idx) => {
  267. switch (ch) {
  268. case ' ':
  269. break;
  270. case '(':
  271. tmp.prevCh = ch;
  272. break;
  273. case '@':
  274. if (!tmp.tagName) throw new Error('No tagName. ');
  275. tmp.prevCh = ch;
  276. break;
  277. case ')':
  278. res = JMParser.generate(tmp.tagName, JMParser.attr(tmp.attrName, tmp.attrValue));
  279. tmp.prevCh = tmp.tagName = tmp.attrName = tmp.attrValue = '';
  280. break;
  281. case '|':
  282. tmp.prevCh = '|';
  283. const filter = this.filters[tmp.filterName];
  284. if (filter) {
  285. res = filter(res, ...tmp.filterParams);
  286. }
  287. tmp.filterName = tmp.currentFilterParams = '';
  288. tmp.filterParams = [];
  289. break;
  290. case ',':
  291. tmp.prevCh = ',';
  292. if (tmp.currentFilterParams) {
  293. tmp.filterParams.push(tmp.currentFilterParams);
  294. }
  295. tmp.currentFilterParams = '';
  296. break;
  297. default:
  298. if (tmp.prevCh === '@') {
  299. tmp.attrName += ch;
  300. } else if (tmp.prevCh === '(') {
  301. tmp.attrValue += ch;
  302. } else if(tmp.prevCh === '|') {
  303. tmp.filterName += ch;
  304. } else if (tmp.prevCh === ',') {
  305. tmp.currentFilterParams += ch;
  306. } else {
  307. tmp.tagName += ch;
  308. }
  309. break;
  310. }
  311. return res;
  312. }, undefined);
  313. }
  314.  
  315. addFilter(name, fn) {
  316. this.filters[name] = (prevFn, ...params) => {
  317. return (responseText) => {
  318. const parseRes = prevFn(responseText);
  319. return fn(parseRes, ...params);
  320. }
  321. }
  322. }
  323.  
  324. static generate(tagName, attr) {
  325. const pattern = JMParser.tag(tagName, attr);
  326. return (responseText) => {
  327. const allMatch = responseText.match(pattern);
  328. if (helper.isEmpty(allMatch)) return {found: false};
  329. return allMatch.reduce((res, matchItem) => {
  330. const execRes = pattern.exec(matchItem);
  331. pattern.lastIndex = 0;
  332. const matchRes = execRes && execRes.slice(1) || [];
  333. return res.concat([new JMXMLResult(tagName, matchRes[1], matchRes)]);
  334. }, []);
  335. }
  336. }
  337.  
  338. static tag(name, attr) {
  339. return new RegExp(`${name}[\\s\\S]*?${attr}[\\s\\S]*?>([\\s\\S]*?)<\/${name}>`, 'gi');
  340. }
  341.  
  342. static attr(name, value) {
  343. return `${name}="(${value})"`;
  344. }
  345. }
  346.  
  347. module.exports = JMParser;
  348. },{}],5:[function(require,module,exports){
  349. GM_xmlhttpRequest = window.GM_xmlhttpRequest;
  350.  
  351. const FnMethodNameMap = {
  352. 'abort': 'onabort',
  353. 'failed': 'onerror',
  354. 'fail': 'onerror',
  355. 'error': 'onerror',
  356. 'loaded': 'onload',
  357. 'load': 'onload',
  358. 'success': 'onload',
  359. 'onload': 'onload',
  360. 'progress': 'onprogress',
  361. 'onprogress': 'onprogress',
  362. 'ready': 'onreadystatechange',
  363. 'readystatechange': 'onreadystatechange',
  364. 'onreadystatechange': 'onreadystatechange',
  365. 'timeout': 'ontimeout',
  366. 'ontimeout': 'ontimeout',
  367. };
  368.  
  369. const MethodNameMap = {
  370. 'get': 'GET',
  371. 'Get': 'GET',
  372. 'GET': 'GET',
  373. 'post': 'POST',
  374. 'Post': 'POST',
  375. 'POST': 'POST',
  376. 'head': 'HEAD',
  377. 'Head': 'HEAD',
  378. 'HEAD': 'HEAD',
  379. 'delete': 'DELETE',
  380. 'Delete': 'DELETE',
  381. 'DELETE': 'DELETE',
  382. 'patch': 'PATCH',
  383. 'Patch': 'PATCH',
  384. 'PATCH': 'PATCH',
  385. 'put': 'PUT',
  386. 'Put': 'PUT',
  387. 'PUT': 'PUT',
  388. };
  389.  
  390. class JMRequestHeader {
  391. constructor(headers) {
  392. if (headers instanceof JMRequestHeader) {
  393. headers = headers.value();
  394. }
  395. this.headerObj = headers;
  396. }
  397.  
  398. option(key, value) {
  399. this.headerObj[key] = value;
  400. return this;
  401. } // chain
  402. setAccept(value) {
  403. this._accept = this.headerObj.accept = value;
  404. return this;
  405. }
  406.  
  407. setAcceptCharset(value) {
  408. this.acceptCharset = this.headerObj['Accept-Charset'] = value;
  409. return this;
  410. }
  411.  
  412. setAcceptEncoding(value) {
  413. this.acceptEncoding = this.headerObj['Accept-Encoding'] = value;
  414. return this;
  415. }
  416.  
  417. setAge(value) {
  418. this.age = this.headerObj.age = value;
  419. return this;
  420. }
  421.  
  422. setAuthorization(value) {
  423. this.authorization = this.headerObj.Authorization = value;
  424. return this;
  425. }
  426.  
  427. setContentEncoding(value) {
  428. this.contentEncoding = this.headerObj['Content-Encoding'] = value;
  429. return this;
  430. }
  431.  
  432. setContentLength(value) {
  433. this.contentLength = this.headerObj['Content-Length'] = value;
  434. return this;
  435. }
  436.  
  437. setContentType(value) {
  438. this.contentType = this.headerObj['Content-Type'] = value;
  439. return this;
  440. }
  441.  
  442. setCookie(value) {
  443. this.cookie = this.headerObj.Cookie = value;
  444. return this;
  445. }
  446.  
  447. setUA(value) {
  448. this.ua = this.headerObj['User-Agent'] = value;
  449. return this;
  450. }
  451.  
  452. value() {
  453. return this.headerObj;
  454. }
  455. }
  456.  
  457. class JMRequest {
  458. constructor(options) {
  459. this._method = options.method && MethodNameMap[options.method] || 'GET';
  460. this._url = options.url || '';
  461. this.options = {};
  462. this.options.headers = new JMRequestHeader(options.headers || {});
  463. for (let key of Object.keys(options)) {
  464. if (FnMethodNameMap[key] && typeof options[key] === 'function') {
  465. this.options[FnMethodNameMap[key]] = options[key];
  466. }
  467. }
  468. this.options.data = this.handleRequestData(options.data)
  469. }
  470.  
  471. handleRequestData(data) {
  472. if (!data) return '';
  473. const contentType = this.options.headers.contentType;
  474. if (!contentType || contentType === 'application/json') {
  475. return JMRequest.toJsonData(data);
  476. } else if (contentType === 'application/x-www-form-urlencoded') {
  477. return JMRequest.toFormData(data);
  478. } else {
  479. // treat other as plain/text, do not support multipart/form-data
  480. return data.toString();
  481. }
  482. }
  483.  
  484. setMethod(_method) {
  485. this._method = MethodNameMap[_method];
  486. return this;
  487. }
  488.  
  489. setUrl(_url) {
  490. this._url = _url;
  491. return this;
  492. }
  493.  
  494. setHeaders(headers) {
  495. this.options.headers = headers;
  496. return this;
  497. }
  498.  
  499. setData(obj) {
  500. this.options.data = this.handleRequestData(obj);
  501. return this;
  502. }
  503.  
  504. load(fn) {
  505. this.options.onload = fn;
  506. return this;
  507. }
  508.  
  509. error(fn) {
  510. this.options.onerror = fn;
  511. return this;
  512. }
  513.  
  514. timeout(fn) {
  515. this.options.ontimeout = fn;
  516. return this;
  517. }
  518.  
  519. readyStateChange(fn) {
  520. this.options.onreadystatechange = fn;
  521. return this;
  522. }
  523.  
  524. abort(fn) {
  525. this.options.onabort = fn;
  526. return this;
  527. }
  528.  
  529. progress(fn) {
  530. this.options.onprogress = fn;
  531. return this;
  532. }
  533.  
  534. send() {
  535. return JMRequest.request(this._method, this._url, this.options);
  536. }
  537.  
  538. static toFormData(data) {
  539. if (typeof data === 'string') {
  540. return data;
  541. } else {
  542. let result = '';
  543. for (let key of Object.keys(data)) {
  544. result += key + '=' + data[key] + '&';
  545. }
  546. return result.slice(0, -1);
  547. }
  548. }
  549.  
  550. static toJsonData(data) {
  551. if (typeof data === 'object') {
  552. return JSON.stringify(data);
  553. } else {
  554. return data;
  555. }
  556. }
  557.  
  558. static request(method, url, options) {
  559. return new Promise((resolve, reject) => {
  560. GM_xmlhttpRequest({
  561. method: MethodNameMap[method],
  562. url: url,
  563. headers: options.headers.value(),
  564. data: options.data,
  565. onreadystatechange: (response) => {
  566. if (!options.onreadystatechange) return console.log('on ready state change. ');
  567. const fn = options.onreadystatechange;
  568. (!fn.then ? Promise.resolve(fn(response)) : fn(response)).then(function (res) {
  569. resolve(res);
  570. });
  571. },
  572. onabort: (response) => {
  573. if (!options.onabort) {
  574. console.error('on abort. ');
  575. reject({cause: 'abort'});
  576. } else {
  577. const fn = options.onabort;
  578. (!fn.then ? Promise.resolve(fn(response)) : fn(response)).then(function (res) {
  579. resolve(res);
  580. });
  581. }
  582.  
  583. },
  584. onerror: (response) => {
  585. if (!options.onerror) {
  586. console.error('on error. ');
  587. reject({cause: 'error', response: response});
  588. } else {
  589. const fn = options.onerror;
  590. (!fn.then ? Promise.resolve(fn(response)) : fn(response)).then(function (res) {
  591. resolve(res);
  592. });
  593. }
  594. },
  595. onprogress: (response) => {
  596. if (!options.onprogress) return console.log('on progress. ');
  597. const fn = options.onprogress;
  598. (!fn.then ? Promise.resolve(fn(response)) : fn(response)).then(function (res) {
  599. resolve(res);
  600. });
  601. }
  602. ,
  603. ontimeout: (response) => {
  604. if (!options.ontimeout) {
  605. console.error('on timeout. ');
  606. reject({cause: 'timeout', response: response});
  607. }
  608. const fn = options.ontimeout;
  609. (!fn.then ? Promise.resolve(fn(response)) : fn(response)).then(function (res) {
  610. resolve(res);
  611. });
  612. },
  613. onload: (response) => {
  614. if (!options.onload) {
  615. console.log('on load. ');
  616. resolve(response);
  617. } else {
  618. const fn = options.onload;
  619. (!fn.then ? Promise.resolve(fn(response)) : fn(response)).then(function (res) {
  620. resolve(res);
  621. });
  622. }
  623. },
  624. })
  625. });
  626. }
  627.  
  628. static get(url, options) {
  629. return JMRequest.request('GET', url, options);
  630. }
  631.  
  632. static post(url, options) {
  633. return JMRequest.request('POST', url, options);
  634. }
  635.  
  636. static put(url, options) {
  637. return JMRequest.request('PUT', url, options);
  638. }
  639.  
  640. static delete(url, options) {
  641. return JMRequest.request('DELETE', url, options);
  642. }
  643.  
  644. static head(url, options) {
  645. return JMRequest.request('HEAD', url, options);
  646. }
  647.  
  648. static patch(url, options) {
  649. return JMRequest.request('PATCH', url, options);
  650. }
  651. }
  652.  
  653. module.exports = {
  654. Request: JMRequest,
  655. Header: JMRequestHeader,
  656. };
  657. },{}],6:[function(require,module,exports){
  658. const JMElement = require('../element');
  659.  
  660. class BaseButton extends JMElement {
  661. constructor() {
  662. super('button');
  663. this.btnClickedStyleChangeTimeout = undefined;
  664. }
  665.  
  666. setNormalBtnBoxShadow() {
  667. this.setStyle('boxShadow', '0 0 2px 2px rgba(0, 0, 0, 0.08)');
  668. }
  669.  
  670. setClickedBtnBoxShadow() {
  671. this.setStyle('boxShadow', 'none');
  672. }
  673.  
  674. listenClick(fn) {
  675. this.listen('click', (e) => {
  676. this.setClickedBtnBoxShadow();
  677. if (this.btnClickedStyleChangeTimeout) {
  678. clearTimeout(this.btnClickedStyleChangeTimeout);
  679. this.btnClickedStyleChangeTimeout = null;
  680. }
  681. this.btnClickedStyleChangeTimeout = setTimeout(() => {
  682. this.setNormalBtnBoxShadow();
  683. }, 100);
  684. fn(e, this);
  685. })
  686. }
  687. }
  688. class IconButton {
  689. constructor(icon, size, clickFn) {
  690. this.button = new BaseButton();
  691. IconButton.initBtnStyle(this.button, typeof size === 'string' ? '128px' : size + 'px');
  692. this.image = new JMElement('img');
  693. this.image.setAttribute('src', icon);
  694. IconButton.initImageStyle(this.image);
  695. this.button.appendChild(this.image);
  696. this.button.listenClick(clickFn)
  697. }
  698.  
  699. appendTo(parent) {
  700. this.button.appendTo(parent);
  701. }
  702.  
  703. get element() {
  704. return this.button;
  705. }
  706.  
  707. static initBtnStyle(button, size) {
  708. button.setCss({
  709. position: 'relative',
  710. height: size,
  711. width: size,
  712. padding: '0',
  713. borderRadius: '50%',
  714. border: 'none',
  715. outline: 'none',
  716. });
  717. }
  718.  
  719. static initImageStyle(image) {
  720. image.setCss({
  721. width: '100%',
  722. height: '100%',
  723. borderRadius: '50%',
  724. cursor: 'pointer'
  725. })
  726. }
  727. }
  728.  
  729. class NormalButton {
  730. constructor(label, size, clickFn) {
  731. this.button = new BaseButton();
  732. NormalButton.initBtnStyle(this.button, NormalButton._handleSizeParam(size));
  733. this.label = new JMElement('p');
  734. NormalButton.initLabelStyle(this.label);
  735. this.label.innerText(label);
  736. this.button.appendChild(this.label);
  737. this.button.listenClick(clickFn)
  738. }
  739.  
  740. appendTo(parent) {
  741. this.button.appendTo(parent);
  742. }
  743.  
  744. get element() {
  745. return this.button;
  746. }
  747.  
  748. static initBtnStyle(button, size) {
  749. button.setCss({
  750. height: size.height || '24px',
  751. width: '64px',
  752. borderRadius: '4px',
  753. border: 'none',
  754. backgroundColor: 'skyblue',
  755. cursor: 'pointer',
  756. outline: 'none',
  757. });
  758. }
  759.  
  760. static initLabelStyle(label) {
  761. label.setCss({
  762. fontSize: '12px',
  763. color: 'rgba(255, 255,255, 0.87)',
  764. lineHeight: '100%',
  765. margin: '0',
  766. });
  767. }
  768.  
  769. static _handleSizeParam(size) {
  770. switch (typeof size) {
  771. case 'object':
  772. return {
  773. height: typeof size.height === 'string' ? size.height : size.height + 'px',
  774. width: typeof size.width === 'string' ? size.width : size.width + 'px',
  775. };
  776. case 'string':
  777. return {height: size, width: size};
  778. case 'number':
  779. return {height: size + 'px', width: size + 'px'};
  780. }
  781. }
  782. }
  783.  
  784. class JMButtonFactory {
  785. constructor() {
  786. if (!JMButtonFactory.ButtonFactory) {
  787. JMButtonFactory.ButtonFactory = this;
  788. }
  789. return JMButtonFactory.ButtonFactory;
  790. }
  791.  
  792. static create(type, iconOrLabel, size, clickFn) {
  793. switch (type) {
  794. case 'icon':
  795. return new IconButton(iconOrLabel, size, clickFn);
  796. case 'normal':
  797. default:
  798. return new NormalButton(iconOrLabel, size, clickFn);
  799. }
  800. }
  801. }
  802. JMButtonFactory.ButtonFactory = null;
  803.  
  804. module.exports = JMButtonFactory;
  805.  
  806. },{"../element":2}],7:[function(require,module,exports){
  807. module.exports = {
  808. Button: require('./button')
  809. }
  810. },{"./button":6}]},{},[3]);