wsemi 1.9.3 → 1.9.4

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 (489) hide show
  1. package/README.md +1 -1
  2. package/dist/wsemi.umd.js +5 -5
  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 +571 -304
  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 +218 -10
  484. package/package.json +1 -1
  485. package/src/domDetect.mjs +570 -303
  486. package/test/domDetect.test.mjs +684 -11
  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
@@ -1,11 +1,684 @@
1
- import assert from 'assert'
2
- //import domDetect from '../src/domDetect.mjs'
3
-
4
-
5
- describe(`domDetect`, function() {
6
-
7
- it(`need test in browser`, function() {
8
- assert.strict.deepStrictEqual(1, 1)
9
- })
10
-
11
- })
1
+ import assert from 'assert'
2
+ import domDetect from '../src/domDetect.mjs'
3
+
4
+
5
+ //本函數於瀏覽器執行, 以ResizeObserver、MutationObserver、window與document偵測元素尺寸, nodejs無此等物件, 故以假環境覆蓋全域
6
+ // 假ResizeObserver與假MutationObserver只記錄觀察對象, 由測試呼叫fireRO、fireMO觸發回呼, 可精確控制瀏覽器於何時回報
7
+ // 假元素之尺寸、是否在頁面中與display由測試直接設定
8
+ // 瀏覽器本身之語義(只觀察content-box時漏掉padding變化、行內元素不回報、開始觀察必回報一次、捲軸佔寬等)非本檔所能驗證, 已另以真瀏覽器實測
9
+
10
+
11
+ let sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms))
12
+
13
+
14
+ class Ele {
15
+ constructor(w, h, o = {}) {
16
+ this.nodeType = 1
17
+ this.display = o.display || 'block'
18
+ this.isConnected = o.connected !== false
19
+ this.size(w, h, o.cw, o.ch)
20
+ }
21
+
22
+ size(w, h, cw, ch) {
23
+ this.offsetWidth = w
24
+ this.offsetHeight = h
25
+ this.clientWidth = (cw !== undefined) ? cw : w
26
+ this.clientHeight = (ch !== undefined) ? ch : h
27
+ }
28
+ }
29
+
30
+
31
+ let envCur = null
32
+
33
+
34
+ //mkEnv, 建立假window與document並覆蓋全域
35
+ function mkEnv(o = {}) {
36
+ let env = {
37
+ ros: [],
38
+ mos: [],
39
+ listeners: [],
40
+ dds: [],
41
+ }
42
+
43
+ class RO {
44
+ constructor(cb) {
45
+ this.cb = cb
46
+ this.targets = new Map()
47
+ env.ros.push(this)
48
+ }
49
+
50
+ observe(t, opt) {
51
+ this.targets.set(t, (opt && opt.box) ? opt.box : 'content-box')
52
+ }
53
+
54
+ unobserve(t) {
55
+ this.targets.delete(t)
56
+ }
57
+
58
+ disconnect() {
59
+ this.targets.clear()
60
+ }
61
+ }
62
+
63
+ class MO {
64
+ constructor(cb) {
65
+ this.cb = cb
66
+ this.active = false
67
+ env.mos.push(this)
68
+ }
69
+
70
+ observe(t, opt) {
71
+ this.active = true
72
+ this.target = t
73
+ this.opt = opt
74
+ }
75
+
76
+ disconnect() {
77
+ this.active = false
78
+ }
79
+ }
80
+
81
+ env.window = {
82
+ innerWidth: 1200,
83
+ innerHeight: 800,
84
+ ResizeObserver: o.noRO ? undefined : RO,
85
+ MutationObserver: MO,
86
+ addEventListener: (type, fn) => {
87
+ env.listeners.push({ type, fn })
88
+ },
89
+ removeEventListener: (type, fn) => {
90
+ env.listeners = env.listeners.filter((l) => !(l.type === type && l.fn === fn))
91
+ },
92
+ getComputedStyle: (e) => {
93
+ return { display: e.display }
94
+ },
95
+ }
96
+ env.document = { documentElement: { name: 'html' } }
97
+ globalThis.window = env.window
98
+ globalThis.document = env.document
99
+
100
+ //fireRO, 瀏覽器回報ele之尺寸變化; box不給時兩種盒皆回報, 給定時只回報觀察該盒者
101
+ env.fireRO = (ele, box) => {
102
+ for (let ro of env.ros) {
103
+ let b = ro.targets.get(ele)
104
+ if (b !== undefined && (box === undefined || b === box)) {
105
+ ro.cb([{ target: ele }], ro)
106
+ }
107
+ }
108
+ }
109
+
110
+ //fireMO, DOM變動
111
+ env.fireMO = () => {
112
+ for (let m of env.mos) {
113
+ if (m.active) {
114
+ m.cb([], m)
115
+ }
116
+ }
117
+ }
118
+
119
+ //resizeWindow
120
+ env.resizeWindow = (w, h) => {
121
+ env.window.innerWidth = w
122
+ env.window.innerHeight = h
123
+ for (let l of env.listeners.slice()) {
124
+ if (l.type === 'resize') {
125
+ l.fn({ type: 'resize' })
126
+ }
127
+ }
128
+ }
129
+
130
+ env.moActive = () => env.mos.filter((m) => m.active).length
131
+ env.observed = (ele) => env.ros.map((ro) => ro.targets.get(ele)).filter((b) => b !== undefined).sort()
132
+ env.nRoTargets = () => env.ros.reduce((n, ro) => n + ro.targets.size, 0)
133
+
134
+ //dd, 建立偵測器並記錄事件; 測試結束時統一clear, 避免模組共用之MutationObserver跨測試殘留
135
+ env.dd = (f, opt) => {
136
+ let d = domDetect(f, opt)
137
+ let rec = {
138
+ d,
139
+ resize: [],
140
+ rww: [],
141
+ }
142
+ if (d) {
143
+ d.on('resize', (m) => rec.resize.push(m))
144
+ d.on('resizeWithWindow', (m) => rec.rww.push(m))
145
+ env.dds.push(d)
146
+ }
147
+ return rec
148
+ }
149
+
150
+ envCur = env
151
+ return env
152
+ }
153
+
154
+
155
+ //ws, 各resize事件之寬
156
+ function ws(rec) {
157
+ return rec.resize.map((m) => m.snew.offsetWidth)
158
+ }
159
+
160
+
161
+ describe(`domDetect`, function() {
162
+
163
+ afterEach(function() {
164
+ if (envCur) {
165
+ for (let d of envCur.dds) {
166
+ d.clear()
167
+ }
168
+ envCur = null
169
+ }
170
+ })
171
+
172
+ after(function() {
173
+ delete globalThis.window
174
+ delete globalThis.document
175
+ })
176
+
177
+ //--- 首次與事件內容 ---
178
+
179
+ it(`should emit resize and resizeWithWindow once the element is first measured`, async function() {
180
+ //D9 首次取得非0尺寸時發出, sold為0
181
+ let env = mkEnv()
182
+ let el = new Ele(300, 40, { cw: 290, ch: 30 })
183
+ let r = env.dd(() => el)
184
+ env.fireRO(el)
185
+ await sleep(10)
186
+ let snew = { offsetWidth: 300, offsetHeight: 40, clientWidth: 290, clientHeight: 30, windowWidth: 1200, windowHeight: 800 }
187
+ let sold = { offsetWidth: 0, offsetHeight: 0, clientWidth: 0, clientHeight: 0, windowWidth: 0, windowHeight: 0 }
188
+ let smode = { width: 'larger', height: 'larger' }
189
+ assert.strict.deepStrictEqual(r.resize, [{ sold, snew, smode, ele: el }])
190
+ assert.strict.deepStrictEqual(r.rww, [{ sold, snew, smode, ele: el, from: 'dom' }])
191
+ })
192
+
193
+ it(`should observe both the border box and the content box`, function() {
194
+ //F1 比較用之offsetWidth即border-box; content-box則負責捲軸出現或消失
195
+ let env = mkEnv()
196
+ let el = new Ele(300, 40)
197
+ env.dd(() => el)
198
+ assert.strict.deepStrictEqual(env.observed(el), ['border-box', 'content-box'])
199
+ })
200
+
201
+ it(`should emit when only the border box changes, such as padding or border`, async function() {
202
+ //F1、G1 只改padding或border時content-box不變, 須靠border-box之回報
203
+ let env = mkEnv()
204
+ let el = new Ele(300, 40)
205
+ let r = env.dd(() => el)
206
+ env.fireRO(el)
207
+ el.size(340, 40, 340, 40)
208
+ env.fireRO(el, 'border-box')
209
+ await sleep(10)
210
+ assert.strict.deepStrictEqual(ws(r), [300, 340])
211
+ })
212
+
213
+ it(`should keep clientWidth fresh when only the content box changes, such as a scrollbar`, async function() {
214
+ //F1、G8 捲軸出現時offsetWidth不變而clientWidth變小, 不發出dom事件, 但之後視窗事件須帶最新之clientWidth
215
+ let env = mkEnv()
216
+ let el = new Ele(300, 100)
217
+ let r = env.dd(() => el)
218
+ env.fireRO(el)
219
+ await sleep(10)
220
+ el.size(300, 100, 285, 100)
221
+ env.fireRO(el, 'content-box')
222
+ await sleep(10)
223
+ env.resizeWindow(1000, 800)
224
+ assert.strict.deepStrictEqual(ws(r), [300])
225
+ let last = r.rww[r.rww.length - 1]
226
+ assert.strict.deepStrictEqual([last.from, last.snew.clientWidth, last.snew.offsetWidth], ['window', 285, 300])
227
+ })
228
+
229
+ //--- 比較規則 ---
230
+
231
+ it(`should not emit a zero size, and emit again when shown at the same size`, async function() {
232
+ //D1、D5 尺寸為0不發出; 由隱藏恢復顯示時即使尺寸相同亦發出
233
+ let env = mkEnv()
234
+ let el = new Ele(300, 40)
235
+ let r = env.dd(() => el)
236
+ env.fireRO(el)
237
+ el.size(0, 0)
238
+ env.fireRO(el)
239
+ el.size(300, 40)
240
+ env.fireRO(el)
241
+ await sleep(10)
242
+ assert.strict.deepStrictEqual(ws(r), [300, 300])
243
+ assert.strict.deepStrictEqual(r.resize[1].sold.offsetWidth, 0)
244
+ })
245
+
246
+ it(`should emit when small changes accumulate beyond the tolerance`, async function() {
247
+ //F2、G3 比較基準為上次發出之尺寸: 每次+1px不超過容許誤差1, 累積至2px即發出, sold與smode皆相對於基準
248
+ let env = mkEnv()
249
+ let el = new Ele(300, 40)
250
+ let r = env.dd(() => el)
251
+ for (let w of [300, 301, 302, 303, 304, 303, 302]) {
252
+ el.size(w, 40)
253
+ env.fireRO(el)
254
+ }
255
+ await sleep(10)
256
+ assert.strict.deepStrictEqual(ws(r), [300, 302, 304, 302])
257
+ assert.strict.deepStrictEqual(r.resize.map((m) => m.sold.offsetWidth), [0, 300, 302, 304])
258
+ assert.strict.deepStrictEqual(r.resize.map((m) => m.smode.width), ['larger', 'larger', 'larger', 'smaller'])
259
+ })
260
+
261
+ it(`should emit every change when tolerancePixel is 0`, async function() {
262
+ //缺陷B 原以ispint驗證故0被改回1
263
+ let env = mkEnv()
264
+ let el = new Ele(300, 40)
265
+ let r = env.dd(() => el, { tolerancePixel: 0 })
266
+ for (let w of [300, 301, 303]) {
267
+ el.size(w, 40)
268
+ env.fireRO(el)
269
+ }
270
+ await sleep(10)
271
+ assert.strict.deepStrictEqual(ws(r), [300, 301, 303])
272
+ })
273
+
274
+ it(`should fall back to a tolerance of one for an invalid tolerancePixel`, async function() {
275
+ for (let tol of [-1, 'x', 1.5, null]) {
276
+ let env = mkEnv()
277
+ let el = new Ele(300, 40)
278
+ let r = env.dd(() => el, { tolerancePixel: tol })
279
+ for (let w of [300, 301, 303]) {
280
+ el.size(w, 40)
281
+ env.fireRO(el)
282
+ }
283
+ await sleep(10)
284
+ assert.strict.deepStrictEqual(ws(r), [300, 303], String(tol))
285
+ for (let d of env.dds) {
286
+ d.clear()
287
+ }
288
+ }
289
+ })
290
+
291
+ it(`should compare the height as well as the width`, async function() {
292
+ let env = mkEnv()
293
+ let el = new Ele(300, 40)
294
+ let r = env.dd(() => el)
295
+ env.fireRO(el)
296
+ el.size(300, 60)
297
+ env.fireRO(el)
298
+ await sleep(10)
299
+ assert.strict.deepStrictEqual(r.resize.map((m) => [m.snew.offsetHeight, m.smode.width, m.smode.height]), [[40, 'larger', 'larger'], [60, '', 'larger']])
300
+ })
301
+
302
+ //--- 發出時點與清除 ---
303
+
304
+ it(`should emit asynchronously by default and synchronously with sync`, async function() {
305
+ //D14 sync時於ResizeObserver回呼內同步發出, 供須於繪製前更新版面之使用端
306
+ let env = mkEnv()
307
+ let el1 = new Ele(300, 40)
308
+ let el2 = new Ele(300, 40)
309
+ let r1 = env.dd(() => el1)
310
+ let r2 = env.dd(() => el2, { sync: true })
311
+ env.fireRO(el1)
312
+ env.fireRO(el2)
313
+ let n = [r1.resize.length, r2.resize.length]
314
+ await sleep(10)
315
+ assert.strict.deepStrictEqual(n, [0, 1])
316
+ assert.strict.deepStrictEqual([r1.resize.length, r2.resize.length], [1, 1])
317
+ })
318
+
319
+ it(`should not emit scheduled events after clear`, async function() {
320
+ //缺陷A 已排定之事件於clear後不得發出; 兩種模式共用同一段發出與清除
321
+ let env = mkEnv()
322
+ let el = new Ele(300, 40)
323
+ let r = env.dd(() => el)
324
+ env.fireRO(el)
325
+ r.d.clear()
326
+ await sleep(10)
327
+ assert.strict.deepStrictEqual([r.resize.length, r.rww.length], [0, 0])
328
+ })
329
+
330
+ it(`should clear at any time, even before the element exists, and release everything`, async function() {
331
+ //D2 元素尚未取得即clear不得拋錯, 且觀察器、共用MutationObserver與視窗監聽全數解除; 重複clear無害
332
+ let env = mkEnv()
333
+ let el = null
334
+ let r = env.dd(() => el)
335
+ assert.strict.deepStrictEqual(env.moActive(), 1)
336
+ assert.doesNotThrow(() => {
337
+ r.d.clear()
338
+ r.d.clear()
339
+ })
340
+ el = new Ele(300, 40)
341
+ env.fireMO()
342
+ env.fireRO(el)
343
+ await sleep(10)
344
+ assert.strict.deepStrictEqual([env.moActive(), env.nRoTargets(), env.listeners.length, r.resize.length], [0, 0, 0, 0])
345
+ })
346
+
347
+ it(`should release the observers, the shared MutationObserver and the window listener on clear`, async function() {
348
+ //已觀察元素後clear, 兩個ResizeObserver皆解除
349
+ let env = mkEnv()
350
+ let el = new Ele(0, 0)
351
+ let r = env.dd(() => el)
352
+ env.fireRO(el)
353
+ assert.strict.deepStrictEqual([env.nRoTargets(), env.moActive(), env.listeners.length], [2, 1, 1])
354
+ r.d.clear()
355
+ el.size(300, 40)
356
+ env.fireRO(el)
357
+ await sleep(10)
358
+ assert.strict.deepStrictEqual([env.nRoTargets(), env.moActive(), env.listeners.length, r.resize.length], [0, 0, 0, 0])
359
+ })
360
+
361
+ it(`should not emit resizeWithWindow when a resize listener clears`, async function() {
362
+ //clear後不再發出任何事件, 含同一次發出之第二個事件
363
+ let env = mkEnv()
364
+ let el = new Ele(300, 40)
365
+ let r = env.dd(() => el)
366
+ r.d.on('resize', () => {
367
+ r.d.clear()
368
+ })
369
+ env.fireRO(el)
370
+ await sleep(10)
371
+ assert.strict.deepStrictEqual([r.resize.length, r.rww.length], [1, 0])
372
+ })
373
+
374
+ it(`should stop window events after clear`, function() {
375
+ let env = mkEnv()
376
+ let el = new Ele(300, 40)
377
+ let r = env.dd(() => el)
378
+ env.resizeWindow(1000, 800)
379
+ r.d.clear()
380
+ env.resizeWindow(900, 800)
381
+ assert.strict.deepStrictEqual(r.rww.map((m) => m.snew.windowWidth), [1000])
382
+ })
383
+
384
+ //--- 元素之取得與替換 ---
385
+
386
+ it(`should pick up an element that appears later`, async function() {
387
+ //D3 起初取不到, 登記等待; DOM變動時取得並觀察, 量測後不再等待
388
+ let env = mkEnv()
389
+ let el = null
390
+ let r = env.dd(() => el)
391
+ assert.strict.deepStrictEqual(env.moActive(), 1)
392
+ el = new Ele(250, 40)
393
+ env.fireMO()
394
+ assert.strict.deepStrictEqual(env.observed(el), ['border-box', 'content-box'])
395
+ assert.strict.deepStrictEqual(env.moActive(), 1)
396
+ env.fireRO(el)
397
+ assert.strict.deepStrictEqual(env.moActive(), 0)
398
+ el.size(350, 40)
399
+ env.fireRO(el)
400
+ await sleep(10)
401
+ assert.strict.deepStrictEqual(ws(r), [250, 350])
402
+ })
403
+
404
+ it(`should follow a replacement node`, async function() {
405
+ //D4 舊節點移出(ResizeObserver回報其尺寸變0)時重新取得元素, 改觀察新節點
406
+ let env = mkEnv()
407
+ let a = new Ele(200, 40)
408
+ let cur = a
409
+ let r = env.dd(() => cur)
410
+ env.fireRO(a)
411
+ let b = new Ele(320, 40)
412
+ cur = b
413
+ a.isConnected = false
414
+ a.size(0, 0)
415
+ env.fireRO(a)
416
+ assert.strict.deepStrictEqual([env.observed(a), env.observed(b)], [[], ['border-box', 'content-box']])
417
+ b.size(400, 40)
418
+ env.fireRO(b)
419
+ await sleep(10)
420
+ assert.strict.deepStrictEqual(ws(r), [200, 320, 400])
421
+ })
422
+
423
+ it(`should follow a node that is hidden, removed and replaced while hidden`, async function() {
424
+ //D11 已隱藏之元素再被移除時尺寸0→0不會回報, 故尺寸為0時亦須等待DOM變動
425
+ let env = mkEnv()
426
+ let a = new Ele(200, 40)
427
+ let cur = a
428
+ let r = env.dd(() => cur)
429
+ env.fireRO(a)
430
+ assert.strict.deepStrictEqual(env.moActive(), 0)
431
+ a.size(0, 0)
432
+ env.fireRO(a)
433
+ assert.strict.deepStrictEqual(env.moActive(), 1)
434
+ a.isConnected = false
435
+ let b = new Ele(0, 0)
436
+ cur = b
437
+ env.fireMO()
438
+ env.fireRO(b)
439
+ b.size(280, 40)
440
+ env.fireRO(b)
441
+ b.size(330, 40)
442
+ env.fireRO(b)
443
+ await sleep(10)
444
+ assert.strict.deepStrictEqual(ws(r), [200, 280, 330])
445
+ assert.strict.deepStrictEqual(env.moActive(), 0)
446
+ })
447
+
448
+ it(`should keep waiting after picking a new element until it is measured visible`, function() {
449
+ //等待中經DOM變動取得新節點, 須待新節點量測為可見才退出等待
450
+ let env = mkEnv()
451
+ let a = new Ele(0, 0)
452
+ let cur = a
453
+ env.dd(() => cur)
454
+ env.fireRO(a)
455
+ assert.strict.deepStrictEqual(env.moActive(), 1)
456
+ cur = new Ele(300, 40)
457
+ env.fireMO()
458
+ assert.strict.deepStrictEqual(env.moActive(), 1)
459
+ env.fireRO(cur)
460
+ assert.strict.deepStrictEqual(env.moActive(), 0)
461
+ })
462
+
463
+ it(`should not follow a new element while the old one stays visible, unless watchIdentity`, async function() {
464
+ //D12 預設於元素可見時不監看DOM變動; watchIdentity時持續監看
465
+ for (let watchIdentity of [false, true]) {
466
+ let env = mkEnv()
467
+ let a = new Ele(200, 40)
468
+ let cur = a
469
+ let r = env.dd(() => cur, { watchIdentity })
470
+ env.fireRO(a)
471
+ let b = new Ele(320, 40)
472
+ cur = b
473
+ env.fireMO()
474
+ env.fireRO(b)
475
+ await sleep(10)
476
+ assert.strict.deepStrictEqual([ws(r), env.moActive()], watchIdentity ? [[200, 320], 1] : [[200], 0], String(watchIdentity))
477
+ for (let d of env.dds) {
478
+ d.clear()
479
+ }
480
+ }
481
+ })
482
+
483
+ it(`should treat a throwing f or a non element as not found`, async function() {
484
+ //F5 f拋錯或回傳非元素時視為取不到, 不中斷偵測
485
+ let env = mkEnv()
486
+ let mode = 'throw'
487
+ let el = new Ele(300, 40)
488
+ let f = () => {
489
+ if (mode === 'throw') {
490
+ throw new Error('f boom')
491
+ }
492
+ if (mode === 'obj') {
493
+ return { offsetWidth: 300, offsetHeight: 40 }
494
+ }
495
+ return el
496
+ }
497
+ let r = null
498
+ assert.doesNotThrow(() => {
499
+ r = env.dd(f)
500
+ })
501
+ mode = 'obj'
502
+ env.fireMO()
503
+ assert.strict.deepStrictEqual(env.nRoTargets(), 0)
504
+ mode = 'ele'
505
+ env.fireMO()
506
+ env.fireRO(el)
507
+ await sleep(10)
508
+ assert.strict.deepStrictEqual(ws(r), [300])
509
+ })
510
+
511
+ //--- 行內元素、視窗與共用觀察器 ---
512
+
513
+ it(`should measure an inline element periodically, and stop once it is no longer inline`, async function() {
514
+ //F4 非替換之行內元素ResizeObserver不回報, 改以定期量測
515
+ let env = mkEnv()
516
+ let el = new Ele(27, 18, { display: 'inline' })
517
+ let r = env.dd(() => el, { timeInterval: 5 })
518
+ await sleep(30)
519
+ el.size(137, 18)
520
+ await sleep(30)
521
+ el.display = 'block'
522
+ env.fireRO(el)
523
+ let n = r.resize.length
524
+ el.size(200, 18)
525
+ await sleep(30)
526
+ let nStopped = r.resize.length
527
+ env.fireRO(el)
528
+ await sleep(10)
529
+ assert.strict.deepStrictEqual(ws(r), [27, 137, 200])
530
+ assert.strict.deepStrictEqual([n, nStopped], [2, 2])
531
+ })
532
+
533
+ it(`should carry the current window size in resizeWithWindow from the window`, async function() {
534
+ //F3、G4 元素尺寸未變時, 視窗事件之視窗尺寸仍須為當下之值
535
+ let env = mkEnv()
536
+ let el = new Ele(200, 40)
537
+ let r = env.dd(() => el)
538
+ env.fireRO(el)
539
+ await sleep(10)
540
+ env.resizeWindow(1000, 700)
541
+ env.resizeWindow(600, 500)
542
+ let ev = r.rww.filter((m) => m.from === 'window')
543
+ assert.strict.deepStrictEqual(ev.map((m) => [m.snew.windowWidth, m.snew.windowHeight, m.snew.offsetWidth]), [[1000, 700, 200], [600, 500, 200]])
544
+ assert.strict.deepStrictEqual(ev.map((m) => 'ele' in m), [false, false])
545
+ assert.strict.deepStrictEqual(ws(r), [200])
546
+ })
547
+
548
+ it(`should share one MutationObserver among waiting detectors`, function() {
549
+ //D2、D8 共用MutationObserver僅於有偵測器等待時啟用, 最後一個退出等待時解除
550
+ let env = mkEnv()
551
+ let r1 = env.dd(() => null)
552
+ let r2 = env.dd(() => null)
553
+ assert.strict.deepStrictEqual([env.mos.length, env.moActive()], [1, 1])
554
+ assert.strict.deepStrictEqual(env.mos[0].target, env.document.documentElement)
555
+ assert.strict.deepStrictEqual(env.mos[0].opt, { childList: true, subtree: true })
556
+ r1.d.clear()
557
+ assert.strict.deepStrictEqual(env.moActive(), 1)
558
+ r2.d.clear()
559
+ assert.strict.deepStrictEqual(env.moActive(), 0)
560
+ })
561
+
562
+ it(`should update the waiting state even when a sync listener throws`, function() {
563
+ //G9 sync時監聽器之拋錯會外拋至ResizeObserver回呼, 等待狀態仍須更新
564
+ let env = mkEnv()
565
+ let el = new Ele(0, 0)
566
+ let r = env.dd(() => el, { sync: true })
567
+ r.d.on('resize', () => {
568
+ throw new Error('consumer boom')
569
+ })
570
+ env.fireRO(el)
571
+ assert.strict.deepStrictEqual(env.moActive(), 1)
572
+ el.size(300, 40)
573
+ assert.throws(() => env.fireRO(el), /consumer boom/)
574
+ assert.strict.deepStrictEqual([ws(r), env.moActive()], [[300], 0])
575
+ })
576
+
577
+ //--- 輪詢模式 ---
578
+
579
+ it(`should use polling when mode is polling or ResizeObserver is missing`, async function() {
580
+ for (let [o, opt] of [[{}, { mode: 'polling', timeInterval: 5 }], [{ noRO: true }, { timeInterval: 5 }]]) {
581
+ let env = mkEnv(o)
582
+ let el = new Ele(300, 40)
583
+ let r = env.dd(() => el, opt)
584
+ await sleep(30)
585
+ assert.strict.deepStrictEqual([ws(r), env.ros.length, env.mos.length], [[300], 0, 0], JSON.stringify(o))
586
+ for (let d of env.dds) {
587
+ d.clear()
588
+ }
589
+ }
590
+ })
591
+
592
+ it(`should apply the same rules in polling mode`, async function() {
593
+ //輪詢與ResizeObserver共用比較、發出、視窗事件與清除: 累積超過容許誤差即發出、尺寸0不發出、恢復顯示再發出、視窗尺寸取當下值
594
+ let env = mkEnv()
595
+ let el = new Ele(300, 40)
596
+ let r = env.dd(() => el, { mode: 'polling', timeInterval: 5 })
597
+ for (let w of [300, 301, 302, 0, 302]) {
598
+ el.size(w, w === 0 ? 0 : 40)
599
+ await sleep(25)
600
+ }
601
+ env.resizeWindow(900, 600)
602
+ r.d.clear()
603
+ el.size(400, 40)
604
+ await sleep(25)
605
+ assert.strict.deepStrictEqual(ws(r), [300, 302, 302])
606
+ assert.strict.deepStrictEqual(r.rww.filter((m) => m.from === 'window').map((m) => m.snew.windowWidth), [900])
607
+ assert.strict.deepStrictEqual(env.listeners.length, 0)
608
+ })
609
+
610
+ it(`should treat a throwing f as not found in polling mode`, async function() {
611
+ //F5 與ResizeObserver模式一致, 不因f拋錯而於每次輪詢拋出
612
+ let env = mkEnv()
613
+ let ok = false
614
+ let el = new Ele(300, 40)
615
+ let r = env.dd(() => {
616
+ if (!ok) {
617
+ throw new Error('f boom')
618
+ }
619
+ return el
620
+ }, { mode: 'polling', timeInterval: 5 })
621
+ await sleep(25)
622
+ ok = true
623
+ await sleep(25)
624
+ assert.strict.deepStrictEqual(ws(r), [300])
625
+ })
626
+
627
+ it(`should return null for an invalid f`, function() {
628
+ let log = console.log
629
+ console.log = () => {}
630
+ try {
631
+ for (let o of [{}, { mode: 'polling' }]) {
632
+ let env = mkEnv()
633
+ let d = domDetect('x', o)
634
+ assert.strict.deepStrictEqual([d, env.listeners.length, env.ros.length], [null, 0, 0], JSON.stringify(o))
635
+ }
636
+ }
637
+ finally {
638
+ console.log = log
639
+ }
640
+ })
641
+
642
+ //--- 不變式 ---
643
+
644
+ it(`should never emit a zero size, and end within the tolerance of the actual size`, async function() {
645
+ //以固定種子之亂數產生尺寸變化序列(含0與小幅變化), 每次變化後瀏覽器皆回報, 須滿足:
646
+ // (1) 不發出尺寸為0之事件 (2) 靜止時最後一次發出之尺寸與實際尺寸之差不超過容許誤差
647
+ let seed = 20260925
648
+ let rnd = () => {
649
+ seed = (seed + 0x6D2B79F5) | 0
650
+ let v = Math.imul(seed ^ (seed >>> 15), 1 | seed)
651
+ v = (v + Math.imul(v ^ (v >>> 7), 61 | v)) ^ v
652
+ return ((v ^ (v >>> 14)) >>> 0) / 4294967296
653
+ }
654
+ for (let k = 0; k < 200; k++) {
655
+ let env = mkEnv()
656
+ let tol = k % 3
657
+ let el = new Ele(300, 40)
658
+ let r = env.dd(() => el, { tolerancePixel: tol, sync: true })
659
+ let w = 300
660
+ let h = 40
661
+ for (let i = 0; i < 30; i++) {
662
+ let x = rnd()
663
+ if (x < 0.1) {
664
+ el.size(0, 0)
665
+ }
666
+ else {
667
+ w = Math.max(1, w + Math.floor(rnd() * 7) - 3)
668
+ h = Math.max(1, h + Math.floor(rnd() * 3) - 1)
669
+ el.size(w, h)
670
+ }
671
+ env.fireRO(el)
672
+ }
673
+ el.size(w, h)
674
+ env.fireRO(el)
675
+ assert.strict.deepStrictEqual(r.resize.filter((m) => !(m.snew.offsetWidth > 0 && m.snew.offsetHeight > 0)).length, 0, `run=${k}`)
676
+ let last = r.resize[r.resize.length - 1]
677
+ assert.ok(Math.abs(last.snew.offsetWidth - w) <= tol && Math.abs(last.snew.offsetHeight - h) <= tol, `run=${k} last=${last.snew.offsetWidth}x${last.snew.offsetHeight} real=${w}x${h}`)
678
+ for (let d of env.dds) {
679
+ d.clear()
680
+ }
681
+ }
682
+ })
683
+
684
+ })
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * wsemip v1.9.3
2
+ * wsemip v1.9.4
3
3
  * (c) 2018-2021 yuda-lyu(semisphere)
4
4
  * Released under the MIT License.
5
5
  */