wsemi 1.9.4 → 1.9.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (490) hide show
  1. package/README.md +1 -1
  2. package/dist/wsemi.umd.js +2 -2
  3. package/dist/wsemi.umd.js.map +1 -1
  4. package/docs/-_class.mjs.html +1 -1
  5. package/docs/-_const.mjs.html +1 -1
  6. package/docs/ab2blob.mjs.html +1 -1
  7. package/docs/ab2u8arr.mjs.html +1 -1
  8. package/docs/addExcelWorksheetFromData.mjs.html +1 -1
  9. package/docs/addMonth.mjs.html +1 -1
  10. package/docs/aes2str.mjs.html +1 -1
  11. package/docs/alive.mjs.html +1 -1
  12. package/docs/arr2dt.mjs.html +1 -1
  13. package/docs/arrAccum.mjs.html +1 -1
  14. package/docs/arrAdd.mjs.html +1 -1
  15. package/docs/arrAt.mjs.html +1 -1
  16. package/docs/arrDiff.mjs.html +1 -1
  17. package/docs/arrFilterByKeywords.mjs.html +1 -1
  18. package/docs/arrFilterByNum.mjs.html +1 -1
  19. package/docs/arrFilterByPnum.mjs.html +1 -1
  20. package/docs/arrFilterByPnumAndToLog.mjs.html +1 -1
  21. package/docs/arrFind.mjs.html +1 -1
  22. package/docs/arrGroupByMaxmin.mjs.html +1 -1
  23. package/docs/arrHas.mjs.html +1 -1
  24. package/docs/arrInsert.mjs.html +1 -1
  25. package/docs/arrLookupByMaxmin.mjs.html +1 -1
  26. package/docs/arrMax.mjs.html +1 -1
  27. package/docs/arrMin.mjs.html +1 -1
  28. package/docs/arrMulti.mjs.html +1 -1
  29. package/docs/arrNorm.mjs.html +1 -1
  30. package/docs/arrProduct.mjs.html +1 -1
  31. package/docs/arrPull.mjs.html +1 -1
  32. package/docs/arrPullAt.mjs.html +1 -1
  33. package/docs/arrReduce.mjs.html +1 -1
  34. package/docs/arrReverse.mjs.html +1 -1
  35. package/docs/arrSep.mjs.html +1 -1
  36. package/docs/arrSort.mjs.html +1 -1
  37. package/docs/asind.mjs.html +1 -1
  38. package/docs/atan2d.mjs.html +1 -1
  39. package/docs/atand.mjs.html +1 -1
  40. package/docs/attstr.mjs.html +1 -1
  41. package/docs/b642obj.mjs.html +1 -1
  42. package/docs/b642str.mjs.html +1 -1
  43. package/docs/b642u16arr.mjs.html +1 -1
  44. package/docs/b642u8arr.mjs.html +1 -1
  45. package/docs/binstr.mjs.html +1 -1
  46. package/docs/blob2ab.mjs.html +1 -1
  47. package/docs/blob2b64.mjs.html +1 -1
  48. package/docs/blob2str.mjs.html +1 -1
  49. package/docs/blob2u8arr.mjs.html +1 -1
  50. package/docs/blobs2b64s.mjs.html +1 -1
  51. package/docs/blobs2u8arrs.mjs.html +1 -1
  52. package/docs/bodyLog.mjs.html +1 -1
  53. package/docs/browserView.mjs.html +1 -1
  54. package/docs/browserViewFromBlob.mjs.html +1 -1
  55. package/docs/browserViewFromText.mjs.html +1 -1
  56. package/docs/browserViewFromU8arr.mjs.html +1 -1
  57. package/docs/bs2u8arr.mjs.html +1 -1
  58. package/docs/bufRead.mjs.html +1 -1
  59. package/docs/bufReadDbl.mjs.html +1 -1
  60. package/docs/bufWrite.mjs.html +1 -1
  61. package/docs/bufWriteDbl.mjs.html +1 -1
  62. package/docs/cache.mjs.html +1 -1
  63. package/docs/cacheBd.mjs.html +1 -1
  64. package/docs/cacheSt.mjs.html +1 -1
  65. package/docs/cbol.mjs.html +1 -1
  66. package/docs/cdbl.mjs.html +1 -1
  67. package/docs/ceil.mjs.html +1 -1
  68. package/docs/cfilesize.mjs.html +1 -1
  69. package/docs/cfinancial.mjs.html +1 -1
  70. package/docs/cint.mjs.html +1 -1
  71. package/docs/clearXSS.mjs.html +1 -1
  72. package/docs/clearXSSDyn.mjs.html +1 -1
  73. package/docs/color.mjs.html +1 -1
  74. package/docs/composeToTree.mjs.html +1 -1
  75. package/docs/convertToTree.mjs.html +1 -1
  76. package/docs/copyStrToClipboard.mjs.html +1 -1
  77. package/docs/cosd.mjs.html +1 -1
  78. package/docs/cotd.mjs.html +1 -1
  79. package/docs/createExcelWorkbook.mjs.html +1 -1
  80. package/docs/cscd.mjs.html +1 -1
  81. package/docs/cstr.mjs.html +1 -1
  82. package/docs/day2cht.mjs.html +1 -1
  83. package/docs/debounce.mjs.html +1 -1
  84. package/docs/delay.mjs.html +1 -1
  85. package/docs/dig.mjs.html +1 -1
  86. package/docs/digExp.mjs.html +1 -1
  87. package/docs/domAlert.mjs.html +1 -1
  88. package/docs/domAppend.mjs.html +1 -1
  89. package/docs/domCancelEvent.mjs.html +1 -1
  90. package/docs/domCompareText.mjs.html +1 -1
  91. package/docs/domConvertToPic.mjs.html +1 -1
  92. package/docs/domConvertToPicDyn.mjs.html +1 -1
  93. package/docs/domDetect.mjs.html +462 -571
  94. package/docs/domDrag.mjs.html +1 -1
  95. package/docs/domDragBarAndScroll.mjs.html +1 -1
  96. package/docs/domDragPointer.mjs.html +1 -1
  97. package/docs/domDragPreview.mjs.html +1 -1
  98. package/docs/domDropFiles.mjs.html +1 -1
  99. package/docs/domElementsFromPoint.mjs.html +1 -1
  100. package/docs/domFadeIn.mjs.html +1 -1
  101. package/docs/domFadeOut.mjs.html +1 -1
  102. package/docs/domFind.mjs.html +1 -1
  103. package/docs/domFinds.mjs.html +1 -1
  104. package/docs/domGetAttr.mjs.html +1 -1
  105. package/docs/domGetBoudRect.mjs.html +1 -1
  106. package/docs/domGetBoudRectRefSelf.mjs.html +1 -1
  107. package/docs/domGetFileAccept.mjs.html +1 -1
  108. package/docs/domGetFiles.mjs.html +1 -1
  109. package/docs/domGetParents.mjs.html +1 -1
  110. package/docs/domGetPointFromEvent.mjs.html +1 -1
  111. package/docs/domGetScrollableParent.mjs.html +1 -1
  112. package/docs/domGetWindowSize.mjs.html +1 -1
  113. package/docs/domIsClientXYIn.mjs.html +1 -1
  114. package/docs/domIsFocused.mjs.html +1 -1
  115. package/docs/domIsStable.mjs.html +1 -1
  116. package/docs/domIsVisible.mjs.html +1 -1
  117. package/docs/domPrepend.mjs.html +1 -1
  118. package/docs/domRemove.mjs.html +1 -1
  119. package/docs/domRenderMarkdownMind.mjs.html +1 -1
  120. package/docs/domRenderMarkdownMindDyn.mjs.html +1 -1
  121. package/docs/domRipple.mjs.html +1 -1
  122. package/docs/domScrollIntoView.mjs.html +1 -1
  123. package/docs/domScrollTo.mjs.html +1 -1
  124. package/docs/domSetAttr.mjs.html +1 -1
  125. package/docs/domShowImages.mjs.html +1 -1
  126. package/docs/domShowImagesDyn.mjs.html +1 -1
  127. package/docs/domShowInputAndGetFiles.mjs.html +1 -1
  128. package/docs/domShowInputAndGetFilesU8Arrs.mjs.html +1 -1
  129. package/docs/domShowInputDatatime.mjs.html +1 -1
  130. package/docs/domTooltip.mjs.html +1 -1
  131. package/docs/domTriggerEvent.mjs.html +1 -1
  132. package/docs/domVirtualCreate.mjs.html +1 -1
  133. package/docs/domVirtualCreateQueue.mjs.html +1 -1
  134. package/docs/downloadExcelFileFromData.mjs.html +1 -1
  135. package/docs/downloadExcelFileFromDataDyn.mjs.html +1 -1
  136. package/docs/downloadFileFromB64.mjs.html +1 -1
  137. package/docs/downloadFileFromBlob.mjs.html +1 -1
  138. package/docs/downloadFileFromText.mjs.html +1 -1
  139. package/docs/downloadFileFromU8Arr.mjs.html +1 -1
  140. package/docs/dtmapping.mjs.html +1 -1
  141. package/docs/dtpick.mjs.html +1 -1
  142. package/docs/estimateTicks.mjs.html +1 -1
  143. package/docs/evEmit.mjs.html +1 -1
  144. package/docs/evEmitDelay.mjs.html +1 -1
  145. package/docs/evem.mjs.html +1 -1
  146. package/docs/examples/ex-blob2b64.html +1 -1
  147. package/docs/examples/ex-clearXSS.html +1 -1
  148. package/docs/examples/ex-clearXSSDyn.html +1 -1
  149. package/docs/examples/ex-colorConverter.html +1 -1
  150. package/docs/examples/ex-domCompareText.html +1 -1
  151. package/docs/examples/ex-domConvertToPic.html +1 -1
  152. package/docs/examples/ex-domDrag.html +1 -1
  153. package/docs/examples/ex-domDropFiles.html +1 -1
  154. package/docs/examples/ex-domIsVisible.html +1 -1
  155. package/docs/examples/ex-domRenderMarkdownMind.html +1 -1
  156. package/docs/examples/ex-domRenderMarkdownMindDyn.html +1 -1
  157. package/docs/examples/ex-domRipple.html +1 -1
  158. package/docs/examples/ex-domScrollIntoView.html +1 -1
  159. package/docs/examples/ex-domScrollTo.html +1 -1
  160. package/docs/examples/ex-domShowImages.html +1 -1
  161. package/docs/examples/ex-domShowImagesDyn.html +1 -1
  162. package/docs/examples/ex-domShowInputAndGetFiles.html +1 -1
  163. package/docs/examples/ex-domTooltip.html +1 -1
  164. package/docs/examples/ex-getFileHash.html +1 -1
  165. package/docs/examples/ex-getUserAgent.html +1 -1
  166. package/docs/examples/ex-getUserAgentDyn.html +1 -1
  167. package/docs/examples/ex-html2str.html +1 -1
  168. package/docs/examples/ex-obj2u8arr-u8arr2obj.html +1 -1
  169. package/docs/examples/ex-openLink.html +1 -1
  170. package/docs/examples/ex-str2aes-aes2str.html +1 -1
  171. package/docs/examples/ex-str2b64-b642str.html +1 -1
  172. package/docs/examples/ex-strFindFuzz.html +1 -1
  173. package/docs/examples/ex-timeTZ2expire-timeTZ2past.html +1 -1
  174. package/docs/examples/ex-xlsx.html +1 -1
  175. package/docs/execCli.mjs.html +1 -1
  176. package/docs/execCliCore.mjs.html +1 -1
  177. package/docs/execCliJsonRpc.mjs.html +1 -1
  178. package/docs/execCliSession.mjs.html +1 -1
  179. package/docs/execJsCode.mjs.html +1 -1
  180. package/docs/execProcess.mjs.html +1 -1
  181. package/docs/execProcessKillPid.mjs.html +1 -1
  182. package/docs/filepathToTree.mjs.html +1 -1
  183. package/docs/files2data.mjs.html +1 -1
  184. package/docs/flattenToConn.mjs.html +1 -1
  185. package/docs/flattenTree.mjs.html +1 -1
  186. package/docs/floor.mjs.html +1 -1
  187. package/docs/fsBuildReadStreamText.mjs.html +1 -1
  188. package/docs/fsBuildWriteStreamText.mjs.html +1 -1
  189. package/docs/fsCleanFolder.mjs.html +1 -1
  190. package/docs/fsCleanFolderCore.mjs.html +1 -1
  191. package/docs/fsCopyFile.mjs.html +1 -1
  192. package/docs/fsCopyFileCore.mjs.html +1 -1
  193. package/docs/fsCopyFolder.mjs.html +1 -1
  194. package/docs/fsCopyFolderCore.mjs.html +1 -1
  195. package/docs/fsCreateFile.mjs.html +1 -1
  196. package/docs/fsCreateFileCore.mjs.html +1 -1
  197. package/docs/fsCreateFolder.mjs.html +1 -1
  198. package/docs/fsCreateFolderCore.mjs.html +1 -1
  199. package/docs/fsDeleteFile.mjs.html +1 -1
  200. package/docs/fsDeleteFileCore.mjs.html +1 -1
  201. package/docs/fsDeleteFileSafe.mjs.html +1 -1
  202. package/docs/fsDeleteFileSafeCore.mjs.html +1 -1
  203. package/docs/fsDeleteFolder.mjs.html +1 -1
  204. package/docs/fsDeleteFolderCore.mjs.html +1 -1
  205. package/docs/fsDeleteFolderSafe.mjs.html +1 -1
  206. package/docs/fsDeleteFolderSafeCore.mjs.html +1 -1
  207. package/docs/fsDownloadFile.mjs.html +1 -1
  208. package/docs/fsDownloadFileCore.mjs.html +1 -1
  209. package/docs/fsEvem.mjs.html +1 -1
  210. package/docs/fsExists.mjs.html +1 -1
  211. package/docs/fsExistsCore.mjs.html +1 -1
  212. package/docs/fsGetFileBasicHash.mjs.html +1 -1
  213. package/docs/fsGetFileBasicHashCore.mjs.html +1 -1
  214. package/docs/fsGetFileHash.mjs.html +1 -1
  215. package/docs/fsGetFileHashCore.mjs.html +1 -1
  216. package/docs/fsGetFileXxHash.mjs.html +1 -1
  217. package/docs/fsGetFileXxHashCore.mjs.html +1 -1
  218. package/docs/fsGetFilesInFolder.mjs.html +1 -1
  219. package/docs/fsGetFilesInFolderCore.mjs.html +1 -1
  220. package/docs/fsGetFilesWithHashInFolder.mjs.html +1 -1
  221. package/docs/fsGetFilesWithHashInFolderCore.mjs.html +1 -1
  222. package/docs/fsGetFolderBasicHash.mjs.html +1 -1
  223. package/docs/fsGetFolderBasicHashCore.mjs.html +1 -1
  224. package/docs/fsGetFoldersInFolder.mjs.html +1 -1
  225. package/docs/fsGetFoldersInFolderCore.mjs.html +1 -1
  226. package/docs/fsIsFile.mjs.html +1 -1
  227. package/docs/fsIsFileCore.mjs.html +1 -1
  228. package/docs/fsIsFolder.mjs.html +1 -1
  229. package/docs/fsIsFolderCore.mjs.html +1 -1
  230. package/docs/fsMergeFiles.mjs.html +1 -1
  231. package/docs/fsMergeFilesCore.mjs.html +1 -1
  232. package/docs/fsReadJson.mjs.html +1 -1
  233. package/docs/fsReadText.mjs.html +1 -1
  234. package/docs/fsReadTextCore.mjs.html +1 -1
  235. package/docs/fsRenameFile.mjs.html +1 -1
  236. package/docs/fsRenameFileCore.mjs.html +1 -1
  237. package/docs/fsRenameFolder.mjs.html +1 -1
  238. package/docs/fsRenameFolderCore.mjs.html +1 -1
  239. package/docs/fsSrlog.mjs.html +1 -1
  240. package/docs/fsSyncFolder.mjs.html +1 -1
  241. package/docs/fsSyncFolderCore.mjs.html +1 -1
  242. package/docs/fsTask.mjs.html +1 -1
  243. package/docs/fsTaskCp.mjs.html +1 -1
  244. package/docs/fsTreeFolder.mjs.html +1 -1
  245. package/docs/fsTreeFolderCore.mjs.html +1 -1
  246. package/docs/fsTreeFolderWithHash.mjs.html +1 -1
  247. package/docs/fsTreeFolderWithHashCore.mjs.html +1 -1
  248. package/docs/fsWatchFile.mjs.html +1 -1
  249. package/docs/fsWatchFolder.mjs.html +1 -1
  250. package/docs/fsWriteJson.mjs.html +1 -1
  251. package/docs/fsWriteText.mjs.html +1 -1
  252. package/docs/fsWriteTextCore.mjs.html +1 -1
  253. package/docs/genGradientColor.mjs.html +1 -1
  254. package/docs/genID.mjs.html +1 -1
  255. package/docs/genIDSeq.mjs.html +1 -1
  256. package/docs/genPm.mjs.html +1 -1
  257. package/docs/getBufferSize.mjs.html +1 -1
  258. package/docs/getClearPathName.mjs.html +1 -1
  259. package/docs/getCsvStrFromData.mjs.html +1 -1
  260. package/docs/getDataFromExcelFileU8Arr.mjs.html +1 -1
  261. package/docs/getDataFromExcelFileU8ArrDyn.mjs.html +1 -1
  262. package/docs/getEnv.mjs.html +1 -1
  263. package/docs/getErrorMessage.mjs.html +1 -1
  264. package/docs/getExcelU8ArrFromData.mjs.html +1 -1
  265. package/docs/getExcelU8ArrFromWorkbook.mjs.html +1 -1
  266. package/docs/getExcelWorkbookFromData.mjs.html +1 -1
  267. package/docs/getExcelWorkbookFromWorksheet.mjs.html +1 -1
  268. package/docs/getExcelWorksheetFromData.mjs.html +1 -1
  269. package/docs/getFileAccept.mjs.html +1 -1
  270. package/docs/getFileBasicHash.mjs.html +1 -1
  271. package/docs/getFileHash.mjs.html +1 -1
  272. package/docs/getFileName.mjs.html +1 -1
  273. package/docs/getFileNameExt.mjs.html +1 -1
  274. package/docs/getFileTrueName.mjs.html +1 -1
  275. package/docs/getFileType.mjs.html +1 -1
  276. package/docs/getFileXxHash.mjs.html +1 -1
  277. package/docs/getGlobal.mjs.html +1 -1
  278. package/docs/getObjSize.mjs.html +1 -1
  279. package/docs/getPathParent.mjs.html +1 -1
  280. package/docs/getTimeBetween.mjs.html +1 -1
  281. package/docs/getTimeFromUnit.mjs.html +1 -1
  282. package/docs/getTimeHp.mjs.html +1 -1
  283. package/docs/getTimeObject.mjs.html +1 -1
  284. package/docs/getTimeRange.mjs.html +1 -1
  285. package/docs/getUserAgent.mjs.html +1 -1
  286. package/docs/getUserAgentDyn.mjs.html +1 -1
  287. package/docs/getltdtkeys.mjs.html +1 -1
  288. package/docs/global.html +1 -1
  289. package/docs/haskey.mjs.html +1 -1
  290. package/docs/html2str.mjs.html +1 -1
  291. package/docs/htmlDecode.mjs.html +1 -1
  292. package/docs/htmlEncode.mjs.html +1 -1
  293. package/docs/importResources.mjs.html +1 -1
  294. package/docs/index.html +1 -1
  295. package/docs/interp1.mjs.html +1 -1
  296. package/docs/isDate.mjs.html +1 -1
  297. package/docs/isDev.mjs.html +1 -1
  298. package/docs/isEle.mjs.html +1 -1
  299. package/docs/isEleExistByID.mjs.html +1 -1
  300. package/docs/isEmail.mjs.html +1 -1
  301. package/docs/isErr.mjs.html +1 -1
  302. package/docs/isIE.mjs.html +1 -1
  303. package/docs/isNarrow.mjs.html +1 -1
  304. package/docs/isStrHasCapital.mjs.html +1 -1
  305. package/docs/isStrHasLetter.mjs.html +1 -1
  306. package/docs/isStrHasLowerCase.mjs.html +1 -1
  307. package/docs/isStrHasNumber.mjs.html +1 -1
  308. package/docs/isStrHasSpace.mjs.html +1 -1
  309. package/docs/isStrHasSymbol.mjs.html +1 -1
  310. package/docs/isUserIdentify.mjs.html +1 -1
  311. package/docs/isUserName.mjs.html +1 -1
  312. package/docs/isUserPw.mjs.html +1 -1
  313. package/docs/isWindow.mjs.html +1 -1
  314. package/docs/isab.mjs.html +1 -1
  315. package/docs/isarr.mjs.html +1 -1
  316. package/docs/isarr0.mjs.html +1 -1
  317. package/docs/isarr1.mjs.html +1 -1
  318. package/docs/isbigint.mjs.html +1 -1
  319. package/docs/isblob.mjs.html +1 -1
  320. package/docs/isbol.mjs.html +1 -1
  321. package/docs/isday.mjs.html +1 -1
  322. package/docs/isearr.mjs.html +1 -1
  323. package/docs/iseobj.mjs.html +1 -1
  324. package/docs/iser.mjs.html +1 -1
  325. package/docs/isernot.mjs.html +1 -1
  326. package/docs/isestr.mjs.html +1 -1
  327. package/docs/isfile.mjs.html +1 -1
  328. package/docs/isfun.mjs.html +1 -1
  329. package/docs/isint.mjs.html +1 -1
  330. package/docs/ismonth.mjs.html +1 -1
  331. package/docs/isn0int.mjs.html +1 -1
  332. package/docs/isn0num.mjs.html +1 -1
  333. package/docs/isnan.mjs.html +1 -1
  334. package/docs/isnbr.mjs.html +1 -1
  335. package/docs/isnint.mjs.html +1 -1
  336. package/docs/isnnum.mjs.html +1 -1
  337. package/docs/isnull.mjs.html +1 -1
  338. package/docs/isnum.mjs.html +1 -1
  339. package/docs/isobj.mjs.html +1 -1
  340. package/docs/isobj0.mjs.html +1 -1
  341. package/docs/isp0int.mjs.html +1 -1
  342. package/docs/isp0num.mjs.html +1 -1
  343. package/docs/ispint.mjs.html +1 -1
  344. package/docs/ispm.mjs.html +1 -1
  345. package/docs/ispnum.mjs.html +1 -1
  346. package/docs/isstr.mjs.html +1 -1
  347. package/docs/isstr0.mjs.html +1 -1
  348. package/docs/istime.mjs.html +1 -1
  349. package/docs/istimeTZ.mjs.html +1 -1
  350. package/docs/istimems.mjs.html +1 -1
  351. package/docs/istimemsTZ.mjs.html +1 -1
  352. package/docs/isu16arr.mjs.html +1 -1
  353. package/docs/isu8arr.mjs.html +1 -1
  354. package/docs/isundefined.mjs.html +1 -1
  355. package/docs/j2o.mjs.html +1 -1
  356. package/docs/judge.mjs.html +1 -1
  357. package/docs/keysmat2ltdt.mjs.html +1 -1
  358. package/docs/ltdt2vrtsable.mjs.html +1 -1
  359. package/docs/ltdtDiff.mjs.html +1 -1
  360. package/docs/ltdtDiffByKey.mjs.html +1 -1
  361. package/docs/ltdtkeys2mat.mjs.html +1 -1
  362. package/docs/ltdtkeysheads2mat.mjs.html +1 -1
  363. package/docs/ltdtmapping.mjs.html +1 -1
  364. package/docs/ltdtmerge.mjs.html +1 -1
  365. package/docs/ltdtpick.mjs.html +1 -1
  366. package/docs/ltdtpull.mjs.html +1 -1
  367. package/docs/mat2ltdt.mjs.html +1 -1
  368. package/docs/matConcat.mjs.html +1 -1
  369. package/docs/matDiff.mjs.html +1 -1
  370. package/docs/matat.mjs.html +1 -1
  371. package/docs/now2str.mjs.html +1 -1
  372. package/docs/now2strp.mjs.html +1 -1
  373. package/docs/nowDay2str.mjs.html +1 -1
  374. package/docs/nowms2str.mjs.html +1 -1
  375. package/docs/nowms2strp.mjs.html +1 -1
  376. package/docs/o2j.mjs.html +1 -1
  377. package/docs/obj2b64.mjs.html +1 -1
  378. package/docs/obj2pb64.mjs.html +1 -1
  379. package/docs/obj2str.mjs.html +1 -1
  380. package/docs/obj2stru8arr.mjs.html +1 -1
  381. package/docs/obj2u8arr.mjs.html +1 -1
  382. package/docs/objSortBy.mjs.html +1 -1
  383. package/docs/objSortByKeys.mjs.html +1 -1
  384. package/docs/oo.mjs.html +1 -1
  385. package/docs/openLink.mjs.html +1 -1
  386. package/docs/pb642obj.mjs.html +1 -1
  387. package/docs/pmChain.mjs.html +1 -1
  388. package/docs/pmConvertResolve.mjs.html +1 -1
  389. package/docs/pmDebounce.mjs.html +1 -1
  390. package/docs/pmHook.mjs.html +1 -1
  391. package/docs/pmHookReject.mjs.html +1 -1
  392. package/docs/pmIni.mjs.html +1 -1
  393. package/docs/pmInvResolve.mjs.html +1 -1
  394. package/docs/pmKeyMutex.mjs.html +1 -1
  395. package/docs/pmMap.mjs.html +1 -1
  396. package/docs/pmQueue.mjs.html +1 -1
  397. package/docs/pmSeries.mjs.html +1 -1
  398. package/docs/pmThrottle.mjs.html +1 -1
  399. package/docs/pmTimeout.mjs.html +1 -1
  400. package/docs/preciseNum.mjs.html +1 -1
  401. package/docs/pseudoRandom.mjs.html +1 -1
  402. package/docs/pseudoRandomIntRange.mjs.html +1 -1
  403. package/docs/pseudoRandomIntsNdpRange.mjs.html +1 -1
  404. package/docs/pseudoRandomIntsRange.mjs.html +1 -1
  405. package/docs/pseudoRandomRange.mjs.html +1 -1
  406. package/docs/pseudoRandomsRange.mjs.html +1 -1
  407. package/docs/queue.mjs.html +1 -1
  408. package/docs/random.mjs.html +1 -1
  409. package/docs/randomIntRange.mjs.html +1 -1
  410. package/docs/randomIntsNdpRange.mjs.html +1 -1
  411. package/docs/randomIntsRange.mjs.html +1 -1
  412. package/docs/randomRange.mjs.html +1 -1
  413. package/docs/randomsRange.mjs.html +1 -1
  414. package/docs/rang.mjs.html +1 -1
  415. package/docs/rep.mjs.html +1 -1
  416. package/docs/repObj.mjs.html +1 -1
  417. package/docs/replace.mjs.html +1 -1
  418. package/docs/replaceObj.mjs.html +1 -1
  419. package/docs/replacePlus.mjs.html +1 -1
  420. package/docs/round.mjs.html +1 -1
  421. package/docs/secd.mjs.html +1 -1
  422. package/docs/sep.mjs.html +1 -1
  423. package/docs/sepInt.mjs.html +1 -1
  424. package/docs/setIntervalHp.mjs.html +1 -1
  425. package/docs/setTimeoutHp.mjs.html +1 -1
  426. package/docs/sind.mjs.html +1 -1
  427. package/docs/split.mjs.html +1 -1
  428. package/docs/str2aes.mjs.html +1 -1
  429. package/docs/str2b64.mjs.html +1 -1
  430. package/docs/str2hint.mjs.html +1 -1
  431. package/docs/str2md5.mjs.html +1 -1
  432. package/docs/str2obj.mjs.html +1 -1
  433. package/docs/str2sha.mjs.html +1 -1
  434. package/docs/str2sha512.mjs.html +1 -1
  435. package/docs/str2u8arr.mjs.html +1 -1
  436. package/docs/strCompare.mjs.html +1 -1
  437. package/docs/strCompareForVersion.mjs.html +1 -1
  438. package/docs/strDiff.mjs.html +1 -1
  439. package/docs/strDiffToHtml.mjs.html +1 -1
  440. package/docs/strFindFuzz.mjs.html +1 -1
  441. package/docs/strFindSimilar.mjs.html +1 -1
  442. package/docs/strTruncate.mjs.html +1 -1
  443. package/docs/strdelleft.mjs.html +1 -1
  444. package/docs/strdelright.mjs.html +1 -1
  445. package/docs/strleft.mjs.html +1 -1
  446. package/docs/strmid.mjs.html +1 -1
  447. package/docs/strright.mjs.html +1 -1
  448. package/docs/stru8arr2obj.mjs.html +1 -1
  449. package/docs/tand.mjs.html +1 -1
  450. package/docs/time2day.mjs.html +1 -1
  451. package/docs/time2hour.mjs.html +1 -1
  452. package/docs/time2min.mjs.html +1 -1
  453. package/docs/timeTZ2day.mjs.html +1 -1
  454. package/docs/timeTZ2expire.mjs.html +1 -1
  455. package/docs/timeTZ2hour.mjs.html +1 -1
  456. package/docs/timeTZ2min.mjs.html +1 -1
  457. package/docs/timeTZ2past.mjs.html +1 -1
  458. package/docs/timems2day.mjs.html +1 -1
  459. package/docs/timems2hour.mjs.html +1 -1
  460. package/docs/timems2min.mjs.html +1 -1
  461. package/docs/timems2time.mjs.html +1 -1
  462. package/docs/timemsTZ2day.mjs.html +1 -1
  463. package/docs/timemsTZ2expire.mjs.html +1 -1
  464. package/docs/timemsTZ2hour.mjs.html +1 -1
  465. package/docs/timemsTZ2min.mjs.html +1 -1
  466. package/docs/timemsTZ2past.mjs.html +1 -1
  467. package/docs/timemsTZ2time.mjs.html +1 -1
  468. package/docs/treeObj.mjs.html +1 -1
  469. package/docs/treeToFilepath.mjs.html +1 -1
  470. package/docs/trim.mjs.html +1 -1
  471. package/docs/u16arr2b64.mjs.html +1 -1
  472. package/docs/u16arr2u8arr.mjs.html +1 -1
  473. package/docs/u8arr2ab.mjs.html +1 -1
  474. package/docs/u8arr2b64.mjs.html +1 -1
  475. package/docs/u8arr2blob.mjs.html +1 -1
  476. package/docs/u8arr2bs.mjs.html +1 -1
  477. package/docs/u8arr2obj.mjs.html +1 -1
  478. package/docs/u8arr2str.mjs.html +1 -1
  479. package/docs/u8arr2u16arr.mjs.html +1 -1
  480. package/docs/urlParse.mjs.html +1 -1
  481. package/docs/verifyValue.mjs.html +1 -1
  482. package/docs/waitFun.mjs.html +1 -1
  483. package/docs/wsemi.html +6 -20
  484. package/package.json +1 -1
  485. package/src/domDetect.mjs +461 -570
  486. package/test/domDetect.test.mjs +854 -684
  487. package/toolfp/dist/wsemip.umd.js +1 -1
  488. package/toolparfor/dist/wpf.umd.js +1 -1
  489. package/toolparfor/dist/wpf_pmSeries.umd.js +1 -1
  490. package//345/273/272/350/255/260wsemi/350/252/277/346/225/264.md +457 -0
@@ -45,576 +45,467 @@
45
45
 
46
46
  <section>
47
47
  <article>
48
- <pre class="prettyprint source linenums"><code>import get from 'lodash-es/get.js'
49
- import ispint from './ispint.mjs'
50
- import isp0int from './isp0int.mjs'
51
- import evem from './evem.mjs'
52
- import isfun from './isfun.mjs'
53
-
54
-
55
- //2020年曾以IntersectionObserver與ResizeObserver實作(即下方註解舊碼), 因下列實作缺陷致WTextSelect下拉選單不穩而改為輪詢:
56
- //1.元素尺寸為0(隱藏或移出DOM)時仍發出resize, 使用端讀到高度0而算錯版面
57
- //2.clear未防空值, 元素尚未取得即clear時拋錯, 且已建立之觀察器與已排定之事件未解除
58
- //3.觀察器只綁首次取得之元素, 元素被換成新節點後即失去偵測
59
- //現以ResizeObserver偵測尺寸, 並以共用MutationObserver於[元素取不到、不在頁面中或尺寸為0]時重新取得元素, 逐一對應上述缺陷; 無ResizeObserver或MutationObserver時退回輪詢
60
-
61
-
62
- // function domDetect(f, opt = {}) {
63
-
64
- //使用IntersectionObserver與ResizeObserver時, 當顯隱頻繁導致元素尚未出現需等待與過快清除時, 會導致WTextSelect下拉選單無法穩定出現內容問題
65
-
66
- // let ele = null
67
- // let obInts = null
68
- // let obRes = null
69
-
70
- // //tolerancePixel
71
- // let tolerancePixel = get(opt, 'tolerancePixel', null)
72
- // if (!ispint(tolerancePixel)) {
73
- // tolerancePixel = 1
74
- // }
75
-
76
- // //ev
77
- // let ev = evem()
78
-
79
- // //timer, sold
80
- // let timer
81
- // let sold = {
82
- // offsetWidth: 0,
83
- // offsetHeight: 0,
84
- // }
85
-
86
- // //check
87
- // if (!isfun(f)) {
88
- // console.log('invalid f', f)
89
- // return ev
90
- // }
91
-
92
- // //check
93
- // if (!window.IntersectionObserver) {
94
- // console.log('invalid IntersectionObserver')
95
- // return ev
96
- // }
97
-
98
- // //check
99
- // if (!window.ResizeObserver) {
100
- // console.log('invalid ResizeObserver')
101
- // return ev
102
- // }
103
-
104
- // //setInterval
105
- // timer = setInterval(() => {
106
-
107
- // //execute
108
- // let eleTemp = f()
109
-
110
- // //check
111
- // if (eleTemp) {
112
-
113
- // //save
114
- // ele = eleTemp
115
-
116
- // //obInts
117
- // if (!obInts) {
118
- // obInts = new window.IntersectionObserver((entries) => {
119
- // let entry = entries[0]
120
-
121
- // setTimeout(() => { //emit觸發事件為同步, 用setTimeout脫勾
122
- // ev.emit('display', { mode: entry.isIntersecting ? 'show' : 'hide', ele })
123
- // }, 1)
124
-
125
- // })
126
- // obInts.observe(ele)
127
- // }
128
-
129
- // //obRes
130
- // if (!obRes) {
131
- // obRes = new window.ResizeObserver((entries) => {
132
- // // let entry = entries[0]
133
-
134
- // //new size
135
- // let snew = {
136
- // offsetWidth: ele.offsetWidth,
137
- // offsetHeight: ele.offsetHeight,
138
- // }
139
-
140
- // //save sold
141
- // let soldt = { ...sold }
142
-
143
- // //tolerancePixel
144
- // let bw = Math.abs(sold.offsetWidth - snew.offsetWidth) > tolerancePixel
145
- // let bh = Math.abs(sold.offsetHeight - snew.offsetHeight) > tolerancePixel
146
-
147
- // if (bw || bh) {
148
- // setTimeout(() => { //emit觸發事件為同步, 用setTimeout脫勾
149
- // ev.emit('resize', { sold: soldt, snew, ele })
150
- // ev.emit('resizeWithWindow', { sold: soldt, snew, ele, from: 'dom' })
151
- // }, 1)
152
- // }
153
-
154
- // //save
155
- // sold = snew
156
-
157
- // })
158
- // obRes.observe(ele)
159
- // }
160
-
161
- // //clearInterval
162
- // clearInterval(timer)
163
-
164
- // }
165
-
166
- // }, 10)
167
-
168
- // //fWindowResize
169
- // let fWindowResize = (e) => {
170
- // ev.emit('resizeWithWindow', { snew: sold, from: 'window' })
171
- // }
172
- // window.addEventListener('resize', fWindowResize)
173
-
174
- // //clear
175
- // ev.clear = () => {
176
- // obInts.unobserve(ele)
177
- // obRes.unobserve(ele)
178
- // clearInterval(timer) //若一直沒偵測到元素故也需要強制中止timer
179
- // window.removeEventListener('resize', fWindowResize)
180
- // }
181
-
182
- // return ev
183
- // }
184
-
185
-
186
- //waiting, 等待重新取得元素之偵測器; mo, 共用之MutationObserver, 僅於有偵測器等待時啟用
187
- let waiting = new Set()
188
- let mo = null
189
-
190
-
191
- function waitAdd(fn) {
192
- waiting.add(fn)
193
- if (!mo) {
194
- mo = new window.MutationObserver(() => {
195
- for (let g of Array.from(waiting)) {
196
- g()
197
- }
198
- })
199
- mo.observe(document.documentElement, { childList: true, subtree: true })
200
- }
201
- }
202
-
203
-
204
- function waitRemove(fn) {
205
- waiting.delete(fn)
206
- if (waiting.size === 0 &amp;&amp; mo) {
207
- mo.disconnect()
208
- mo = null
209
- }
210
- }
211
-
212
-
213
- function getTimeInterval(opt) {
214
- let timeInterval = get(opt, 'timeInterval', null)
215
- if (!ispint(timeInterval)) {
216
- timeInterval = 20
217
- }
218
- return timeInterval
219
- }
220
-
221
-
222
- function getTolerancePixel(opt) {
223
- let tolerancePixel = get(opt, 'tolerancePixel', null)
224
- if (!isp0int(tolerancePixel)) { //可給0, 表示任何變化皆發出
225
- tolerancePixel = 1
226
- }
227
- return tolerancePixel
228
- }
229
-
230
-
231
- //getEle, f()拋錯或回傳非元素時視為取不到, 不中斷偵測
232
- function getEle(f) {
233
- let p = null
234
- try {
235
- p = f()
236
- }
237
- catch (err) {
238
- p = null
239
- }
240
- return (p &amp;&amp; p.nodeType === 1) ? p : null
241
- }
242
-
243
-
244
- function sizeZero() {
245
- return {
246
- offsetWidth: 0,
247
- offsetHeight: 0,
248
- clientWidth: 0,
249
- clientHeight: 0,
250
- windowWidth: 0,
251
- windowHeight: 0,
252
- }
253
- }
254
-
255
-
256
- function measure(p) {
257
- return {
258
- offsetWidth: p.offsetWidth,
259
- offsetHeight: p.offsetHeight,
260
- clientWidth: p.clientWidth,
261
- clientHeight: p.clientHeight,
262
- windowWidth: window.innerWidth,
263
- windowHeight: window.innerHeight,
264
- }
265
- }
266
-
267
-
268
- //createCore, 輪詢與ResizeObserver兩種模式共用之比較、發出、視窗事件與清除, 使兩者之規則只寫一處
269
- // 比較基準sb為上次發出事件時之尺寸, 差值超過容許誤差才更新; 若每次量測皆更新基準, 緩慢之連續小變化(如逐px拖曳或縮放視窗)永遠不會超過容許誤差, 累積再大也不發出
270
- // 尺寸為0時差值必超過容許誤差而使基準歸0, 故由隱藏恢復顯示時必發出
271
- function createCore(ev, opt) {
272
-
273
- //tolerancePixel
274
- let tolerancePixel = getTolerancePixel(opt)
275
-
276
- //sync, 於ResizeObserver回呼內同步發出事件(繪製前), 供須於同一幀更新版面之使用端(例如圖表重繪); 預設以setTimeout脫勾
277
- let sync = get(opt, 'sync', false) === true
278
-
279
- //cleared, st, sd, sb, smode, timers
280
- let cleared = false
281
- let st = sizeZero() //前次量測
282
- let sd = sizeZero() //最新量測
283
- let sb = sizeZero() //比較基準, 上次發出事件時之尺寸
284
- let smode = {
285
- width: '',
286
- height: '',
287
- }
288
- let timers = new Set()
289
-
290
- //emit
291
- let emit = (sold, snew, sm, p) => {
292
-
293
- //cleared, clear後不再發出已排定之事件
294
- if (cleared) {
295
- return
296
- }
297
-
298
- //detect resize, 尺寸為0(隱藏或移出DOM)不發出
299
- if (snew.offsetWidth > 0 &amp;&amp; snew.offsetHeight > 0) {
300
- ev.emit('resize', {
301
- sold,
302
- snew,
303
- smode: sm,
304
- ele: p,
305
- })
306
-
307
- //cleared, resize之監聽器內可能呼叫clear
308
- if (cleared) {
309
- return
310
- }
311
-
312
- ev.emit('resizeWithWindow', {
313
- sold,
314
- snew,
315
- smode: sm,
316
- ele: p,
317
- from: 'dom',
318
- })
319
- }
320
-
321
- }
322
-
323
- //check, 量測並與比較基準比較
324
- let check = (p, allowSync) => {
325
- if (cleared || !p) {
326
- return
327
- }
328
-
329
- //new size
330
- let snew = measure(p)
331
-
332
- //dw, dh
333
- let dw = sb.offsetWidth - snew.offsetWidth
334
- let dh = sb.offsetHeight - snew.offsetHeight
335
-
336
- //bw, bh
337
- let bw = Math.abs(dw) > tolerancePixel
338
- let bh = Math.abs(dh) > tolerancePixel
339
-
340
- //smode
341
- smode = {
342
- width: dw > 0 ? 'smaller' : (dw &lt; 0 ? 'larger' : ''),
343
- height: dh > 0 ? 'smaller' : (dh &lt; 0 ? 'larger' : ''),
344
- }
345
-
346
- //save
347
- st = sd
348
- sd = snew
349
-
350
- //check
351
- if (!bw &amp;&amp; !bh) {
352
- return
353
- }
354
-
355
- //sold, sb
356
- let sold = sb
357
- sb = snew
358
- let sm = { ...smode }
359
-
360
- //emit
361
- if (allowSync &amp;&amp; sync) {
362
- emit(sold, snew, sm, p)
363
- return
364
- }
365
- let t = setTimeout(() => { //emit觸發事件為同步, 用setTimeout脫勾
366
- timers.delete(t)
367
- emit(sold, snew, sm, p)
368
- }, 1)
369
- timers.add(t)
370
-
371
- }
372
-
373
- //fWindowResize, 視窗尺寸取當下值, 否則元素尺寸未變時會一直帶著上次量測時之視窗尺寸
374
- let fWindowResize = (e) => {
375
- if (cleared) {
376
- return
377
- }
378
- sd = {
379
- ...sd,
380
- windowWidth: window.innerWidth,
381
- windowHeight: window.innerHeight,
382
- }
383
- ev.emit('resizeWithWindow', {
384
- sold: st,
385
- snew: sd,
386
- smode,
387
- from: 'window',
388
- })
389
- }
390
- window.addEventListener('resize', fWindowResize)
391
-
392
- //clear
393
- let clear = () => {
394
- cleared = true
395
- for (let t of timers) {
396
- clearTimeout(t)
397
- }
398
- timers.clear()
399
- window.removeEventListener('resize', fWindowResize)
400
- }
401
-
402
- return {
403
- check,
404
- clear,
405
- isCleared: () => cleared,
406
- isVisible: () => sd.offsetWidth > 0 &amp;&amp; sd.offsetHeight > 0,
407
- }
408
- }
409
-
410
-
411
- function domDetectByPolling(f, opt = {}) {
412
-
413
- //check
414
- if (!isfun(f)) {
415
- console.log('invalid f', f)
416
- return null
417
- }
418
-
419
- //ev, core
420
- let ev = evem()
421
- let core = createCore(ev, opt)
422
-
423
- //setInterval
424
- let timer = setInterval(() => {
425
- let p = getEle(f)
426
- if (p) {
427
- core.check(p, false)
428
- }
429
- }, getTimeInterval(opt))
430
-
431
- //clear
432
- ev.clear = () => {
433
- clearInterval(timer)
434
- core.clear()
435
- }
436
-
437
- return ev
438
- }
439
-
440
-
441
- function domDetectByObserver(f, opt = {}) {
442
-
443
- //check
444
- if (!isfun(f)) {
445
- console.log('invalid f', f)
446
- return null
447
- }
448
-
449
- //watchIdentity, 元素可見時亦持續於DOM變動時重新取得元素, 供f()可能於舊元素仍可見時改回傳他元素之使用端
450
- let watchIdentity = get(opt, 'watchIdentity', false) === true
451
-
452
- //timeInterval, 行內元素改以定期量測時使用
453
- let timeInterval = getTimeInterval(opt)
454
-
455
- //ev, core
456
- let ev = evem()
457
- let core = createCore(ev, opt)
458
-
459
- //ele, timerInline, roBorder, roContent
460
- let ele = null
461
- let timerInline = null
462
- let roBorder = null
463
- let roContent = null
464
-
465
- //syncInline, 非替換之行內元素ResizeObserver不回報(規範明定), 取得之元素為display:inline時改以定期量測, 不為inline時停止
466
- let syncInline = () => {
467
- let inline = false
468
- if (ele) {
469
- try {
470
- inline = window.getComputedStyle(ele).display === 'inline'
471
- }
472
- catch (err) {
473
- inline = false
474
- }
475
- }
476
- if (inline &amp;&amp; timerInline === null) {
477
- timerInline = setInterval(onResize, timeInterval)
478
- }
479
- else if (!inline &amp;&amp; timerInline !== null) {
480
- clearInterval(timerInline)
481
- timerInline = null
482
- }
483
- }
484
-
485
- //retarget, 重新取得元素: 換成新節點時改觀察新節點, 新節點之首次回報由check比較
486
- // 同時觀察border-box與content-box: 比較用之offsetWidth即border-box, 只觀察content-box會漏掉只改padding或border之變化; content-box則使捲軸出現或消失時clientWidth保持最新
487
- let retarget = () => {
488
- if (core.isCleared()) {
489
- return
490
- }
491
- let p = getEle(f)
492
- if (p === ele) {
493
- return
494
- }
495
- if (ele) {
496
- roBorder.unobserve(ele)
497
- roContent.unobserve(ele)
498
- }
499
- ele = p
500
- if (ele) {
501
- roBorder.observe(ele, { box: 'border-box' })
502
- roContent.observe(ele)
503
- }
504
- syncInline()
505
- }
506
-
507
- //updateWaiting, 元素取不到、不在頁面中或尺寸為0時登記等待DOM變動:
508
- // 元素消失(移除或換新節點)時ResizeObserver無從得知新節點, 且已隱藏(尺寸0)之元素再被移除時尺寸0→0不會回報, 故尺寸為0時亦須等待
509
- let updateWaiting = () => {
510
- if (core.isCleared()) {
511
- return
512
- }
513
- let visible = ele &amp;&amp; ele.isConnected &amp;&amp; core.isVisible()
514
- if (visible &amp;&amp; !watchIdentity) {
515
- waitRemove(onDomChange)
516
- }
517
- else {
518
- waitAdd(onDomChange)
519
- }
520
- }
521
-
522
- //onDomChange, 僅重新取得元素不量測, 避免強制重排版; 換新節點後由ResizeObserver之首次回報觸發check
523
- let onDomChange = () => {
524
- retarget()
525
- updateWaiting()
526
- }
527
-
528
- //onResize
529
- let onResize = () => {
530
- retarget()
531
- try {
532
- core.check(ele, true)
533
- }
534
- finally {
535
- //sync模式下監聽器拋錯時仍須更新行內與等待狀態
536
- syncInline()
537
- updateWaiting()
538
- }
539
- }
540
-
541
- //roBorder, roContent
542
- roBorder = new window.ResizeObserver(onResize)
543
- roContent = new window.ResizeObserver(onResize)
544
-
545
- //initialize
546
- retarget()
547
- updateWaiting()
548
-
549
- //clear, 可於任何時點呼叫(含元素尚未取得), 並取消已排定之事件
550
- ev.clear = () => {
551
- if (core.isCleared()) {
552
- return
553
- }
554
- core.clear()
555
- waitRemove(onDomChange)
556
- roBorder.disconnect()
557
- roContent.disconnect()
558
- if (timerInline !== null) {
559
- clearInterval(timerInline)
560
- timerInline = null
561
- }
562
- ele = null
563
- }
564
-
565
- return ev
566
- }
567
-
568
-
569
- /**
570
- * 前端針對DOM元素監聽resize、resizeWithWindow事件,其中resizeWithWindow為dom resize與window resize皆會觸發的事件
571
- *
572
- * 瀏覽器支援ResizeObserver與MutationObserver時以其偵測(即時且閒置時不耗資源),否則退回定期輪詢,兩者之比較規則與事件相同:以offsetWidth、offsetHeight與比較基準之差超過容許誤差即發出,比較基準為上次發出事件時之尺寸,故緩慢之連續小變化累積超過容許誤差亦會發出;尺寸為0(隱藏或移出DOM)不發出,由隱藏恢復顯示時會發出,首次取得非0尺寸時會發出
573
- *
574
- * 元素可取不到、中途消失或重建為新節點:取不到、不在頁面中或尺寸為0時,於DOM變動時重新以f取得元素並改觀察之。行內元素(display:inline)ResizeObserver不回報,該偵測器改以定期量測
575
- *
576
- * 事件內容:sold為比較基準(上次發出事件時之尺寸),snew為本次量測,smode為寬與高相對比較基準之變化方向('larger'、'smaller'或''),ele為元素;from為'window'之事件其snew為最新量測,其中視窗尺寸取事件當下之值
577
- *
578
- * 已知限制:ResizeObserver模式下,僅屬性變化(如class)使f改指他元素、或Shadow DOM內之節點被替換時不會跟隨,此類使用端請用mode:'polling';sync為true時監聽器不得使所監聽元素之尺寸於同一幀內再變,否則瀏覽器回報ResizeObserver loop錯誤;Safari 15.4以前不支援觀察border-box,只改padding或border之變化於該處不會發出
579
- *
580
- * Unit Test: {@link https://github.com/yuda-lyu/wsemi/blob/master/test/domDetect.test.mjs Github}
581
- * @memberOf wsemi
582
- * @param {Function} f 輸入取得dom函數,可回傳null表示目前取不到
583
- * @param {Object} [opt={}] 輸入設定物件,預設{}
584
- * @param {String} [opt.mode=''] 輸入偵測模式字串,給'polling'則強制使用定期輪詢,預設''
585
- * @param {Integer} [opt.timeInterval=20] 輸入定期偵測時間整數,單位毫秒,用於輪詢模式與行內元素,預設20
586
- * @param {Integer} [opt.tolerancePixel=1] 輸入容許誤差整數,單位px,可給0表示任何變化皆發出,預設1
587
- * @param {Boolean} [opt.sync=false] 輸入是否於ResizeObserver回呼內同步發出事件布林值,true時使用端可於瀏覽器繪製前更新版面(例如圖表重繪),僅ResizeObserver模式有效,預設false
588
- * @param {Boolean} [opt.watchIdentity=false] 輸入元素可見時是否仍於DOM變動時重新取得元素布林值,f可能於舊元素仍可見時改回傳另一元素者給true,僅ResizeObserver模式有效,預設false
589
- * @returns {Object} 回傳物件,可使用on與clear函數,on可監聽resize與resizeWithWindow事件,clear為釋放監聽,可於任何時點呼叫(含元素尚未取得),並取消已排定之事件
590
- * @example
591
- * need test in browser
592
- *
593
- * //監聽dom
594
- * let de = domDetect(() => {
595
- * return document.querySelector('#id')
596
- * })
597
- * de.on('resize', (s) => {
598
- * console.log('resize', s)
599
- * })
600
- * de.on('resizeWithWindow', (s) => {
601
- * console.log('resizeWithWindow', s)
602
- * })
603
- *
604
- * //釋放監聽
605
- * de.clear()
606
- *
607
- */
608
- function domDetect(f, opt = {}) {
609
- let useObserver = typeof window !== 'undefined' &amp;&amp; !!window.ResizeObserver &amp;&amp; !!window.MutationObserver &amp;&amp; get(opt, 'mode', '') !== 'polling'
610
- if (useObserver) {
611
- return domDetectByObserver(f, opt)
612
- }
613
- return domDetectByPolling(f, opt)
614
- }
615
-
616
-
617
- export default domDetect
48
+ <pre class="prettyprint source linenums"><code>import get from 'lodash-es/get.js'
49
+ import ispint from './ispint.mjs'
50
+ import isp0int from './isp0int.mjs'
51
+ import evem from './evem.mjs'
52
+ import isfun from './isfun.mjs'
53
+
54
+
55
+ //2020年曾以IntersectionObserver與ResizeObserver實作(詳細請查git紀錄), 因實作缺陷致WTextSelect下拉選單不穩而改為輪詢:
56
+ //1.元素尺寸為0(隱藏或移出DOM)時仍發出resize, 使用端讀到高度0而算錯版面
57
+ //2.clear未防空值, 元素尚未取得即clear時拋錯, 且已建立之觀察器與已排定之事件未解除
58
+ //3.觀察器只綁首次取得之元素, 元素被換成新節點後即失去偵測
59
+
60
+ //現已恢復並用以ResizeObserver偵測尺寸, 並以共用MutationObserver於[元素取不到、不在頁面中或尺寸為0]時重新取得元素, 逐一對應上述缺陷; 無ResizeObserver或MutationObserver時退回輪詢
61
+
62
+
63
+ //waiting, 等待重新取得元素之偵測器; mo, 共用之MutationObserver, 僅於有偵測器等待時啟用
64
+ let waiting = new Set()
65
+ let mo = null
66
+
67
+
68
+ function waitAdd(fn) {
69
+ waiting.add(fn)
70
+ if (!mo) {
71
+ mo = new window.MutationObserver(() => {
72
+ for (let g of Array.from(waiting)) {
73
+ g()
74
+ }
75
+ })
76
+ mo.observe(document.documentElement, { childList: true, subtree: true })
77
+ }
78
+ }
79
+
80
+
81
+ function waitRemove(fn) {
82
+ waiting.delete(fn)
83
+ if (waiting.size === 0 &amp;&amp; mo) {
84
+ mo.disconnect()
85
+ mo = null
86
+ }
87
+ }
88
+
89
+
90
+ function getTimeInterval(opt) {
91
+ let timeInterval = get(opt, 'timeInterval', null)
92
+ if (!ispint(timeInterval)) {
93
+ timeInterval = 20
94
+ }
95
+ return timeInterval
96
+ }
97
+
98
+
99
+ function getTolerancePixel(opt) {
100
+ let tolerancePixel = get(opt, 'tolerancePixel', null)
101
+ if (!isp0int(tolerancePixel)) { //可給0, 表示任何變化皆發出
102
+ tolerancePixel = 1
103
+ }
104
+ return tolerancePixel
105
+ }
106
+
107
+
108
+ //getEle, f()拋錯或回傳非元素時視為取不到, 不中斷偵測
109
+ function getEle(f) {
110
+ let p = null
111
+ try {
112
+ p = f()
113
+ }
114
+ catch (err) {
115
+ p = null
116
+ }
117
+ return (p &amp;&amp; p.nodeType === 1) ? p : null
118
+ }
119
+
120
+
121
+ function sizeZero() {
122
+ return {
123
+ offsetWidth: 0,
124
+ offsetHeight: 0,
125
+ clientWidth: 0,
126
+ clientHeight: 0,
127
+ windowWidth: 0,
128
+ windowHeight: 0,
129
+ }
130
+ }
131
+
132
+
133
+ function measure(p) {
134
+ return {
135
+ offsetWidth: p.offsetWidth,
136
+ offsetHeight: p.offsetHeight,
137
+ clientWidth: p.clientWidth,
138
+ clientHeight: p.clientHeight,
139
+ windowWidth: window.innerWidth,
140
+ windowHeight: window.innerHeight,
141
+ }
142
+ }
143
+
144
+
145
+ //createCore, 輪詢與ResizeObserver兩種模式共用之比較、發出、視窗事件與清除, 使兩者之規則只寫一處
146
+ // 比較基準sb為上次發出事件時之尺寸, 差值超過容許誤差才更新; 若每次量測皆更新基準, 緩慢之連續小變化(如逐px拖曳或縮放視窗)永遠不會超過容許誤差, 累積再大也不發出
147
+ // 尺寸為0時差值必超過容許誤差而使基準歸0, 故由隱藏恢復顯示時必發出
148
+ function createCore(ev, opt) {
149
+
150
+ //tolerancePixel
151
+ let tolerancePixel = getTolerancePixel(opt)
152
+
153
+ //sync, 於ResizeObserver回呼內同步發出事件(繪製前), 供須於同一幀更新版面之使用端(例如圖表重繪); 預設以setTimeout脫勾
154
+ let sync = get(opt, 'sync', false) === true
155
+
156
+ //cleared, sd, sb, timers
157
+ let cleared = false
158
+ let sd = sizeZero() //最新量測
159
+ let sb = sizeZero() //比較基準, 上次發出事件時之尺寸
160
+ let timers = new Set()
161
+
162
+ //emit
163
+ let emit = (sold, snew, sm, p) => {
164
+
165
+ //cleared, clear後不再發出已排定之事件
166
+ if (cleared) {
167
+ return
168
+ }
169
+
170
+ //detect resize, 尺寸為0(隱藏或移出DOM)不發出
171
+ if (snew.offsetWidth > 0 &amp;&amp; snew.offsetHeight > 0) {
172
+ ev.emit('resize', {
173
+ sold,
174
+ snew,
175
+ smode: sm,
176
+ ele: p,
177
+ })
178
+
179
+ //cleared, resize之監聽器內可能呼叫clear
180
+ if (cleared) {
181
+ return
182
+ }
183
+
184
+ ev.emit('resizeWithWindow', {
185
+ sold,
186
+ snew,
187
+ smode: sm,
188
+ ele: p,
189
+ from: 'dom',
190
+ })
191
+ }
192
+
193
+ }
194
+
195
+ //check, 量測並與比較基準比較
196
+ let check = (p, allowSync) => {
197
+ if (cleared || !p) {
198
+ return
199
+ }
200
+
201
+ //new size
202
+ let snew = measure(p)
203
+
204
+ //dw, dh
205
+ let dw = sb.offsetWidth - snew.offsetWidth
206
+ let dh = sb.offsetHeight - snew.offsetHeight
207
+
208
+ //bw, bh
209
+ let bw = Math.abs(dw) > tolerancePixel
210
+ let bh = Math.abs(dh) > tolerancePixel
211
+
212
+ //save
213
+ sd = snew
214
+
215
+ //check
216
+ if (!bw &amp;&amp; !bh) {
217
+ return
218
+ }
219
+
220
+ //sold, sb
221
+ let sold = sb
222
+ sb = snew
223
+
224
+ //sm, 方向只於該軸超過容許誤差時給: 容許誤差內之差值視同未變化(不發事件), 若仍給方向, 另一軸觸發之事件會帶出該軸之殘餘方向
225
+ let sm = {
226
+ width: bw ? (dw > 0 ? 'smaller' : 'larger') : '',
227
+ height: bh ? (dh > 0 ? 'smaller' : 'larger') : '',
228
+ }
229
+
230
+ //emit
231
+ if (allowSync &amp;&amp; sync) {
232
+ emit(sold, snew, sm, p)
233
+ return
234
+ }
235
+ let t = setTimeout(() => { //emit觸發事件為同步, 用setTimeout脫勾
236
+ timers.delete(t)
237
+ emit(sold, snew, sm, p)
238
+ }, 1)
239
+ timers.add(t)
240
+
241
+ }
242
+
243
+ //fWindowResize, 視窗尺寸取當下值, 否則元素尺寸未變時會一直帶著上次量測時之視窗尺寸
244
+ // sold為比較基準, 與dom事件同義; 任何超過容許誤差之變化皆已立即更新比較基準, 故最新量測與比較基準之差必在容許誤差內, 方向恆為空
245
+ let fWindowResize = (e) => {
246
+ if (cleared) {
247
+ return
248
+ }
249
+ sd = {
250
+ ...sd,
251
+ windowWidth: window.innerWidth,
252
+ windowHeight: window.innerHeight,
253
+ }
254
+ ev.emit('resizeWithWindow', {
255
+ sold: sb,
256
+ snew: sd,
257
+ smode: {
258
+ width: '',
259
+ height: '',
260
+ },
261
+ from: 'window',
262
+ })
263
+ }
264
+ window.addEventListener('resize', fWindowResize)
265
+
266
+ //clear
267
+ let clear = () => {
268
+ cleared = true
269
+ for (let t of timers) {
270
+ clearTimeout(t)
271
+ }
272
+ timers.clear()
273
+ window.removeEventListener('resize', fWindowResize)
274
+ }
275
+
276
+ return {
277
+ check,
278
+ clear,
279
+ isCleared: () => cleared,
280
+ isVisible: () => sd.offsetWidth > 0 &amp;&amp; sd.offsetHeight > 0,
281
+ }
282
+ }
283
+
284
+
285
+ function domDetectByPolling(f, opt = {}) {
286
+
287
+ //check
288
+ if (!isfun(f)) {
289
+ console.log('invalid f', f)
290
+ return null
291
+ }
292
+
293
+ //ev, core
294
+ let ev = evem()
295
+ let core = createCore(ev, opt)
296
+
297
+ //setInterval
298
+ let timer = setInterval(() => {
299
+ let p = getEle(f)
300
+ if (p) {
301
+ core.check(p, false)
302
+ }
303
+ }, getTimeInterval(opt))
304
+
305
+ //clear
306
+ ev.clear = () => {
307
+ clearInterval(timer)
308
+ core.clear()
309
+ }
310
+
311
+ return ev
312
+ }
313
+
314
+
315
+ function domDetectByObserver(f, opt = {}) {
316
+
317
+ //check
318
+ if (!isfun(f)) {
319
+ console.log('invalid f', f)
320
+ return null
321
+ }
322
+
323
+ //watchIdentity, 元素可見時亦持續於DOM變動時重新取得元素, 供f()可能於舊元素仍可見時改回傳他元素之使用端
324
+ let watchIdentity = get(opt, 'watchIdentity', false) === true
325
+
326
+ //timeInterval, 行內元素改以定期量測時使用
327
+ let timeInterval = getTimeInterval(opt)
328
+
329
+ //ev, core
330
+ let ev = evem()
331
+ let core = createCore(ev, opt)
332
+
333
+ //ele, timerInline, inlineConn, eleInline, roBorder, roContent
334
+ let ele = null
335
+ let timerInline = null
336
+ let inlineConn = false //上次判定是否為行內時元素是否在頁面中
337
+ let eleInline = false //目前元素是否曾判定為行內, 換成新節點時歸零
338
+ let roBorder = null
339
+ let roContent = null
340
+
341
+ //syncInline, 非替換之行內元素ResizeObserver不回報(規範明定), 取得之元素為display:inline時改以定期量測, 不為inline時停止
342
+ // 元素自身隱藏(display:none, 如v-show)時看不出顯示後之型別: 曾判定為行內者持續定期量測, 否則顯示時ResizeObserver會回報; 不在頁面中時display為空字串, 停止量測, 待插入頁面時(onDomChange)重判
343
+ let syncInline = () => {
344
+ let display = ''
345
+ if (ele) {
346
+ try {
347
+ display = window.getComputedStyle(ele).display
348
+ }
349
+ catch (err) {
350
+ display = ''
351
+ }
352
+ }
353
+ inlineConn = !!(ele &amp;&amp; ele.isConnected)
354
+ if (display === 'inline') {
355
+ eleInline = true
356
+ }
357
+ else if (display !== 'none' &amp;&amp; display !== '') {
358
+ eleInline = false
359
+ }
360
+ let inline = display === 'inline' || (display === 'none' &amp;&amp; eleInline)
361
+ if (inline &amp;&amp; timerInline === null) {
362
+ timerInline = setInterval(onResize, timeInterval)
363
+ }
364
+ else if (!inline &amp;&amp; timerInline !== null) {
365
+ clearInterval(timerInline)
366
+ timerInline = null
367
+ }
368
+ }
369
+
370
+ //retarget, 重新取得元素: 換成新節點時改觀察新節點, 新節點之首次回報由check比較
371
+ // 同時觀察border-box與content-box: 比較用之offsetWidth即border-box, 只觀察content-box會漏掉只改padding或border之變化; content-box則使捲軸出現或消失時clientWidth保持最新
372
+ let retarget = () => {
373
+ if (core.isCleared()) {
374
+ return
375
+ }
376
+ let p = getEle(f)
377
+ if (p === ele) {
378
+ return
379
+ }
380
+ if (ele) {
381
+ roBorder.unobserve(ele)
382
+ roContent.unobserve(ele)
383
+ }
384
+ ele = p
385
+ eleInline = false
386
+ if (ele) {
387
+ roBorder.observe(ele, { box: 'border-box' })
388
+ roContent.observe(ele)
389
+ }
390
+ syncInline()
391
+ }
392
+
393
+ //updateWaiting, 元素取不到、不在頁面中或尺寸為0時登記等待DOM變動:
394
+ // 元素消失(移除或換新節點)時ResizeObserver無從得知新節點, 且已隱藏(尺寸0)之元素再被移除時尺寸0→0不會回報, 故尺寸為0時亦須等待
395
+ let updateWaiting = () => {
396
+ if (core.isCleared()) {
397
+ return
398
+ }
399
+ let visible = ele &amp;&amp; ele.isConnected &amp;&amp; core.isVisible()
400
+ if (visible &amp;&amp; !watchIdentity) {
401
+ waitRemove(onDomChange)
402
+ }
403
+ else {
404
+ waitAdd(onDomChange)
405
+ }
406
+ }
407
+
408
+ //onDomChange, 僅重新取得元素不量測, 避免強制重排版; 換新節點後由ResizeObserver之首次回報觸發check
409
+ // 元素插入或移出頁面時重判是否為行內: 不在頁面中之元素取不到display而判為非行內(如Vue指令之bind時元素尚未插入, 或行內元素移出後定期量測已停止), 行內元素ResizeObserver又不回報, 不於插入後重判則永不量測
410
+ // 僅於在頁面與否改變時重判, 等待中之其他DOM變動不重複讀取樣式
411
+ let onDomChange = () => {
412
+ retarget()
413
+ if (ele &amp;&amp; ele.isConnected !== inlineConn) {
414
+ syncInline()
415
+ }
416
+ updateWaiting()
417
+ }
418
+
419
+ //onResize
420
+ let onResize = () => {
421
+ retarget()
422
+ try {
423
+ core.check(ele, true)
424
+ }
425
+ finally {
426
+ //sync模式下監聽器拋錯時仍須更新行內與等待狀態
427
+ syncInline()
428
+ updateWaiting()
429
+ }
430
+ }
431
+
432
+ //roBorder, roContent
433
+ roBorder = new window.ResizeObserver(onResize)
434
+ roContent = new window.ResizeObserver(onResize)
435
+
436
+ //initialize
437
+ retarget()
438
+ updateWaiting()
439
+
440
+ //clear, 可於任何時點呼叫(含元素尚未取得), 並取消已排定之事件
441
+ ev.clear = () => {
442
+ if (core.isCleared()) {
443
+ return
444
+ }
445
+ core.clear()
446
+ waitRemove(onDomChange)
447
+ roBorder.disconnect()
448
+ roContent.disconnect()
449
+ if (timerInline !== null) {
450
+ clearInterval(timerInline)
451
+ timerInline = null
452
+ }
453
+ ele = null
454
+ }
455
+
456
+ return ev
457
+ }
458
+
459
+
460
+ /**
461
+ * 前端針對DOM元素監聽resize、resizeWithWindow事件,其中resizeWithWindow為dom resize與window resize皆會觸發的事件
462
+ *
463
+ * 瀏覽器支援ResizeObserver與MutationObserver時以其偵測(即時且閒置時不耗資源),否則退回定期輪詢,兩者之比較規則與事件相同:以offsetWidth、offsetHeight與比較基準之差超過容許誤差即發出,比較基準為上次發出事件時之尺寸,故緩慢之連續小變化累積超過容許誤差亦會發出;尺寸為0(隱藏或移出DOM)不發出,由隱藏恢復顯示時會發出,首次取得非0尺寸時會發出
464
+ *
465
+ * 元素可取不到、中途消失或重建為新節點:取不到、不在頁面中或尺寸為0時,於DOM變動時重新以f取得元素並改觀察之。行內元素(display:inline)ResizeObserver不回報,該偵測器改以定期量測,元素自身隱藏(display:none,如v-show)期間亦持續,顯示後即可量得;是否為行內於取得元素、ResizeObserver回報、定期量測及元素插入或移出頁面時判定
466
+ *
467
+ * 事件內容:sold為比較基準(上次發出事件時之尺寸),snew為本次量測,smode為寬與高相對比較基準之變化方向('larger'、'smaller'或''),僅該軸之差超過容許誤差時給方向,否則為'',ele為元素;from為'window'之事件無ele,其snew為最新量測,其中視窗尺寸取事件當下之值,其smode寬與高恆為''(視窗事件不代表元素尺寸變化,且最新量測與比較基準之差必在容許誤差內)
468
+ *
469
+ * 已知限制:ResizeObserver模式下,僅屬性變化(如class)使f改指他元素、或Shadow DOM內之節點被替換時不會跟隨,行內元素自取得起即自身為display:none(未曾以行內顯示過)、之後僅以style或class改為顯示者不會開始量測,此類使用端請用mode:'polling';sync為true時監聽器不得使所監聽元素之尺寸於同一幀內再變,否則瀏覽器回報ResizeObserver loop錯誤;Safari 15.4以前不支援觀察border-box,只改padding或border之變化於該處不會發出
470
+ *
471
+ * Unit Test: {@link https://github.com/yuda-lyu/wsemi/blob/master/test/domDetect.test.mjs Github}
472
+ * @memberOf wsemi
473
+ * @param {Function} f 輸入取得dom函數,可回傳null表示目前取不到
474
+ * @param {Object} [opt={}] 輸入設定物件,預設{}
475
+ * @param {String} [opt.mode=''] 輸入偵測模式字串,給'polling'則強制使用定期輪詢,預設''
476
+ * @param {Integer} [opt.timeInterval=20] 輸入定期偵測時間整數,單位毫秒,用於輪詢模式與行內元素,預設20
477
+ * @param {Integer} [opt.tolerancePixel=1] 輸入容許誤差整數,單位px,可給0表示任何變化皆發出,預設1
478
+ * @param {Boolean} [opt.sync=false] 輸入是否於ResizeObserver回呼內同步發出事件布林值,true時使用端可於瀏覽器繪製前更新版面(例如圖表重繪),僅ResizeObserver模式有效,預設false
479
+ * @param {Boolean} [opt.watchIdentity=false] 輸入元素可見時是否仍於DOM變動時重新取得元素布林值,f可能於舊元素仍可見時改回傳另一元素者給true,僅ResizeObserver模式有效,預設false
480
+ * @returns {Object} 回傳物件,可使用on與clear函數,on可監聽resize與resizeWithWindow事件,clear為釋放監聽,可於任何時點呼叫(含元素尚未取得),並取消已排定之事件
481
+ * @example
482
+ * need test in browser
483
+ *
484
+ * //監聽dom
485
+ * let de = domDetect(() => {
486
+ * return document.querySelector('#id')
487
+ * })
488
+ * de.on('resize', (s) => {
489
+ * console.log('resize', s)
490
+ * })
491
+ * de.on('resizeWithWindow', (s) => {
492
+ * console.log('resizeWithWindow', s)
493
+ * })
494
+ *
495
+ * //釋放監聽
496
+ * de.clear()
497
+ *
498
+ */
499
+ function domDetect(f, opt = {}) {
500
+ let useObserver = typeof window !== 'undefined' &amp;&amp; !!window.ResizeObserver &amp;&amp; !!window.MutationObserver &amp;&amp; get(opt, 'mode', '') !== 'polling'
501
+ if (useObserver) {
502
+ return domDetectByObserver(f, opt)
503
+ }
504
+ return domDetectByPolling(f, opt)
505
+ }
506
+
507
+
508
+ export default domDetect
618
509
  </code></pre>
619
510
  </article>
620
511
  </section>
@@ -629,7 +520,7 @@ export default domDetect
629
520
  <br class="clear">
630
521
 
631
522
  <footer>
632
- Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 4.0.5</a> on Fri Sep 25 2026 14:59:11 GMT+0800 (台北標準時間) using the <a href="https://github.com/clenemt/docdash">docdash</a> theme.
523
+ Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 4.0.5</a> on Sat Sep 26 2026 08:34:39 GMT+0800 (台北標準時間) using the <a href="https://github.com/clenemt/docdash">docdash</a> theme.
633
524
  </footer>
634
525
 
635
526
  <script>prettyPrint();</script>