JQuery DOM

Optimize JQuery experience of insert DOM.

As of 2024-01-22. See the latest version.

This script should not be not be installed directly. It is a library for other scripts to include with the meta directive // @require https://update.greatest.deepsurf.us/scripts/422934/1315443/JQuery%20DOM.js

  1. // ==UserScript==
  2. // @name JQuery DOM
  3. // @namespace https://greatest.deepsurf.us/
  4. // @version 1.1.10
  5. // @description Optimize JQuery experience of insert DOM.
  6. // @author JMRY
  7. // @include *://*
  8. // @grant none
  9. // ==/UserScript==
  10. if(typeof jQuery===`function`){
  11. jQuery.getDOMString=function(dom_tag,dom_attr,dom_html){
  12. /*
  13. dom_tag:string
  14. HTML tags, like div, input, p, button, and so on.
  15. dom_attr:object
  16. HTML attributes, struct:
  17. {
  18. id:`id`,
  19. class:`class1 class2` OR [`class1`,`class2`],
  20. style:`border:none;` OR {border:`none`},
  21. Extend attributes:
  22. bind:{
  23. click:function,
  24. },
  25. }
  26. dom_attr:string
  27. HTML inner text
  28. dom_html:string
  29. HTML inner text
  30. */
  31. //属性黑名单指的是在遍历属性时直接忽略的key。
  32. //如果需要处理这些key但不要插入html中,则应使用allow_insert_attr,将它置为false即可。
  33. let attr_blacklist=[
  34. `bind`,`children`,
  35. ]
  36. if(dom_tag==undefined){ //html标记为空时,直接返回空值
  37. return ``;
  38. }else if(dom_tag!=undefined && dom_attr==undefined && dom_html==undefined){ //html标记不为空、属性和内容为空时,直接返回字符串
  39. return dom_tag;
  40. }else if(dom_tag!=undefined && dom_attr!=undefined && dom_html==undefined){
  41. dom_html=``;
  42. }
  43. let dom_attr_string=[];
  44. //dom_attr is string, it will be the inner html, without attributes.
  45. if(typeof dom_attr==`string`){
  46. dom_html=dom_attr;
  47. }else if(typeof dom_attr==`object`){
  48. let allow_insert_attr;
  49. for(let key in dom_attr){
  50. allow_insert_attr=true;
  51. let cur_dom_attr=dom_attr[key];
  52. // if(key!=`bind`){
  53. // if(jQuery.inArray(key,attr_blacklist)<0){
  54. if(!attr_blacklist.includes(key)){
  55. //HTML属性的特殊处理
  56. switch(key){
  57. //Class数组化处理
  58. case `class`:
  59. if(typeof cur_dom_attr==`object` && cur_dom_attr.length){
  60. cur_dom_attr=cur_dom_attr.join(` `).trim();
  61. }else if(typeof cur_dom_attr==`object` && cur_dom_attr.length==undefined){
  62. let classList=[];
  63. for(let key in cur_dom_attr){
  64. if(cur_dom_attr[key]==true){
  65. classList.push(key);
  66. }
  67. }
  68. cur_dom_attr=classList.join(` `).trim();
  69. }
  70. break;
  71. //Style对象化处理(交给getDOMObject,因此将allow_insert_attr置为false,以跳过插入属性)
  72. case `style`:
  73. if(typeof cur_dom_attr==`object`){
  74. allow_insert_attr=false;
  75. }
  76. break;
  77. //Html属性转为text。此属性会覆盖dom_html参数,因此不可混用
  78. case `html`:
  79. dom_html=cur_dom_attr;
  80. allow_insert_attr=false;
  81. break;
  82. //tbody属性处理
  83. case `tbody`: case `tr`: case `td`:
  84. allow_insert_attr=false;
  85. break;
  86. }
  87. //cur_dom_attr为undefined、null时,不插入此属性
  88. if(cur_dom_attr!=undefined && cur_dom_attr!=null && allow_insert_attr){
  89. dom_attr_string.push(`${key.replace(/([A-Z])/g,"-$1").toLowerCase()}="${cur_dom_attr}"`);
  90. }
  91. }
  92. }
  93. }
  94. if(dom_tag==`html`){
  95. return `${dom_html}`;
  96. }
  97. return `<${dom_tag} ${dom_attr_string.join(` `)}>${dom_html}</${dom_tag}>`;
  98. }
  99.  
  100. jQuery.getDOMObject=function(dom_tag,dom_attr,dom_html, attach_type){
  101. //dom_tag为对象时,和普通情况一样
  102. if(typeof dom_tag==`object` && dom_tag.length==undefined){
  103. let dom_attr_fix_blacklist=[
  104. `tag`,`attachType`,
  105. ]
  106. let dom_attr_fix_replace={
  107. tagName:`tag`, attrName:`attr`,tag_name:`tagName`,attr_name:`attrName`,
  108. }
  109. let dom_attr_fix={};
  110. if(dom_tag.attr==undefined){
  111. for(let key in dom_tag){
  112. if(!dom_attr_fix_blacklist.includes(key)){
  113. let key_fix=key;
  114. for(let origin in dom_attr_fix_replace){
  115. key_fix=key_fix.replace(origin,dom_attr_fix_replace[origin]);
  116. }
  117. dom_attr_fix[key_fix]=dom_tag[key];
  118. }
  119. }
  120. }
  121. dom_attr=dom_tag.attr || dom_attr_fix;
  122. dom_html=dom_tag.html;
  123. attach_type=dom_tag.attachType || attach_type;
  124. dom_tag=dom_tag.tag;
  125. }
  126.  
  127. try{
  128. let domObject=jQuery(jQuery.getDOMString(dom_tag, dom_attr, dom_html));
  129. if(typeof dom_attr==`object`){
  130. //DOM样式
  131. try{
  132. /*
  133. CSS Struct:
  134. style:{
  135. width:`255px`,
  136. height:`255px`,
  137. }
  138. */
  139. if(typeof dom_attr.style==`object`){
  140. domObject.css(dom_attr.style);
  141. }
  142. }catch(e){
  143. console.error(e);
  144. }
  145.  
  146. //DOM事件绑定
  147. try{
  148. /*
  149. Bind Struct:
  150. bind:{
  151. click:function,
  152. }
  153. Another Struct:
  154. bind:{
  155. click:{
  156. data:{},
  157. function:function,
  158. }
  159. }
  160. */
  161. if(typeof dom_attr.bind==`object`){
  162. for(let key in dom_attr.bind){
  163. let curBind=dom_attr.bind[key];
  164. domObject.unbind(key);
  165. if(typeof curBind==`function`){
  166. domObject.bind(key, curBind);
  167. }else if(typeof curBind==`object`){
  168. curBind={
  169. ...{
  170. data:{},
  171. function(){},
  172. },
  173. ...curBind,
  174. }
  175. domObject.bind(key, curBind.data, curBind.function);
  176. }
  177. }
  178. }
  179. }catch(e){
  180. console.error(e);
  181. }
  182.  
  183. //DOM子项
  184. try{
  185. if(typeof dom_attr.children==`object`){
  186. let default_children={
  187. tag:undefined,attr:undefined,html:undefined,attachType:`append`
  188. };
  189.  
  190. if(dom_attr.children.length==undefined){
  191. /*仅一个子项时,可以直接使用Object
  192. {
  193. tag:`html`,attr:{id:`id`},html:`Test`,attachType:`append`
  194. }
  195. */
  196. let children={
  197. // ...default_children,
  198. ...JSON.parse(JSON.stringify(default_children)),
  199. ...dom_attr.children,
  200. }
  201. // domObject.attachDOM(children.tag,children.attr,children.html,children.attachType);
  202. domObject.append(jQuery.getDOMObject(children));
  203. }else{
  204. /*多个子项时,采用数组形式
  205. [
  206. {
  207. tag:`html`,attr:{id:`id1`},html:`Test1`,attachType:`append`
  208. },
  209. {
  210. tag:`html`,attr:{id:`id2`},html:`Test2`,attachType:`append`
  211. },
  212. ]
  213. */
  214. for(let i=0; i<dom_attr.children.length; i++){
  215. let children={
  216. // ...default_children,
  217. ...JSON.parse(JSON.stringify(default_children)),
  218. ...dom_attr.children[i],
  219. }
  220. // domObject.attachDOM(children.tag,children.attr,children.html,children.attachType);
  221. domObject.append(jQuery.getDOMObject(children));
  222. }
  223. }
  224. }
  225. }catch(e){
  226. console.error(e);
  227. }
  228.  
  229. //TBODY表格
  230. try{
  231. if(typeof dom_attr.tbody==`object` || typeof dom_attr.tr==`object`){
  232. let default_tr={
  233. tag:`tr`,attr:undefined,html:undefined,children:[],attachType:`append`
  234. };
  235. let default_td={
  236. tag:`td`,attr:undefined,html:undefined,children:[],attachType:`append`
  237. }
  238. let trDomObject;
  239. let trList=dom_attr.tbody || dom_attr.tr;
  240. for(let i=0; i<trList.length; i++){
  241. let curTr=trList[i];
  242. let tr={
  243. ...JSON.parse(JSON.stringify(default_tr)),
  244. ...curTr
  245. }
  246. // let trDomObject=domObject.attachDOM(tr.tag,tr.attr,tr.html,tr.attachType);
  247. trDomObject=jQuery.getDOMObject(tr);
  248. for(let j=0; j<curTr.td.length; j++){
  249. let curTd=curTr.td[j];
  250. if(typeof curTd==`string`){
  251. curTd={html:curTd};
  252. }
  253. let td={
  254. ...JSON.parse(JSON.stringify(default_td)),
  255. ...curTd,
  256. }
  257. // trDomObject.attachDOM(td.tag,td.attr,td.html,td.attachType);
  258. trDomObject.append(jQuery.getDOMObject(td));
  259. }
  260. domObject.append(trDomObject);
  261. }
  262. }
  263. }catch(e){
  264. console.error(e);
  265. }
  266. }
  267. return domObject;
  268. }catch(e){
  269. //对不规范写法的容错,如:只传dom_tag的情况下,直接返回字符串,而不是JQuery对象。
  270. return jQuery.getDOMString(dom_tag, dom_attr, dom_html);
  271. }
  272. }
  273.  
  274. jQuery.fn.attachDOM=function(dom_tag, dom_attr, dom_html, attach_type){
  275. //dom_tag为数组时,批量为母元素添加元素
  276. if(typeof dom_tag==`object` && dom_tag.length!=undefined){
  277. let default_children={
  278. tag:undefined,attr:undefined,html:undefined,attachType:`append`
  279. };
  280. for(let cur of dom_tag){
  281. cur={
  282. ...JSON.parse(JSON.stringify(default_children)),
  283. ...cur,
  284. }
  285. this.attachDOM(cur,undefined,undefined,attach_type);
  286. }
  287. return;
  288. }
  289.  
  290. let domObject=jQuery.getDOMObject(dom_tag, dom_attr, dom_html);
  291.  
  292. switch(attach_type){
  293. case `append`:
  294. this.append(domObject);
  295. break;
  296. case `prepend`:
  297. this.prepend(domObject);
  298. break;
  299. case `after`:
  300. this.after(domObject);
  301. break;
  302. case `before`:
  303. this.before(domObject);
  304. break;
  305. case `html`:
  306. this.html(domObject);
  307. break;
  308. }
  309. return domObject;
  310. }
  311.  
  312. jQuery.fn.appendDOM=function(dom_tag,dom_attr,dom_html){
  313. return this.attachDOM(dom_tag,dom_attr,dom_html,`append`);
  314. }
  315. jQuery.fn.prependDOM=function(dom_tag,dom_attr,dom_html){
  316. return this.attachDOM(dom_tag,dom_attr,dom_html,`prepend`);
  317. }
  318. jQuery.fn.afterDOM=function(dom_tag,dom_attr,dom_html){
  319. return this.attachDOM(dom_tag,dom_attr,dom_html,`after`);
  320. }
  321. jQuery.fn.beforeDOM=function(dom_tag,dom_attr,dom_html){
  322. return this.attachDOM(dom_tag,dom_attr,dom_html,`before`);
  323. }
  324. jQuery.fn.htmlDOM=function(dom_tag,dom_attr,dom_html){
  325. return this.attachDOM(dom_tag,dom_attr,dom_html,`html`);
  326. }
  327. jQuery.fn.getHtml=function(dom_tag,dom_attr,dom_html){
  328. return this.attachDOM(dom_tag,dom_attr,dom_html,`html`)[0].outerHTML;
  329. }
  330. jQuery.getDOMHtml=function(dom_tag,dom_attr,dom_html){
  331. return jQuery.fn.getHtml(dom_tag,dom_attr,dom_html);
  332. }
  333. }