vanilla-lib

Vanilla JS library

当前为 2018-07-16 提交的版本,查看 最新版本

此脚本不应直接安装。它是供其他脚本使用的外部库,要使用该库请加入元指令 // @require https://update.gf.qytechs.cn/scripts/369430/613140/vanilla-lib.js

  1. function VanillaLib( ) {
  2. 'use strict';
  3. let self = { version:'1.2.180702.0744' },
  4. undefined; // ensure an 'undefined' reference
  5.  
  6. // Logging related
  7. self.logging = true;
  8. self.logGroup = function( ) { return ! self.logging ? false : console.groupCollapsed.apply(console, arguments); };
  9. self.logEnd = function( ) { return ! self.logging ? false : console.groupEnd.apply(console, arguments); };
  10. self.time = function( ) { return ! self.logging ? false : console.time.apply(console, arguments); };
  11. self.timeEnd = function( ) { return ! self.logging ? false : console.timeEnd.apply(console, arguments); };
  12. self.warn = function( ) { return ! self.logging ? false : console.warn.apply(console, arguments); };
  13. self.log = function( ) { return ! self.logging ? false : console.debug.apply(console, arguments); };
  14. // Core functionality
  15. self.ownsIt = ( obj,prop ) => ( !! prop && self.isobj(obj, true) && obj.hasOwnProperty(prop) );
  16. self.hasval = expr => ( null !== expr && ! self.ndef(expr) );
  17. self.isbool = expr => ( 'boolean' === typeof expr );
  18. self.ifndef = ( expr,value ) => ( self.ndef(expr) ? value : expr );
  19. self.ifnan = ( expr,value ) => ( isNaN(expr) ? value : expr );
  20. self.isarr = expr => self.isobj(expr, Array);
  21. self.isnum = expr => ( 'number' === typeof expr );
  22. self.isstr = expr => ( 'string' === typeof expr );
  23. self.isfn = expr => ( 'function' === typeof expr );
  24. self.ndef = expr => ( 'undefined' === typeof expr );
  25. // Miscelaneous
  26. self.mapFlat = ( array,func ) => array.map( x => func(x) ).reduce( (a,b) => a.concat(b) );
  27. self.ispojo = expr => self.isobj(expr, Object);
  28. self.test = ( expr,func,other ) => ( !! expr ? func(expr) : self.isfn(other) ? other(expr) : other );
  29. // DOM related
  30. self.parenth = ( elem,nth ) => self.traverse(elem, self.ifndef(nth, 1), 0);
  31. self.html = ( elem,val ) => self.test(elem, el => self.ndef(val) ? el.innerHTML : (el.innerHTML = val) );
  32. self.text = ( elem,val ) => self.test(elem, el => self.ndef(val) ? el.innerText : (el.innerText = val) );
  33. self.$$ = ( sel,elem ) => Array.slice((elem || document).querySelectorAll(sel));
  34. self.$ = ( sel,elem ) => (elem || document).querySelector(sel);
  35. // Number related
  36. self.aggRate = ( amnt,rate,times ) => ( times < 1 ? amnt : self.aggRate(amnt * rate, rate, times - 1) );
  37. self.toDec = expr => ( Math.round(parseFloat((expr +'').replace(/\$|,/g, '')) * 100) / 100 );
  38. // Time related
  39. self.secondsIn = ( from,to,other ) => self.ifnan((to - from) / 1000, self.ifndef(other, NaN));
  40. self.minutesIn = ( from,to,other ) => self.ifnan((to - from) / 60000, self.ifndef(other, NaN));
  41. self.hoursIn = ( from,to,other ) => self.ifnan((to - from) / 3600000, self.ifndef(other, NaN));
  42. self.daysIn = ( from,to,other ) => self.ifnan((to - from) / 86400000, self.ifndef(other, NaN));
  43. self.secondsSince = ( from,other ) => self.secondsIn(from, Date.now(), other);
  44. self.minutesSince = ( from,other ) => self.minutesIn(from, Date.now(), other);
  45. self.hoursSince = ( from,other ) => self.hoursIn(from, Date.now(), other);
  46. self.daysSince = ( from,other ) => self.daysIn(from, Date.now(), other);
  47.  
  48.  
  49. self.addClass = function( element, name ) {
  50. if ( !! element && !! name ) {
  51. if ( self.isarr(element) ) {
  52. return element.map( elem => self.addClass(elem, name) );
  53. }
  54.  
  55. name = ( self.isarr(name) ? name : name.split(',') );
  56. name = name.map( nm => nm.trim() )
  57. .filter( nm => ! element.classList.contains(nm) );
  58. element.className = (element.className +' '+ name.join(' ')).trim();
  59. return true;
  60. }
  61. return false;
  62. };
  63.  
  64. self.appendTo = function( element, parent, reference ) {
  65. if ( !! reference ) {
  66. parent = reference.parentNode;
  67. reference = reference.nextSibling;
  68. }
  69.  
  70. if ( !! reference ) {
  71. return self.prependTo(element, parent, reference);
  72. } else if ( !! parent ) {
  73. parent.append(element);
  74. } else {
  75. self.warn('*** appendTo() could not add element: No parent or reference element provided');
  76. }
  77.  
  78. return element;
  79. };
  80.  
  81. self.attr = function( element, name, value ) {
  82. if ( !! element ) {
  83. if ( self.isarr(element) ) {
  84. return element.map( elem => self.attr(elem, name, value) );
  85. }
  86.  
  87. return self.keysAndValues(name, value, ( n,v ) => {
  88. return ( self.hasval(v) ? element.setAttribute(n, v)
  89. : null === v ? element.removeAttribute(n) : element.getAttribute(n) );
  90. } );
  91. }
  92. return element;
  93. };
  94.  
  95. self.choose = function( index, values ) {
  96. return Array.slice(arguments)[ index ];
  97. }
  98.  
  99. self.create = function( html, containerType ) {
  100. let container = null,
  101. result = null,
  102. attrs, style;
  103.  
  104. if ( self.isobj(containerType) ) {
  105. attrs = containerType.attrs;
  106. style = containerType.style;
  107. containerType = containerType.container;
  108. }
  109.  
  110. containerType = containerType || 'div';
  111. create[ containerType ] =
  112. container = self.create[ containerType ] || document.createElement(containerType);
  113. container.innerHTML = html;
  114. result = Array.slice(container.childNodes)
  115. .map( elem => (elem.remove(), elem) );
  116.  
  117. if ( !! attrs ) {
  118. self.attr(result, attrs);
  119. }
  120. if ( !! style ) {
  121. self.css(result, style);
  122. }
  123.  
  124. if ( 1 == result.length ) {
  125. result = result[ 0 ];
  126. }
  127. return result;
  128. };
  129.  
  130. self.createXHR = function( ) {
  131. let xhr = new XMLHttpRequest( );
  132. xhr.onabort = function( ev, xhr ) { self.log('XHR Abort:', ev, xhr, this); };
  133. xhr.onerror = function( ev, xhr ) { self.log('XHR Error:', ev, xhr, this); };
  134. xhr.onload = function( ev, xhr ) { self.log('XHR Load:', ev, xhr, this); };
  135. self.on(xhr, {
  136. 'abort': function( ev ) { self.isfn(this.onabort) && this.onabort(ev, this); },
  137. 'error': function( ev ) { self.isfn(this.onerror) && this.onerror(ev, this); },
  138. 'load': function( ev ) { self.isfn(this.onload) && this.onload(ev, this); },
  139. });
  140. return xhr;
  141. };
  142.  
  143. self.css = function( element, key, value ) {
  144. if ( isarr(element) ) {
  145. return element.map( el => css(el, key, value) );
  146. }
  147.  
  148. keysAndValues(key, value, ( k,v ) => element.style[ k ] = v );
  149. return element;
  150. };
  151.  
  152. self.extend = function( target, sources ) {
  153. for ( let i = 1, n = arguments.length; i < n; i ++ ) {
  154. self.isobj(arguments[ i ], true) && self.copyMembers(arguments[ i ], target);
  155. }
  156. return target;
  157. };
  158.  
  159. self.fire = function( elem, event, args ) {
  160. if ( self.isstr(event) ) {
  161. args = self.ifndef(args, { 'bubbles':true, 'cancelable':true });
  162. event = new Event( event, args );
  163. }
  164. return elem.dispatchEvent(event);
  165. };
  166.  
  167. self.isobj = function( expr, type ) {
  168. if ( 'object' !== typeof expr ) {
  169. return false;
  170. } else if ( true === type ) {
  171. return ( null !== expr );
  172. } else if ( self.isfn(type) ) {
  173. return ( type === expr.constructor );
  174. } else if ( self.isstr(type) ) {
  175. return ( !! expr.constructor && type === expr.constructor.name );
  176. }
  177. return true;
  178. }
  179.  
  180. self.keysAndValues = function( key, value, action ) {
  181. if ( self.ndef(action) && self.isfn(value) ) {
  182. action = value;
  183. value = undefined;
  184. }
  185.  
  186. // Case 1: key is an object (and there is no value)
  187. if ( self.isobj(key) && ! value ) {
  188. return Object.keys(key)
  189. .map( k => action(k, key[ k ]) );
  190. // Case 2: key is an array
  191. } else if ( self.isarr(key) ) {
  192. // Case 1.a: value is an array of the same length
  193. if ( self.isarr(value) && key.length === value.length ) {
  194. return key.map( ( k,i ) => action(k, value[ i ]) );
  195. // Case 1.b: value is considered a simple, plain value
  196. } else {
  197. return key.map( k => action(k, value) );
  198. }
  199. // Default Case: key and value considered as simple, plain values
  200. } else {
  201. return action(key, value);
  202. }
  203. };
  204.  
  205. self.localJson = function( key, value ) {
  206. if ( !! key && self.isstr(key) ) {
  207. try {
  208. if ( self.ndef(value) ) {
  209. return JSON.parse(localStorage.getItem(key));
  210. } else if ( null === value ) {
  211. return localStorage.removeItem(key);
  212. } else {
  213. return localStorage.setItem(key, JSON.stringify(value));
  214. }
  215. } catch ( error ) {
  216. self.warn('* localJson() error:', error, '\n\tfor:', key, value);
  217. }
  218. }
  219. return null;
  220. };
  221.  
  222. self.off = function( element, event, callback ) {
  223. if ( self.ndef(callback) && self.isobj(event) ) {
  224. return self.keysAndValues(event, ( k,v ) => self.off(element, k, v) );
  225. } else if ( self.isarr(element) ) {
  226. return element.map( elem => self.off(elem, event, callback) );
  227. }
  228. return element.removeEventListener(event, callback);
  229. };
  230.  
  231. self.on = function( element, event, callback ) {
  232. if ( self.ndef(callback) && self.isobj(event) ) {
  233. return self.keysAndValues(event, ( k,v ) => self.on(element, k, v) );
  234. } else if ( self.isarr(element) ) {
  235. return element.map( elem => self.on(elem, event, callback) );
  236. }
  237. return element.addEventListener(event, callback);
  238. };
  239.  
  240. self.onmutate = function( element, callback, config ) {
  241. if ( !! element && self.isfn(callback) ) {
  242. config = config || { 'attributes':false, 'childList':true, 'subtree':false };
  243.  
  244. if ( self.isarr(element) ) {
  245. return element.map( elem => self.onmutate(elem, callback, config) );
  246. }
  247.  
  248. let observer = new MutationObserver( callback );
  249. observer.initialConfig = ( ) => config;
  250. observer.reconnect = function( newConfig ) {
  251. this.observe(element, newConfig || this.initialConfig());
  252. return this;
  253. };
  254. return observer.reconnect();
  255. }
  256. return null;
  257. };
  258.  
  259. self.pojo2query = function( pojo ) {
  260. if ( self.isobj(pojo) && !! pojo ) {
  261. let query = Object.keys(pojo)
  262. .map( key => escape(key) +'='+ escape(pojo[ key ]) )
  263. .join('&');
  264. return '?'+ query;
  265. }
  266. return null;
  267. };
  268.  
  269. self.prependTo = function( element, parent, reference ) {
  270. if ( ! reference && !! parent ) {
  271. reference = parent.childNodes[ 0 ];
  272. }
  273.  
  274. if ( !! reference ) {
  275. reference.parentNode.insertBefore(element, reference);
  276. } else if ( !! parent ) {
  277. parent.append(element);
  278. } else {
  279. self.warn('*** prependTo() could not add element: No parent or reference element provided');
  280. }
  281.  
  282. return element;
  283. };
  284.  
  285. self.query2pojo = function( query ) {
  286. query = (self.ifndef(query, location.search) +'')
  287. .replace(/^[?&]+|$&+/g, '');
  288. if ( !! query ) {
  289. let segs, key, val, pojo = { };
  290. query.split('&')
  291. .forEach( item => {
  292. [ key, val ] =
  293. segs = item.split('=');
  294. val = ( self.ndef(val) ? null : segs.slice(1).join('=') );
  295. pojo[ unescape(key) ] = val;
  296. } );
  297. return pojo;
  298. }
  299. return null;
  300. };
  301.  
  302. self.request = function( url, verb, data, callback ) {
  303. self.log('* request of:', verb, url, data, callback);
  304.  
  305. // "Validate" HTTP Verb, to an extent
  306. verb = (verb || 'GET').toUpperCase();
  307. switch ( verb ) {
  308. case 'P': verb = 'POST'; break;
  309. case 'G': verb = 'GET'; break;
  310. case 'H': verb = 'HEAD'; break;
  311. }
  312.  
  313. // Switch callback and data when ther is no data
  314. if ( self.ndef(callback) && self.isfn(data) ) {
  315. callback = data;
  316. data = null;
  317. }
  318.  
  319. // Set the data to a string or null
  320. data = self.ifndef(data, null);
  321. data = ( !! data && self.isobj(data) ? self.pojo2query(data).replace('?', '') : data.toString() );
  322. self.log('- request data:', data);
  323.  
  324. // Add data to the URL for GET requests
  325. if ( 'GET' === verb && !! data ) {
  326. url += ( url.includes('?') ? '&' : '?' ) + data;
  327. data = null;
  328. }
  329.  
  330. // Create & open XHR object...
  331. let xhr = self.createXHR();
  332. self.log('-> opening request:', verb, url);
  333. xhr.open(verb, url);
  334. xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
  335.  
  336. // Set the internal event handler, which removes itself on execution
  337. xhr.onabort =
  338. xhr.onerror =
  339. xhr.onload = callback;
  340.  
  341. // Send the actual request
  342. self.log('-> sending request:', data, xhr.readyState, xhr);
  343. return xhr.send(data);
  344. };
  345.  
  346. self.table2json = function( table, headers, filter ) {
  347. if ( !! table && !! table.rows ) {
  348. let obj = { head:[ ], data:[ ] };
  349.  
  350. obj.head = ( self.isfn(headers) ? headers(table) : table.rows[ 0 ] );
  351. if ( self.isobj(obj.head) && !! obj.head.cells ) {
  352. obj.head = Array.map(obj.head.cells, th => th.innerText.trim() );
  353. }
  354.  
  355. if ( obj.head.length ) {
  356. filter = filter || (( row,i ) => ( i && 'TBODY' === row.parentNode.nodeName ));
  357.  
  358. for ( let r = 0, nr = table.rows.length; r < nr; r ++ ) {
  359. let row = table.rows[ r ];
  360.  
  361. if ( filter(row, r) ) {
  362. let item = { };
  363. obj.head.forEach( ( col,i ) => {
  364. col[ 0 ] && (item[ col ] = row.cells[ i ].innerText.trim());
  365. } );
  366. obj.data.push(item);
  367. }
  368. }
  369. }
  370. return obj.data;
  371. }
  372. return null;
  373. };
  374.  
  375. self.toArray = function( expr ) {
  376. if ( self.hasval(expr) && ! self.isarr(expr) ) {
  377. return ( self.ndef(expr.length) ? [ expr ] : Array.slice(expr) );
  378. }
  379. return expr || [ ];
  380. };
  381.  
  382. self.toDec2 = function( amount ) {
  383. amount = self.toDec(amount);
  384. if ( isNaN(amount) ) {
  385. return null;
  386. }
  387. let segs = (amount +'').split('.');
  388. return segs[ 0 ] +'.'+ ((segs[ 1 ] || 0) +'0').slice(0, 2);
  389. };
  390.  
  391. self.toMoney = function( amount ) {
  392. let dec2 = self.toDec2(amount);
  393. return ( isNaN(dec2) ? null : dec2 < 0 ? '-$ '+ (-dec2) : '$ '+ dec2 );
  394. };
  395.  
  396. self.traverse = function( elem, up, sideways, elementsOnly, lastIfNull ) {
  397. let last = elem;
  398. while ( !! elem && up -- > 0 ) elem = (last = elem, elem.parentNode);
  399.  
  400. let prop = ( elementsOnly ? 'Element' : '' ) +'Sibling';
  401. if ( sideways < 0 ) {
  402. while ( !! elem && sideways ++ < 0 ) elem = (last = elem, elem[ 'previous'+ prop ]);
  403. } else if ( sideways > 0 ) {
  404. while ( !! elem && sideways -- > 0 ) elem = (last = elem, elem[ 'next'+ prop ]);
  405. }
  406.  
  407. return ( ! lastIfNull ? elem : elem || last );
  408. };
  409.  
  410. // ----------------------------------------------------
  411. // Intended for Internal Use
  412.  
  413. self.copyMembers = function( source, target, members, preserve ) {
  414. //self.log('* Copying from', source, '\n\tto', target, '\n\t'+ members, preserve);
  415. if ( ! self.isobj(source) || ! self.isobj(target) ) {
  416. self.warn('=> Cannot copy from/to non-objects');
  417. return false;
  418. }
  419.  
  420. let names = Object.keys(source);
  421. preserve = ( self.isobj(preserve) ? preserve : false );
  422. //self.log('- Full list of members:', names, '\n\t', source);
  423.  
  424. if ( self.isstr(members) ) {
  425. members = members.split(',').map( nm => nm.trim() );
  426. }
  427. if ( self.isarr(members) ) {
  428. //self.log('* Member filter:', members);
  429. names = names.filter( nm => members.includes(nm) );
  430. } else if ( self.isfn(members) ) {
  431. names = names.filter(members);
  432. }
  433. //self.log('- Filtered list of members:', names);
  434.  
  435. names.forEach( nm => {
  436. if ( !! target[ nm ] && !! preserve ) {
  437. preserve[ nm ] = target[ nm ];
  438. }
  439. target[ nm ] = source[ nm ];
  440. //self.log('- Target members', nm, target[ nm ]);
  441. } );
  442. //self.log('=>', target);
  443. return (preserve || target);
  444. };
  445.  
  446. self.export = function( scope, members, overwriten ) {
  447. if ( ! scope ) {
  448. return false;
  449. }
  450. if ( '*' === (members +'').trim() ) {
  451. members = null;
  452. }
  453. return self.copyMembers(self, scope, members, overwriten);
  454. };
  455.  
  456. // Avoid needing a 'new' operator; this is just a wrapper
  457. return self;
  458. }

QingJ © 2025

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