baseLib

LEORChn JavaScript Base Lib

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

  1. var htmlhead=document.head,
  2. htmlbody=document.body;
  3. (function(){
  4. // IE Method Compat pak 1
  5. var string_includes = function(s){ return this.indexOf(s)>-1; };
  6. _proto(String, 'contains', string_includes);
  7. _proto(String, 'includes', string_includes);
  8. /* 这个IF里面判断的东西可以在不需要兼容IE9时删除。。 */
  9. if(window['ActiveXObject']){
  10. var varprop = function(name, type, func){
  11. if(!('__var_pool' in this)) this['__var_pool'] = {};
  12. if(!(name in this.__var_pool)){
  13. Object.defineProperty(this, name,
  14. this.__var_pool[name] = {
  15. get: function(){},
  16. set: function(){}
  17. }
  18. );
  19. }
  20. this.__var_pool[name][type] = func;
  21. };
  22. Object.prototype['__defineGetter__'] = function(name, func){
  23. varprop(name, 'get', func);
  24. };
  25. Object.prototype['__defineSetter__'] = function(name, func){
  26. varprop(name, 'set', func);
  27. }
  28. // window.File 最低支持:IE10
  29. if(!('File' in window))
  30. window.File = function(){};
  31. // window.HTMLInputElement 继承到 Object 的最低支持:IE9
  32. _proto(HTMLInputElement, '__defineGetter__', function(){});
  33. _proto(HTMLInputElement, '__defineSetter__', function(){}); // TODO:其实是无效的
  34. // window.HTMLElement 最低支持:IE9
  35. if(!('HTMLElement' in window))
  36. window.HTMLElement = function(){};
  37. // document.getElementsByClassName 最低支持:IE9
  38. if(!('getElementsByClassName' in document))
  39. document.getElementsByClassName = function(n){
  40. var res = [];
  41. for(var i=0, a=document.all; i<a.length; i++)
  42. if((' '+a[i].className+' ').includes(' '+n+' '))
  43. res.push(a[i]);
  44. return res;
  45. };
  46. }
  47. /* 上面这个IF里面判断的东西可以在不需要兼容IE9时删除。。 */
  48. // Generic Method Compat
  49. var imed=false;
  50. HTMLInputElement.prototype.__defineGetter__('imeDisabled',function(){ return imed? true: false; });
  51. HTMLInputElement.prototype.__defineSetter__('imeDisabled',function(s){
  52. imed = s? true: false;
  53. this.onkeyup = imed? function(){
  54. var sel = this.selectionStart,
  55. sav = this.value,
  56. right = sav.substr(sel),
  57. lef = sav.substr(0, sel),
  58. aft = lef.replace(/'/g, ''),
  59. wipecount = lef.length - aft.length;
  60. if(sel != this.selectionEnd) return;
  61. this.blur();
  62. this.focus();
  63. this.value = aft + right;
  64. this.selectionStart = this.selectionEnd = sel - wipecount;
  65. }: undefined;
  66. });
  67. // Firefox Method Compat
  68. if(!('innerText' in document.body)){
  69. HTMLElement.prototype.__defineGetter__("innerText", function(){ return this.textContent; });
  70. HTMLElement.prototype.__defineSetter__("innerText", function(s){ return this.textContent=s; });
  71. }
  72. // Constom Method Modify
  73. _proto(Array, 'foreach', function(func){ for(var i=0; i<this.length; i++) try{ if(func(this[i], i, this)) return true; }catch(e){ pl(e); } }, true);
  74. var norepeat = function(){
  75. return (_this = this).filter(function(e, i){
  76. return _this.indexOf(e) == i;
  77. });
  78. };
  79. _proto(Array, 'filterRepeat', norepeat);
  80. _proto(Array, 'removeRepeat', norepeat);
  81. _proto(HTMLElement, 'appendChildren', function(){ var t = this; arr(arguments).foreach(function(e){ t.appendChild(e); }); });
  82. _proto(HTMLElement, 'prependChild', function(e){
  83. var f=this.firstElementChild;
  84. if(f) this.insertBefore(e,f); else this.appendChild(e);
  85. });
  86. _proto(HTMLElement, 'insertAfter', function(e,f){
  87. f=f.nextElementSibling;
  88. if(f) this.insertBefore(e,f); else this.appendChild(e);
  89. });
  90. _proto(Event, 'block', function(){ this.preventDefault(); this.stopPropagation(); });
  91. _proto(File, 'readAsText', function(f){ // 最低支持:IE10
  92. switch(true){
  93. case f.constructor.name=='Function':
  94. var r=f;
  95. f=new FileReader();
  96. f.onload=function(p){
  97. r(p.target.result, p);
  98. };
  99. case f instanceof FileReader:
  100. f.readAsText(this);
  101. return f; // FileReader
  102. }
  103. });
  104. _proto(String, 'format', function(){
  105. _this = this;
  106. var args = arr(arguments);
  107. if(args[0].constructor === Array) args = args[0];
  108. args.foreach(function(e, i){
  109. _this = _this.replace(new RegExp("\\{" + i + "\\}", "gm"), e);
  110. });
  111. // 检查有没有没替换的可能
  112. var res = /\{(\d+)\}/gm.exec(_this);
  113. if(res) console.warn('文本:'+this.left(10)+'... 格式化时可能出现问题,未包含第'+res[1]+'号参数。');
  114. return _this;
  115. });
  116. // Visual Basic
  117. _proto(String, 'left', function(n){ return this.substr(0, Math.abs(n)); });
  118. _proto(String, 'right', function(n){ n=Math.abs(n); return this.substr(-n, n); });
  119. // IE Method Compat pak 2
  120. _proto(HTMLElement, 'remove', function(){ try{this.parentElement.removeChild(this);}catch(e){} });
  121. if('EventTarget' in window)
  122. _proto(EventTarget, 'addEventListener', function(n,f){ this.attachEvent('on'+n, f); });
  123. if(!('startsWith' in String)){
  124. _proto(String, 'startsWith', function(s){ return this.left(s.length) == s; });
  125. _proto(String, 'endsWith', function(s){ return this.right(s.length) == s; });
  126. }
  127. })();
  128. function _proto(obj, name, fun, force){
  129. if(obj instanceof Function && obj.name == 'Object'){
  130. pl('不能修改 Object 基类,因为这会导致 jQuery 异常。');
  131. return;
  132. }
  133. if(!(name in obj.prototype) || force){
  134. obj.prototype[name] = fun;
  135. console.debug('baseLib - 已修改方法:' + obj.name + '.' + name);
  136. }else{
  137. console.info('baseLib - 未修改方法:' + obj.name + '.' + name);
  138. }
  139. }
  140. function isReady(){return document.readyState.toLowerCase()=='complete'}
  141. function $(e){return document.querySelector(e);}
  142. function $$(e){return document.querySelectorAll(e);}
  143. function arr(o){return Array.prototype.slice.call(o);}
  144. function fv(id){return document.getElementById(id);}
  145. function ft(tag){return document.getElementsByTagName(tag);}
  146. function fc(cname){return document.getElementsByClassName(cname);}
  147. function ct(tag, t){
  148. if(arguments.length > 2) pl(new Error('Somewhere might using old version to create Elements. PLEASE UPDATE YOUR CODE.'));
  149. tag = {
  150. entity: null,
  151. raw: tag,
  152. data: tag.split(/[#\.\s]/g)
  153. };
  154. var nextStart = 0;
  155. tag.data.foreach(function(e){
  156. nextStart ++;
  157. if(e.length == 0) return; // continue
  158. nextStart --;
  159. switch(tag.raw.charAt(nextStart)){
  160. case ' ': case '.':
  161. addClass(tag.entity, e); break;
  162. case '#':
  163. tag.entity.id = e; break;
  164. default:
  165. tag.entity = document.createElement(e);
  166. nextStart --;
  167. }
  168. nextStart += e.length + 1;
  169. });
  170. if(t) tag.entity.innerText = t;
  171. return tag.entity;
  172. }
  173. function msgbox(msg){alert(msg);}
  174. function inputbox(title,defalt){return prompt(title,defalt);}
  175. function pl(s){console.log(s);}
  176. function vaild(o){return!(o==undefined||o==null||isNaN(o));}
  177. function gquery(n){ return _GET(n); } // get Query
  178. function _GET(n){
  179. var r=location.search.match(new RegExp("[\?\&]"+n+"=([^\&]+)","i"));
  180. return r==null||r.length<1?'':r[1];
  181. }
  182. function type(e){
  183. var t = typeof(e);
  184. return t == 'object'? e == null? 'Null': e.constructor.name: t.replace(t[0], t[0].toUpperCase());
  185. }
  186. /* patch() 参数情况:
  187. 单个EventTarget:直接返回本体
  188. 单个EventTarget但是用数组封装:返回该数组
  189. 多个EventTarget:返回封装数组
  190. 其他情况比如数组和EventTarget混用等:不管他
  191. */
  192. function patch(){
  193. var args = arguments,
  194. insideSelf = args.length==1 && args[0] instanceof EventTarget;
  195. if(args.length==1 && args[0] instanceof Array) args = args[0]; // 如果参数只是一个数组而且没有别的东西,就分离解析
  196. for(var i=0; i<args.length; i++){
  197. args[i].on = function(){
  198. var prog = 0;
  199. do{
  200. var arglen = arguments.length;
  201. switch(arglen){
  202. case undefined:
  203. case 0: return;
  204. case 1:
  205. arguments = arguments[0];
  206. break;
  207. default:
  208. if(arguments[arglen-1] instanceof Function); else return; // 最后一个必须是 function
  209. var event_name = arguments[prog],
  210. befor_func = this['on'+event_name], // replaceable static function
  211. after_func = arguments[arglen-1];
  212. this['on'+event_name] = after_func;
  213. if(this instanceof EventTarget); else return;
  214. this['on'+event_name] = befor_func;
  215. this.addEventListener(event_name, after_func);
  216. if( ++prog == arglen ) return;
  217. }
  218. }while(true);
  219. }
  220. }
  221. if(insideSelf){
  222. args.on = function(){
  223. for(var i=0; i<this.length; i++) if(this[i].on) this[i].on(arguments);
  224. }
  225. }
  226. return insideSelf? args[0]: args;
  227. }
  228. function base64(e, f){
  229. if(!(f instanceof Function)){
  230. console.error('base64: You must set a handler for it, because base64() is using FileReader API.\n\nSee usage by invoke this function without any argument.');
  231. return;
  232. }
  233. switch(true){
  234. case e instanceof Array:
  235. e = new Uint8Array(e);
  236. case e instanceof Uint8Array:
  237. e = new Blob([e]);
  238. case e instanceof Blob:
  239. break;
  240. default:
  241. if(arguments.length == 0){
  242. console.warn('Usage: base64(data, handler)\n\ndata: Array, Uint8Array or Blob.\nhandler: function(data_of_base64){\n\t// process your data here\n}');
  243. return;
  244. }
  245. console.error('base64()\'s first argument only accept: Array/Uint8Array/Blob but found: ' + e);
  246. return;
  247. }
  248. var fr = new FileReader();
  249. fr.onload = function(e){
  250. f(e.target.result.split(',')[1]);
  251. };
  252. fr.readAsDataURL(e);
  253. }
  254. function sortByWin7FileName(fl){
  255. function usage(){
  256. console.warn('Usage: sortByWin7FileName(files)\n\nfiles: FileList or Array, that the children must be File or String.');
  257. }
  258. var isStringType = false;
  259. switch(type(fl)){
  260. case 'FileList':
  261. fl = arr(fl);
  262. case 'Array':
  263. switch(type(fl[0])){
  264. case 'String':
  265. isStringType = true;
  266. case 'File':
  267. break;
  268. default:
  269. usage();
  270. return;
  271. }
  272. break;
  273. default:
  274. usage();
  275. return;
  276. }
  277. return fl.sort(function(a, b){ // 先排序文件名。比如 5-2020-... 应该排在 21-2020-... 的前面。
  278. var x = /(.*?)(\d+)/g, // 划分区块,尝试匹配数字以及其之前的废料文本
  279. y = /(.*?)(\d+)/g, // 复制一个 RegExp 对象声明。不能使用 x = y = 值,因为是对象类型,会导致共享内存地址
  280. classic = function(a,b){ // 典型对比:由系统确定顺序
  281. return a==b? 0: [a,b].sort()[0] == a? -1: 1;
  282. };
  283. if(!isStringType){
  284. a = a.name;
  285. b = b.name;
  286. }
  287. while(true){ // 返回:大于 0 的,A会排在后;小于 0 的,B会排在后
  288. var xs = x.exec(a), // 分区块查找,分别对每个RegExp对象调用exec,参数与上次调用时一致,即查找下一个区块
  289. ys = y.exec(b);
  290. if(xs != null && ys != null){ // 全不为 null 时判断内容
  291. var c = classic(xs[1], ys[1]);
  292. if(c) return c; // 在该数字之前的文本内容有不同,使用典型对比结果
  293. if(parseInt(xs[2]) == parseInt(ys[2])){
  294. if(xs[2] == ys[2]) continue; // 因为两个数字相同而无法判断
  295. else return xs[2].length - ys[2].length; // 两个数字表达值相同,但是长度不同,短的在前
  296. }
  297. return xs[2] - ys[2]; // 常规的 a - b,小数在前
  298. }
  299. // 运行到此处时,表示其中一个已匹配完(正则得到 null,无法匹配区块),表示该文件名更短。需要将短文件名排在前面
  300. return xs == ys?
  301. classic(a, b): // 全 null,启用典型对比
  302. xs == null?
  303. -1: // 仅 y = null
  304. 1; // 仅 x = null
  305. }
  306. });
  307. }
  308.  
  309. (function(){for(var i=0,a=fc('webp');i<a.length;i++) webpReplace(a[i]);})();
  310. function webpReplace(e,u){
  311. var a=new Image();
  312. a.src=/url\(\"?([^\"]*)\"?\)/.exec(e.style.backgroundImage)[1];
  313. a.onerror=function(){
  314. e.style.backgroundImage=u? u: 'url('+this.src.replace(/\.webp$/,'.png')+')';
  315. if(fv('webp-notice')) return;
  316. var root = ct('div'),
  317. style = ct('style', '#webp-notice{display:none} #webp-notice:checked+div{transform:translateY(-100%); transition:2s}'),
  318. inp = ct('input#webp-notice'),
  319. hint = ct('span', '您的浏览器不支持 WebP。'),
  320. wiki = ct('a','维基百科'),
  321. btn = ct('label', '关闭提示');
  322. root.style.cssText = 'position:fixed; right:0; top:0; background-color:#fff; z-index:999';
  323. wiki.href = "https://en.wikipedia.org/wiki/WebP";
  324. wiki.target = '_blank';
  325. inp.type = 'checkbox';
  326. btn.setAttribute('for', 'webp-notice');
  327. root.appendChildren(style, hint, wiki, btn);
  328. htmlbody.appendChildren(inp, root);
  329. }
  330. }
  331.  
  332. function getAbsMousePos(){ // 相对于页面获取的光标和触摸位置,适用于属性 position 的值是 absolute 的元素(相对于整个文档根部) // TODO: 总感觉这个有BUG没修
  333. var x,y,r=document.documentElement, e = window.event;
  334. if(e instanceof MouseEvent){
  335. x=e.clientX+htmlbody.scrollLeft+r.scrollLeft,
  336. y=e.clientY+htmlbody.scrollTop+r.scrollTop;
  337. }else if(e instanceof TouchEvent){
  338. e=e.touches[0];
  339. x=e.pageX;
  340. y=e.pageY;
  341. }
  342. return{ x:x, y:y };
  343. }
  344. function getFixMousePos(){ // 相对于屏幕获取的光标和触摸位置,适用于属性 position 的值是 fixed 的元素
  345. var x,y,r=document.documentElement, e = window.event;
  346. if(e instanceof MouseEvent){
  347. x=e.clientX,
  348. y=e.clientY;
  349. }else if(e instanceof TouchEvent){
  350. e=e.touches[0];
  351. x=e.clientX;
  352. y=e.clientY;
  353. }
  354. return{ x:x, y:y };
  355. }
  356.  
  357. function hasClass(e,n){ return new RegExp("(\\s|^)"+n+"(\\s|$)").test(e.className); }
  358. function addClass(e,n){ if(!hasClass(e,n)) e.className=(e.className+' '+n).trim(); }
  359. function removeClass(e,n){ removeClassName(e,n); }
  360. function removeClassName(e,n){ if(hasClass(e,n)) e.className=e.className.replace(new RegExp('(\\s|^)'+n+'(\\s|$)'), ''); }
  361.  
  362. function imports(){
  363. if(arguments.length == 1) arguments = arguments[0].split(',');
  364. if(arguments[0] instanceof Array) arguments = arguments[0];
  365. for(var i=0,a=arguments;i<a.length;i++) addJs(a[i]);
  366. }
  367. function addJs(url,async){
  368. var d=ct('script');
  369. if(async) d.async='async';
  370. d.type='application/javascript';
  371. d.src= /\$$/.test(url)?
  372. url.trim().replace(/\$$/,''):
  373. url.trim()+(/\.js$/i.test(url)?'':'.js');
  374. htmlbody.appendChild(d);
  375. }
  376. function addCss(url) {
  377. var link = ct('link');
  378. link.type='text/css';
  379. link.rel ='stylesheet';
  380. link.href= url;
  381. htmlhead.appendChild(link);
  382. }
  383.  
  384. function copy(text){
  385. var ta = document.createElement("textarea");
  386. ta.style.position = 'fixed';
  387. ta.style.top = ta.style.left = '100%';
  388. ta.value = text;
  389. document.body.appendChild(ta);
  390. ta.select();
  391. try{
  392. var successful = document.execCommand('copy');
  393. var msg = successful ? '成功复制到剪贴板' : '该浏览器不支持点击复制到剪贴板';
  394. pl(msg)
  395. }catch(e){
  396. alert('浏览器不支持点击复制到剪贴板');
  397. }
  398. document.body.removeChild(textArea);
  399. }
  400.  
  401. function cok_a(n,v,timeExpire,timeShift){
  402. if(timeExpire || timeShift){
  403. if(!(timeExpire instanceof Number || timeExpire instanceof Date)) timeExpire=new Date().getTime();
  404. if(!timeShift instanceof Number) timeShift=0;
  405. document.cookie=n+'='+escape(v)+';expires='+new Date(timeExpire+timeShift).toGMTString();
  406. }else
  407. document.cookie=n+'='+escape(v);
  408. return cok(n);
  409. }
  410. function cok(n){
  411. var k=document.cookie.match(new RegExp('(^| )'+n+'=([^;]*)(;|$)'));
  412. if(k)return unescape(k[2]);
  413. else return'';
  414. }
  415. function cok_d(n){
  416. var e=new Date();
  417. e.setTime(e.getTime()-1);
  418. document.cookie=n+'=0;expires='+e.toGMTString();
  419. }

QingJ © 2025

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