// ==UserScript== // @name JHS-enhance // @namespace JHS-enhance // @version 3.3.16 // @author xiebro,fireinrain // @description Jav-鉴黄师 增强脚本。列表页:作品状态标签、一键筛选、新作品检测、演员黑名单过滤;详情页:磁力链接高亮、DMM 多画质预览视频、标题翻译、整合字幕搜索(迅雷+SubTitleCat)并支持 115 直传、多源预览图(javfree/projectjav/javstore)含来源切换;数据:115 网盘目录匹配与多目录选择、云盘备份/恢复、跨 Tab 同步;其他:自动翻页、分类折叠、Top250、以图识图、热门榜单、评论查看、相关清单。支持 JavDB / JavBus / JavSee / SeeJav / FC2 / JavTrailers // @license MIT // @icon https://www.google.com/s2/favicons?sz=64&domain=javdb.com // @include https://javdb*.com/* // @include https://*javbus*/* // @include https://*javsee*/* // @include https://*seejav*/* // @include https://javtrailers.com/* // @include https://subtitlecat.com/* // @include https://www.aliyundrive.com/* // @include https://www.alipan.com/* // @include https://115.com/* // @match https://javdb.com/* // @match https://www.javbus.com/* // @exclude https://*javbus*/forum/* // @exclude https://*javbus*/*actresses // @exclude https://*javsee*/forum/* // @exclude https://*javsee*/*actresses // @exclude https://*seejav*/forum/* // @exclude https://*seejav*/*actresses // @require https://cdn.jsdelivr.net/npm/jquery@3.7.1/dist/jquery.min.js // @require https://cdn.jsdelivr.net/npm/layui-layer@1.0.9/dist/layer.min.js // @require https://cdn.jsdelivr.net/npm/blueimp-md5@2.19.0/js/md5.min.js // @require https://cdn.jsdelivr.net/npm/toastify-js@1.12.0/src/toastify.min.js // @require https://cdn.jsdelivr.net/npm/localforage@1.10.0/dist/localforage.min.js // @require https://cdn.jsdelivr.net/npm/viewerjs@1.11.1/dist/viewer.min.js // @require https://cdn.jsdelivr.net/npm/qrcodejs@1.0.0/qrcode.min.js // @require https://cdn.jsdelivr.net/npm/systemjs@6.15.1/dist/system.min.js // @require https://cdn.jsdelivr.net/npm/systemjs@6.15.1/dist/extras/named-register.min.js // @require data:application/javascript,%3B(typeof%20System!%3D'undefined')%26%26(System%3Dnew%20System.constructor())%3B // @connect xunlei.com // @connect geilijiasu.com // @connect aliyundrive.com // @connect aliyundrive.net // @connect ja.wikipedia.org // @connect beta.magnet.pics // @connect jdforrepam.com // @connect cc3001.dmm.co.jp // @connect cc3001.dmm.com // @connect www.dmm.co.jp // @connect www.dmm.com // @connect api.dmm.com // @connect special.dmm.co.jp // @connect adult.contents.fc2.com // @connect fc2ppvdb.com // @connect 123av.com // @connect u3c3.com // @connect u9a9.com // @connect btsow.lol // @connect sukebei.nyaa.si // @connect javstore.net // @connect javbest.net // @connect missav.live // @connect jable.tv // @connect www.av.gl // @connect jav.rs // @connect javtrailers.com // @connect javdb.com // @connect javbus.com // @connect supjav.com // @connect 115.com // @connect jianguoyun.com // @connect 127.0.0.1 // @connect * // @grant GM_addStyle // @grant GM_info // @grant GM_openInTab // @grant GM_xmlhttpRequest // @grant unsafeWindow // @grant window.close // @run-at document-idle // ==/UserScript== (a => { if (typeof GM_addStyle == "function") { GM_addStyle(a); return } const A = document.createElement("style"); A.textContent = a, document.head.append(A) })(" html #layuicss-skinlayercss{display:none;position:absolute;width:1989px}.layui-layer-shade,.layui-layer{position:fixed;_position:absolute;pointer-events:auto}.layui-layer-shade{top:0;left:0;width:100%;height:100%}.layui-layer{-webkit-overflow-scrolling:touch}.layui-layer{top:150px;left:0;margin:0;padding:0;background-color:#fff;-webkit-background-clip:content;box-shadow:1px 1px 50px #0000004d}.layui-layer-close{position:absolute}.layui-layer-content{position:relative}.layui-layer-border{border:1px solid #B2B2B2;border:1px solid rgba(0,0,0,.1);box-shadow:1px 1px 5px #0003}.layui-layer-load{background:url(data:image/gif;base64,R0lGODlhJQAlAJECAL3L2AYrTv///wAAACH/C05FVFNDQVBFMi4wAwEAAAAh+QQFCgACACwAAAAAJQAlAAACi5SPqcvtDyGYIFpF690i8xUw3qJBwUlSadmcLqYmGQu6KDIeM13beGzYWWy3DlB4IYaMk+Dso2RWkFCfLPcRvFbZxFLUDTt21BW56TyjRep1e20+i+eYMR145W2eefj+6VFmgTQi+ECVY8iGxcg35phGo/iDFwlTyXWphwlm1imGRdcnuqhHeop6UAAAIfkEBQoAAgAsEAACAAQACwAAAgWMj6nLXAAh+QQFCgACACwVAAUACgALAAACFZQvgRi92dyJcVJlLobUdi8x4bIhBQAh+QQFCgACACwXABEADAADAAACBYyPqcsFACH5BAUKAAIALBUAFQAKAAsAAAITlGKZwWoMHYxqtmplxlNT7ixGAQAh+QQFCgACACwQABgABAALAAACBYyPqctcACH5BAUKAAIALAUAFQAKAAsAAAIVlC+BGL3Z3IlxUmUuhtR2LzHhsiEFACH5BAUKAAIALAEAEQAMAAMAAAIFjI+pywUAIfkEBQoAAgAsBQAFAAoACwAAAhOUYJnAagwdjGq2amXGU1PuLEYBACH5BAUKAAIALBAAAgAEAAsAAAIFhI+py1wAIfkEBQoAAgAsFQAFAAoACwAAAhWUL4AIvdnciXFSZS6G1HYvMeGyIQUAIfkEBQoAAgAsFwARAAwAAwAAAgWEj6nLBQAh+QQFCgACACwVABUACgALAAACE5RgmcBqDB2MarZqZcZTU+4sRgEAIfkEBQoAAgAsEAAYAAQACwAAAgWEj6nLXAAh+QQFCgACACwFABUACgALAAACFZQvgAi92dyJcVJlLobUdi8x4bIhBQAh+QQFCgACACwBABEADAADAAACBYSPqcsFADs=) #eee center center no-repeat}.layui-layer-ico{background:url(data:image/png;base64,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) no-repeat}.layui-layer-dialog .layui-layer-ico,.layui-layer-setwin a,.layui-layer-btn a{display:inline-block;*display: inline;*zoom: 1;vertical-align:top}.layui-layer-move{display:none;position:fixed;*position: absolute;left:0;top:0;width:100%;height:100%;cursor:move;opacity:0;filter:alpha(opacity=0);background-color:#fff;z-index:2147483647}.layui-layer-resize{position:absolute;width:15px;height:15px;right:0;bottom:0;cursor:se-resize}.layui-layer{border-radius:2px;-webkit-animation-fill-mode:both;animation-fill-mode:both;-webkit-animation-duration:.3s;animation-duration:.3s}@-webkit-keyframes bounceIn{0%{opacity:0;-webkit-transform:scale(.5);transform:scale(.5)}to{opacity:1;-webkit-transform:scale(1);transform:scale(1)}}@keyframes bounceIn{0%{opacity:0;-webkit-transform:scale(.5);-ms-transform:scale(.5);transform:scale(.5)}to{opacity:1;-webkit-transform:scale(1);-ms-transform:scale(1);transform:scale(1)}}.layer-anim{-webkit-animation-name:bounceIn;animation-name:bounceIn}@-webkit-keyframes zoomInDown{0%{opacity:0;-webkit-transform:scale(.1) translateY(-2000px);transform:scale(.1) translateY(-2000px);-webkit-animation-timing-function:ease-in-out;animation-timing-function:ease-in-out}60%{opacity:1;-webkit-transform:scale(.475) translateY(60px);transform:scale(.475) translateY(60px);-webkit-animation-timing-function:ease-out;animation-timing-function:ease-out}}@keyframes zoomInDown{0%{opacity:0;-webkit-transform:scale(.1) translateY(-2000px);-ms-transform:scale(.1) translateY(-2000px);transform:scale(.1) translateY(-2000px);-webkit-animation-timing-function:ease-in-out;animation-timing-function:ease-in-out}60%{opacity:1;-webkit-transform:scale(.475) translateY(60px);-ms-transform:scale(.475) translateY(60px);transform:scale(.475) translateY(60px);-webkit-animation-timing-function:ease-out;animation-timing-function:ease-out}}.layer-anim-01{-webkit-animation-name:zoomInDown;animation-name:zoomInDown}@-webkit-keyframes fadeInUpBig{0%{opacity:0;-webkit-transform:translateY(2000px);transform:translateY(2000px)}to{opacity:1;-webkit-transform:translateY(0);transform:translateY(0)}}@keyframes fadeInUpBig{0%{opacity:0;-webkit-transform:translateY(2000px);-ms-transform:translateY(2000px);transform:translateY(2000px)}to{opacity:1;-webkit-transform:translateY(0);-ms-transform:translateY(0);transform:translateY(0)}}.layer-anim-02{-webkit-animation-name:fadeInUpBig;animation-name:fadeInUpBig}@-webkit-keyframes zoomInLeft{0%{opacity:0;-webkit-transform:scale(.1) translateX(-2000px);transform:scale(.1) translate(-2000px);-webkit-animation-timing-function:ease-in-out;animation-timing-function:ease-in-out}60%{opacity:1;-webkit-transform:scale(.475) translateX(48px);transform:scale(.475) translate(48px);-webkit-animation-timing-function:ease-out;animation-timing-function:ease-out}}@keyframes zoomInLeft{0%{opacity:0;-webkit-transform:scale(.1) translateX(-2000px);-ms-transform:scale(.1) translateX(-2000px);transform:scale(.1) translate(-2000px);-webkit-animation-timing-function:ease-in-out;animation-timing-function:ease-in-out}60%{opacity:1;-webkit-transform:scale(.475) translateX(48px);-ms-transform:scale(.475) translateX(48px);transform:scale(.475) translate(48px);-webkit-animation-timing-function:ease-out;animation-timing-function:ease-out}}.layer-anim-03{-webkit-animation-name:zoomInLeft;animation-name:zoomInLeft}@-webkit-keyframes rollIn{0%{opacity:0;-webkit-transform:translateX(-100%) rotate(-120deg);transform:translate(-100%) rotate(-120deg)}to{opacity:1;-webkit-transform:translateX(0px) rotate(0deg);transform:translate(0) rotate(0)}}@keyframes rollIn{0%{opacity:0;-webkit-transform:translateX(-100%) rotate(-120deg);-ms-transform:translateX(-100%) rotate(-120deg);transform:translate(-100%) rotate(-120deg)}to{opacity:1;-webkit-transform:translateX(0px) rotate(0deg);-ms-transform:translateX(0px) rotate(0deg);transform:translate(0) rotate(0)}}.layer-anim-04{-webkit-animation-name:rollIn;animation-name:rollIn}@keyframes fadeIn{0%{opacity:0}to{opacity:1}}.layer-anim-05{-webkit-animation-name:fadeIn;animation-name:fadeIn}@-webkit-keyframes shake{0%,to{-webkit-transform:translateX(0);transform:translate(0)}10%,30%,50%,70%,90%{-webkit-transform:translateX(-10px);transform:translate(-10px)}20%,40%,60%,80%{-webkit-transform:translateX(10px);transform:translate(10px)}}@keyframes shake{0%,to{-webkit-transform:translateX(0);-ms-transform:translateX(0);transform:translate(0)}10%,30%,50%,70%,90%{-webkit-transform:translateX(-10px);-ms-transform:translateX(-10px);transform:translate(-10px)}20%,40%,60%,80%{-webkit-transform:translateX(10px);-ms-transform:translateX(10px);transform:translate(10px)}}.layer-anim-06{-webkit-animation-name:shake;animation-name:shake}@-webkit-keyframes fadeIn{0%{opacity:0}to{opacity:1}}@-webkit-keyframes bounceOut{to{opacity:0;-webkit-transform:scale(.7);transform:scale(.7)}30%{-webkit-transform:scale(1.05);transform:scale(1.05)}0%{-webkit-transform:scale(1);transform:scale(1)}}@keyframes bounceOut{to{opacity:0;-webkit-transform:scale(.7);-ms-transform:scale(.7);transform:scale(.7)}30%{-webkit-transform:scale(1.05);-ms-transform:scale(1.05);transform:scale(1.05)}0%{-webkit-transform:scale(1);-ms-transform:scale(1);transform:scale(1)}}.layer-anim-close{-webkit-animation-name:bounceOut;animation-name:bounceOut;-webkit-animation-duration:.2s;animation-duration:.2s}.layui-layer-title{padding:0 80px 0 20px;height:42px;line-height:42px;border-bottom:1px solid #eee;font-size:14px;color:#333;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;background-color:#f8f8f8;border-radius:2px 2px 0 0}.layui-layer-setwin{position:absolute;right:15px;*right: 0;top:15px;font-size:0;line-height:initial}.layui-layer-setwin a{position:relative;width:16px;height:16px;margin-left:10px;font-size:12px;_overflow:hidden}.layui-layer-setwin .layui-layer-min cite{position:absolute;width:14px;height:2px;left:0;top:50%;margin-top:-1px;background-color:#2e2d3c;cursor:pointer;_overflow:hidden}.layui-layer-setwin .layui-layer-min:hover cite{background-color:#2d93ca}.layui-layer-setwin .layui-layer-max{background-position:-32px -40px}.layui-layer-setwin .layui-layer-max:hover{background-position:-16px -40px}.layui-layer-setwin .layui-layer-maxmin{background-position:-65px -40px}.layui-layer-setwin .layui-layer-maxmin:hover{background-position:-49px -40px}.layui-layer-setwin .layui-layer-close1{background-position:0 -40px;cursor:pointer}.layui-layer-setwin .layui-layer-close1:hover{opacity:.7}.layui-layer-setwin .layui-layer-close2{position:absolute;right:-28px;top:-28px;width:30px;height:30px;margin-left:0;background-position:-149px -31px;*right: -18px;_display:none}.layui-layer-setwin .layui-layer-close2:hover{background-position:-180px -31px}.layui-layer-btn{text-align:right;padding:0 10px 12px;pointer-events:auto;user-select:none;-webkit-user-select:none}.layui-layer-btn a{height:28px;line-height:28px;margin:0 6px;padding:0 15px;border:1px #dedede solid;background-color:#f1f1f1;color:#333;border-radius:2px;font-weight:400;cursor:pointer;text-decoration:none}.layui-layer-btn a:hover{opacity:.9;text-decoration:none}.layui-layer-btn a:active{opacity:.8}.layui-layer-btn .layui-layer-btn0{border-color:#4898d5;background-color:#2e8ded;color:#fff}.layui-layer-btn-l{text-align:left}.layui-layer-btn-c{text-align:center}.layui-layer-dialog{min-width:260px}.layui-layer-dialog .layui-layer-content{position:relative;padding:20px;line-height:24px;word-break:break-all;overflow:hidden;font-size:14px;overflow-x:hidden;overflow-y:auto}.layui-layer-dialog .layui-layer-content .layui-layer-ico{position:absolute;top:16px;left:15px;width:30px;height:30px}.layui-layer-ico1{background-position:-30px 0}.layui-layer-ico2{background-position:-60px 0}.layui-layer-ico3{background-position:-90px 0}.layui-layer-ico4{background-position:-120px 0}.layui-layer-ico5{background-position:-150px 0}.layui-layer-ico6{background-position:-180px 0}.layui-layer-rim{border:6px solid #8D8D8D;border:6px solid rgba(0,0,0,.3);border-radius:5px;box-shadow:none}.layui-layer-msg{min-width:180px;border:1px solid #D3D4D3;box-shadow:none}.layui-layer-hui{min-width:100px;background-color:#000;filter:alpha(opacity=60);background-color:#0009;color:#fff;border:none}.layui-layer-hui .layui-layer-content{padding:12px 25px;text-align:center}.layui-layer-dialog .layui-layer-padding{padding:20px 20px 20px 55px;text-align:left}.layui-layer-page .layui-layer-content{position:relative;overflow:auto}.layui-layer-page .layui-layer-btn,.layui-layer-iframe .layui-layer-btn{padding-top:10px}.layui-layer-nobg{background:none}.layui-layer-iframe iframe{display:block;width:100%}.layui-layer-loading{border-radius:100%;background:none;box-shadow:none;border:none}.layui-layer-loading .layui-layer-content{width:60px;height:24px;background:url(data:image/gif;base64,R0lGODlhPAAYALMPAPPJp/HYxfSwkf50Df5TD/+HAPe5bvqHR/twOviZavyrMu/m3f9EAP9mAP+ZAO7u7iH/C05FVFNDQVBFMi4wAwEAAAAh/wtYTVAgRGF0YVhNUDw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMC1jMDYwIDYxLjEzNDc3NywgMjAxMC8wMi8xMi0xNzozMjowMCAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wUmlnaHRzPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvcmlnaHRzLyIgeG1sbnM6eG1wTU09Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9tbS8iIHhtbG5zOnN0UmVmPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvc1R5cGUvUmVzb3VyY2VSZWYjIiB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iIHhtcFJpZ2h0czpNYXJrZWQ9IkZhbHNlIiB4bXBNTTpPcmlnaW5hbERvY3VtZW50SUQ9InhtcC5kaWQ6QUNDRERBRjMxRTIwNjgxMTg4QzZERjVGQ0I0MDI1NDkiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6NTlDMEI5MzU5RTY2MTFFMTkxRDY5NkVCMDBGOTBFRUYiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6NTlDMEI5MzQ5RTY2MTFFMTkxRDY5NkVCMDBGOTBFRUYiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNSBNYWNpbnRvc2giPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDpENzU2N0YwMTMyMjA2ODExODhDNkRGNUZDQjQwMjU0OSIgc3RS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) no-repeat}.layui-layer-loading .layui-layer-loading1{width:37px;height:37px;background:url(data:image/gif;base64,R0lGODlhJQAlAJECAL3L2AYrTv///wAAACH/C05FVFNDQVBFMi4wAwEAAAAh+QQFCgACACwAAAAAJQAlAAACi5SPqcvtDyGYIFpF690i8xUw3qJBwUlSadmcLqYmGQu6KDIeM13beGzYWWy3DlB4IYaMk+Dso2RWkFCfLPcRvFbZxFLUDTt21BW56TyjRep1e20+i+eYMR145W2eefj+6VFmgTQi+ECVY8iGxcg35phGo/iDFwlTyXWphwlm1imGRdcnuqhHeop6UAAAIfkEBQoAAgAsEAACAAQACwAAAgWMj6nLXAAh+QQFCgACACwVAAUACgALAAACFZQvgRi92dyJcVJlLobUdi8x4bIhBQAh+QQFCgACACwXABEADAADAAACBYyPqcsFACH5BAUKAAIALBUAFQAKAAsAAAITlGKZwWoMHYxqtmplxlNT7ixGAQAh+QQFCgACACwQABgABAALAAACBYyPqctcACH5BAUKAAIALAUAFQAKAAsAAAIVlC+BGL3Z3IlxUmUuhtR2LzHhsiEFACH5BAUKAAIALAEAEQAMAAMAAAIFjI+pywUAIfkEBQoAAgAsBQAFAAoACwAAAhOUYJnAagwdjGq2amXGU1PuLEYBACH5BAUKAAIALBAAAgAEAAsAAAIFhI+py1wAIfkEBQoAAgAsFQAFAAoACwAAAhWUL4AIvdnciXFSZS6G1HYvMeGyIQUAIfkEBQoAAgAsFwARAAwAAwAAAgWEj6nLBQAh+QQFCgACACwVABUACgALAAACE5RgmcBqDB2MarZqZcZTU+4sRgEAIfkEBQoAAgAsEAAYAAQACwAAAgWEj6nLXAAh+QQFCgACACwFABUACgALAAACFZQvgAi92dyJcVJlLobUdi8x4bIhBQAh+QQFCgACACwBABEADAADAAACBYSPqcsFADs=) no-repeat}.layui-layer-loading .layui-layer-loading2,.layui-layer-ico16{width:32px;height:32px;background:url(data:image/gif;base64,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) no-repeat}.layui-layer-tips{background:none;box-shadow:none;border:none}.layui-layer-tips .layui-layer-content{position:relative;line-height:22px;min-width:12px;padding:5px 10px;font-size:12px;_float:left;border-radius:2px;box-shadow:1px 1px 3px #0003;background-color:#000;color:#fff}.layui-layer-tips .layui-layer-close{right:-2px;top:-1px}.layui-layer-tips i.layui-layer-TipsG{position:absolute;width:0;height:0;border-width:8px;border-color:transparent;border-style:dashed;*overflow: hidden}.layui-layer-tips i.layui-layer-TipsT,.layui-layer-tips i.layui-layer-TipsB{left:5px;border-right-style:solid;border-right-color:#000}.layui-layer-tips i.layui-layer-TipsT{bottom:-8px}.layui-layer-tips i.layui-layer-TipsB{top:-8px}.layui-layer-tips i.layui-layer-TipsR,.layui-layer-tips i.layui-layer-TipsL{top:1px;border-bottom-style:solid;border-bottom-color:#000}.layui-layer-tips i.layui-layer-TipsR{left:-8px}.layui-layer-tips i.layui-layer-TipsL{right:-8px}.layui-layer-lan[type=dialog]{min-width:280px}.layui-layer-lan .layui-layer-title{background:#4476a7;color:#fff;border:none}.layui-layer-lan .layui-layer-btn{padding:10px;text-align:right;border-top:1px solid #E9E7E7}.layui-layer-lan .layui-layer-btn a{background:#bbb5b5;border:none}.layui-layer-lan .layui-layer-btn .layui-layer-btn1{background:#c9c5c5}.layui-layer-molv .layui-layer-title{background:#009f95;color:#fff;border:none}.layui-layer-molv .layui-layer-btn a{background:#009f95}.layui-layer-molv .layui-layer-btn .layui-layer-btn1{background:#92b8b1}.layui-layer-iconext{background:url(data:image/png;base64,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) no-repeat}.layui-layer-prompt .layui-layer-input{display:block;width:220px;height:30px;margin:0 auto;line-height:30px;padding:0 5px;border:1px solid #ccc;box-shadow:1px 1px 5px #0000001a inset;color:#333}.layui-layer-prompt textarea.layui-layer-input{width:300px;height:100px;line-height:20px}.layui-layer-prompt .layui-layer-content{padding:20px}.layui-layer-prompt .layui-layer-btn{padding-top:0}.layui-layer-tab{box-shadow:1px 1px 50px #0006}.layui-layer-tab .layui-layer-title{padding-left:0;border-bottom:1px solid #ccc;background-color:#eee;overflow:visible}.layui-layer-tab .layui-layer-title span{position:relative;float:left;min-width:80px;max-width:260px;padding:0 20px;text-align:center;cursor:default;text-overflow:ellipsis;overflow:hidden;white-space:nowrap}.layui-layer-tab .layui-layer-title span.layui-layer-tabnow{height:43px;border-left:1px solid #ccc;border-right:1px solid #ccc;background-color:#fff;z-index:10}.layui-layer-tab .layui-layer-title span:first-child{border-left:none}.layui-layer-tabmain{line-height:24px;clear:both}.layui-layer-tabmain .layui-layer-tabli{display:none}.layui-layer-tabmain .layui-layer-tabli.xubox_tab_layer{display:block}.xubox_tabclose{position:absolute;right:10px;top:5px;cursor:pointer}.layui-layer-photos{-webkit-animation-duration:1s;animation-duration:1s}.layui-layer-photos .layui-layer-content{overflow:hidden;text-align:center}.layui-layer-photos .layui-layer-phimg img{position:relative;width:100%;display:inline-block;*display: inline;*zoom: 1;vertical-align:top}.layui-layer-imguide,.layui-layer-imgbar{display:none}.layui-layer-imgprev,.layui-layer-imgnext{position:absolute;top:50%;width:27px;_width:44px;height:44px;margin-top:-22px;outline:none;blr:expression(this.onFocus=this.blur())}.layui-layer-imgprev{left:10px;background-position:-5px -5px}.layui-layer-imgprev:hover{background-position:-33px -5px}.layui-layer-imgnext{right:10px;background-position:-5px -50px}.layui-layer-imgnext:hover{background-position:-33px -50px}.layui-layer-imgbar{position:absolute;left:0;bottom:0;width:100%;height:32px;line-height:32px;background-color:#000c;background-color:#000 \\ ;filter:Alpha(opacity=80);color:#fff;text-overflow:ellipsis;overflow:hidden;white-space:nowrap;font-size:0}.layui-layer-imgtit *{display:inline-block;*display: inline;*zoom: 1;vertical-align:top;font-size:12px}.layui-layer-imgtit a{max-width:65%;text-overflow:ellipsis;overflow:hidden;white-space:nowrap;color:#fff}.layui-layer-imgtit a:hover{color:#fff;text-decoration:underline}.layui-layer-imgtit em{padding-left:10px;font-style:normal}@media screen and (max-width:1100px){.layui-layer-iframe{overflow-y:auto;-webkit-overflow-scrolling:touch}} "); System.addImportMap({ imports: { "jquery": "user:jquery", "localforage": "user:localforage", "toastify-js": "user:toastify-js", "blueimp-md5": "user:blueimp-md5", "viewerjs": "user:viewerjs", "qrcodejs": "user:qrcodejs" } }); System.set("user:jquery", (() => { const _ = jQuery; ('default' in _) || (_.default = _); return _ })()); System.set("user:localforage", (() => { const _ = localforage; ('default' in _) || (_.default = _); return _ })()); System.set("user:toastify-js", (() => { const _ = Toastify; ('default' in _) || (_.default = _); return _ })()); System.set("user:blueimp-md5", (() => { const _ = md5; ('default' in _) || (_.default = _); return _ })()); System.set("user:viewerjs", (() => { const _ = Viewer; ('default' in _) || (_.default = _); return _ })()); System.set("user:qrcodejs", (() => { const _ = QRCode; ('default' in _) || (_.default = _); return _ })()); System.register("./__entry.js", ['jquery', 'localforage', 'toastify-js', 'blueimp-md5', 'viewerjs', 'qrcodejs'], (function (exports, module) { 'use strict'; var $$1, localforage$1, Toastify$1, md5$1, Viewer$1, QRCode$1; return { setters: [module => { $$1 = module.default; }, module => { localforage$1 = module.default; }, module => { Toastify$1 = module.default; }, module => { md5$1 = module.default; }, module => { Viewer$1 = module.default; }, module => { QRCode$1 = module.default; }], execute: (async function () { var __defProp = Object.defineProperty; var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value; var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value); var _a; const scriptRel = /* @__PURE__ */ (function detectScriptRel() { const relList = typeof document !== "undefined" && document.createElement("link").relList; return relList && relList.supports && relList.supports("modulepreload") ? "modulepreload" : "preload"; })(); const assetsURL = function (dep) { return "/" + dep; }; const seen = {}; const __vitePreload = function preload(baseModule, deps, importerUrl) { let promise = Promise.resolve(); if (deps && deps.length > 0) { let allSettled2 = function (promises) { return Promise.all( promises.map( (p) => Promise.resolve(p).then( (value) => ({status: "fulfilled", value}), (reason) => ({status: "rejected", reason}) ) ) ); }; document.getElementsByTagName("link"); const cspNonceMeta = document.querySelector( "meta[property=csp-nonce]" ); const cspNonce = (cspNonceMeta == null ? void 0 : cspNonceMeta.nonce) || (cspNonceMeta == null ? void 0 : cspNonceMeta.getAttribute("nonce")); promise = allSettled2( deps.map((dep) => { dep = assetsURL(dep); if (dep in seen) return; seen[dep] = true; const isCss = dep.endsWith(".css"); const cssSelector = isCss ? '[rel="stylesheet"]' : ""; if (document.querySelector(`link[href="${dep}"]${cssSelector}`)) { return; } const link2 = document.createElement("link"); link2.rel = isCss ? "stylesheet" : scriptRel; if (!isCss) { link2.as = "script"; } link2.crossOrigin = ""; link2.href = dep; if (cspNonce) { link2.setAttribute("nonce", cspNonce); } document.head.appendChild(link2); if (isCss) { return new Promise((res, rej) => { link2.addEventListener("load", res); link2.addEventListener( "error", () => rej(new Error(`Unable to preload CSS for ${dep}`)) ); }); } }) ); } function handlePreloadError(err) { const e = new Event("vite:preloadError", { cancelable: true }); e.payload = err; window.dispatchEvent(e); if (!e.defaultPrevented) { throw err; } } return promise.then((res) => { for (const item of res || []) { if (item.status !== "rejected") continue; handlePreloadError(item.reason); } return baseModule().catch(handlePreloadError); }); }; var __defProp2 = Object.defineProperty, __typeError = (msg) => { throw TypeError(msg); }, __publicField2 = (obj, key, value) => ((obj2, key2, value2) => key2 in obj2 ? __defProp2(obj2, key2, { enumerable: true, configurable: true, writable: true, value: value2 }) : obj2[key2] = value2)(obj, "symbol" != typeof key ? key + "" : key, value), __privateMethod = (obj, member, method) => (((obj2, member2, msg) => { member2.has(obj2) || __typeError("Cannot " + msg); })(obj, member, "access private method"), method); const currentHref$1 = window.location.href, isJavDb$1 = currentHref$1.includes("javdb"), isJavBus$1 = currentHref$1.includes("javbus") || currentHref$1.includes("seejav") || currentHref$1.includes("bus") || currentHref$1.includes("javsee") || "javbus" === (() => { try { const _alt = $(".hidden-xs").attr("alt"); return _alt ? _alt.trim().toLowerCase() : void 0; } catch (_e) { return void 0; } })(), isSearchPage = currentHref$1.includes("/search?q") || currentHref$1.includes("/search/") || currentHref$1.includes("/users/"), Status_RUNNING = "RUNNING", Status_SUCCESS = "SUCCESS", Status_FAIL = "FAIL", Status_LOADING = "LOADING", Status_FILTER$1 = "filter", Status_FAVORITE$1 = "favorite", Status_HAS_DOWN$1 = "hasDown", Status_HAS_WATCH$1 = "hasWatch", NO$1 = "no", YES$1 = "yes", qualityOptions = [{ id: "video-mhb", quality: "dmb_w", text: "旧视频源-中画质宽版 (404p)", canSelect: false }, { id: "video-mhb", quality: "sm_s", text: "旧视频源-低画质 (240p)", canSelect: false }, { id: "video-mhb", quality: "dm_s", text: "旧视频源-中画质 (360p)", canSelect: false }, { id: "video-mhb", quality: "dmb_s", text: "旧视频源-中画质 (480p)", canSelect: false }, { id: "video-mhb", quality: "mhb_w", text: "旧视频源-高画质宽版 (404p)", canSelect: false }, { id: "video-mmb", quality: "mmb", text: "中画质 (432p)", canSelect: true }, { id: "video-dm", quality: "dm", text: "低画质 (1000kbps)", canSelect: true }, { id: "video-dmb", quality: "dmb", text: "中画质 (1500kbps)", canSelect: true }, { id: "video-mhb", quality: "mhb", text: "高画质 (576p)", canSelect: true }, { id: "video-hmb", quality: "hmb", text: "HD (720p)", canSelect: true }, { id: "video-hhb", quality: "hhb", text: "FullHD (1080p)", canSelect: true }, { id: "video-hhbs", quality: "hhbs", text: "FullHD (1080p60fps)", canSelect: true }, { id: "video-4k", quality: "4k", text: "4K (2160p)", canSelect: true }, { id: "video-4ks", quality: "4ks", text: "4K (2160p60fps)", canSelect: true }]; let detailPageCss$1 = ""; window.location.href.includes("hideNav=1") && (detailPageCss$1 = "\n .navbar-default {\n display: none !important;\n }\n body {\n padding-top:0px!important;\n }\n "); const javBusStyle = ` `; let detailPageCss = ""; window.location.href.includes("hideNav=1") && (detailPageCss = "\n .main-nav,#search-bar-container {\n display: none !important;\n }\n \n html {\n padding-top:0px!important;\n }\n "); const javdbStyle = ` `; const mainCss = ` `; const subtitleModalCss = ` `; function insertStyle(css) { if (css) if (css.includes("\n" ); insertStyle(mainCss); insertStyle(subtitleModalCss); const isEligibleDmmCoverCode = (value) => { const raw = String(value || "").trim().toUpperCase(); if (!/^[A-Z0-9]{2,10}-\d{1,6}$/.test(raw)) return false; const code = raw.replace(/\s+/g, "-").toUpperCase(); if (!/^[A-Z0-9]{2,10}-\d{1,6}$/.test(code) || /^FC2-/.test(code)) return false; if (/^\d{6}[-_]\d{2,3}$/.test(code)) return false; if (/^(DUGA|MYWIFE|HEYZO|PACO|10MU|1PONDO|CARIBBEAN|CARIB|TOKYO|GACHI|REAL|JUKU|AKA|NTR)-/.test(code)) return false; return true; }; window.$ = window.jQuery = $$1; if (typeof $$1.trim !== "function") { $$1.trim = function (text) { return text == null ? "" : (text + "").trim(); }; } if (typeof jQuery !== "undefined" && typeof layer === "undefined") { await __vitePreload(() => module.import('./layer-npqWxmx4-BZXOsKge.js').then((n) => n.l), void 0); } window.localforage = localforage$1; window.Toastify = Toastify$1; window.md5 = md5$1; window.Viewer = Viewer$1; window.QRCode = QRCode$1; window.currentHref = currentHref$1; window.isJavDb = isJavDb$1; window.isJavBus = isJavBus$1; window.isSearchPage = isSearchPage; window.Status_RUNNING = Status_RUNNING; window.Status_SUCCESS = Status_SUCCESS; window.Status_FAIL = Status_FAIL; window.Status_LOADING = Status_LOADING; window.Status_FILTER = Status_FILTER$1; window.Status_FAVORITE = Status_FAVORITE$1; window.Status_HAS_DOWN = Status_HAS_DOWN$1; window.Status_HAS_WATCH = Status_HAS_WATCH$1; window.NO = NO$1; window.YES = YES$1; const HAS_GM = typeof GM !== "undefined"; const NEW_GM = ((scope, GM2) => { if (typeof GM_info === "undefined" || GM_info.scriptHandler !== "Tampermonkey" || compareVersions(GM_info.version, "5.3.2") < 0) return; const GM_xmlhttpRequestOrig = GM_xmlhttpRequest; const GM_xmlHttpRequestOrig = GM2.xmlHttpRequest; function compareVersions(v1, v2) { const parts1 = v1.split(".").map(Number); const parts2 = v2.split(".").map(Number); const length = Math.max(parts1.length, parts2.length); for (let i = 0; i < length; i++) { const num1 = parts1[i] || 0; const num2 = parts2[i] || 0; if (num1 > num2) return 1; if (num1 < num2) return -1; } return 0; } function GM_xmlhttpRequestWrapper(odetails) { if (odetails.redirect !== void 0) { return GM_xmlhttpRequestOrig(odetails); } if (odetails.onprogress || odetails.fetch === false) { console.warn("Fetch mode does not support onprogress in the background."); } const { onload, onloadend, onerror, onabort, ontimeout, ...details } = odetails; const handleRedirects = (initialDetails) => { const request = GM_xmlhttpRequestOrig({ ...initialDetails, redirect: "manual", onload: function (response) { if (response.status >= 300 && response.status < 400) { const m = response.responseHeaders.match(/Location:\s*(\S+)/i); const redirectUrl = m && m[1]; if (redirectUrl) { const absoluteUrl = new URL(redirectUrl, initialDetails.url).href; handleRedirects({...initialDetails, url: absoluteUrl}); return; } } if (onload) onload.call(this, response); if (onloadend) onloadend.call(this, response); }, onerror: function (response) { if (onerror) onerror.call(this, response); if (onloadend) onloadend.call(this, response); }, onabort: function (response) { if (onabort) onabort.call(this, response); if (onloadend) onloadend.call(this, response); }, ontimeout: function (response) { if (ontimeout) ontimeout.call(this, response); if (onloadend) onloadend.call(this, response); } }); return request; }; return handleRedirects(details); } function GM_xmlHttpRequestWrapper(odetails) { let abort; const p = new Promise((resolve, reject) => { const {onload, ontimeout, onerror, ...send} = odetails; send.onerror = function (r) { if (onerror) { resolve(r); onerror.call(this, r); } else { reject(r); } }; send.ontimeout = function (r) { if (ontimeout) { resolve(r); ontimeout.call(this, r); } else { reject(r); } }; send.onload = function (r) { resolve(r); if (onload) onload.call(this, r); }; const a = GM_xmlhttpRequestWrapper(send).abort; if (abort === true) { a(); } else { abort = a; } }); p.abort = () => { if (typeof abort === "function") { abort(); } else { abort = true; } }; return p; } GM_xmlhttpRequest = GM_xmlhttpRequestWrapper; scope.GM_xmlhttpRequestOrig = GM_xmlhttpRequestOrig; const gopd = Object.getOwnPropertyDescriptor(GM2, "xmlHttpRequest"); if (gopd && gopd.configurable === false) { return { __proto__: GM2, xmlHttpRequest: GM_xmlHttpRequestWrapper, xmlHttpRequestOrig: GM_xmlHttpRequestOrig }; } else { GM2.xmlHttpRequest = GM_xmlHttpRequestWrapper; GM2.xmlHttpRequestOrig = GM_xmlHttpRequestOrig; } })(globalThis, HAS_GM ? GM : {}); if (HAS_GM && NEW_GM) GM = NEW_GM; var _StorageManager_instances, setItem_fn, saveFilterItem_fn; _StorageManager_instances = /* @__PURE__ */ new WeakSet(); setItem_fn = async function (key, data) { key === this.favorite_actresses_key && window.clean_cacheFavoriteActressList(); key === this.blacklist_car_list_key && window.clean_cacheBlacklistCarList(); key === this.setting_key && window.clean_cacheSettingObj(); key === this.car_list_key && window.clean_cacheCarList(); await this.forage.setItem(key, data); }; saveFilterItem_fn = async function (items, storageKey, itemName) { let itemList; if (Array.isArray(items)) itemList = [...items]; else { itemList = await this.forage.getItem(storageKey) || []; if (itemList.includes(items)) { const errorMsg = `${items} ${itemName}已存在`; show.error(errorMsg); throw new Error(errorMsg); } itemList.push(items); } await __privateMethod(this, _StorageManager_instances, setItem_fn).call(this, storageKey, itemList); return itemList; }; let StorageManager = class _StorageManager { constructor() { obj = this, (member = _StorageManager_instances).has(obj) ? __typeError("Cannot add the same private member more than once") : member instanceof WeakSet ? member.add(obj) : member.set(obj, value); var obj, member, value; __publicField2(this, "car_list_key", "car_list"); __publicField2(this, "filter_keyword_title_key", "filter_keyword_title"); __publicField2(this, "filter_keyword_review_key", "filter_keyword_review"); __publicField2(this, "setting_key", "setting"); __publicField2(this, "blacklist_key", "blacklist"); __publicField2(this, "blacklist_car_list_key", "blacklist_car_list"); __publicField2(this, "favorite_actresses_key", "favorite_actresses"); __publicField2(this, "highlighted_tags_key", "highlighted_tags"); __publicField2(this, "forage", localforage.createInstance({ driver: localforage.INDEXEDDB, name: "JAV-JHS", version: 1, storeName: "appData" })); __publicField2(this, "cacheCarList", null); __publicField2(this, "cacheBlacklistCarList", null); __publicField2(this, "cacheFavoriteActressList", null); __publicField2(this, "cacheSettingObj", null); if (_StorageManager.instance) throw new Error("StorageManager已被实例化过了!"); _StorageManager.instance = this; } async getCarList() { if (this.cacheCarList) return utils.copyObj(this.cacheCarList); this.cacheCarList = await this.forage.getItem(this.car_list_key) || []; return utils.copyObj(this.cacheCarList); } async getCar(carNum2) { return (await this.getCarList()).find(((item) => item.carNum === carNum2)); } _handleSingleCar(carParam, carList) { let {carNum: carNum2, url, names, actionType, publishTime, starId} = carParam; if (!carNum2) { show.error("番号为空!"); throw new Error("番号为空!"); } if (!url) { show.error("url为空!"); throw new Error("url为空!"); } url.includes("http") || (url = window.location.origin + url); names && (names = names.trim()); let carData = carList.find(((item) => item.carNum === carNum2)); if (carData) { names && (carData.names = names); url && (carData.url = url); publishTime && (carData.publishTime = publishTime); carData.updateDate = utils.getNowStr(); } else { let nowStr = utils.getNowStr(); carData = { carNum: carNum2, url, names, status: "", createDate: nowStr, updateDate: nowStr, publishTime }; starId && (carData.starId = starId); carList.push(carData); } switch (actionType) { case Status_FILTER: if (carData.status === Status_FILTER) { const msg2 = `${carNum2} 已在屏蔽列表中`; show.error(msg2); throw new Error(msg2); } carData.status = Status_FILTER; break; case Status_FAVORITE: if (carData.status === Status_FAVORITE) { const msg2 = `${carNum2} 已在收藏列表中`; show.error(msg2); throw new Error(msg2); } carData.status = Status_FAVORITE; break; case Status_HAS_DOWN: carData.status = Status_HAS_DOWN; break; case Status_HAS_WATCH: carData.status = Status_HAS_WATCH; break; default: const msg = "actionType错误, 请联系作者更正: " + actionType; show.error(msg); throw new Error(msg); } } async saveCar(carData) { const carList = await this.forage.getItem(this.car_list_key) || []; this._handleSingleCar(carData, carList); await __privateMethod(this, _StorageManager_instances, setItem_fn).call(this, this.car_list_key, carList); await this.removeNewVideoList([carData.carNum]); } async updateCarInfo(carParam) { let {carNum: carNum2, url, names, actionType, publishTime, remark} = carParam; if (!carNum2) { show.error("番号为空!"); throw new Error("番号为空!"); } if (!url) { show.error("url为空!"); throw new Error("url为空!"); } names && (names = names.trim()); const carList = await this.forage.getItem(this.car_list_key) || []; let carData = carList.find(((item) => item.carNum === carNum2)); if (!carData) { const msg = "数据不存在: " + carNum2; show.error(msg); throw new Error(msg); } carData.names = names; carData.url = url; carData.remark = remark; carData.updateDate = utils.getNowStr(); switch (actionType) { case Status_FILTER: carData.status = Status_FILTER; break; case Status_FAVORITE: carData.status = Status_FAVORITE; break; case Status_HAS_DOWN: carData.status = Status_HAS_DOWN; break; case Status_HAS_WATCH: carData.status = Status_HAS_WATCH; break; default: const msg = "actionType错误, 请联系作者更正: " + actionType; show.error(msg); throw new Error(msg); } await __privateMethod(this, _StorageManager_instances, setItem_fn).call(this, this.car_list_key, carList); } async saveCarList(carRecords) { if (!carRecords || !Array.isArray(carRecords) || 0 === carRecords.length) { show.error("记录列表为空!"); throw new Error("记录列表为空!"); } const carList = await this.forage.getItem(this.car_list_key) || []; for (const record of carRecords) try { this._handleSingleCar(record, carList); } catch (error) { throw error; } await __privateMethod(this, _StorageManager_instances, setItem_fn).call(this, this.car_list_key, carList); } async removeNewVideoList(carNumList) { const favoriteActressesList = await this.getFavoriteActressList(); let hasAnyListBeenModified = false; const updatedActressList = favoriteActressesList.map(((actress) => { if (!actress.newVideoList || !Array.isArray(actress.newVideoList)) return actress; const newFilteredVideoList = actress.newVideoList.filter(((carNumString) => { const isRemoved = carNumList.includes(carNumString); if (isRemoved) { clog.log("移除关联女优新作品", actress.name, carNumString); hasAnyListBeenModified = true; } return !isRemoved; })); return { ...actress, newVideoList: newFilteredVideoList }; })); hasAnyListBeenModified && await __privateMethod(this, _StorageManager_instances, setItem_fn).call(this, this.favorite_actresses_key, updatedActressList); } async removeCar(carNum2) { const carList = await this.getCarList(), initialLength = carList.length, updatedList = carList.filter(((car) => car.carNum !== carNum2)); if (updatedList.length === initialLength) { show.error(`${carNum2} 不存在`); return false; } await __privateMethod(this, _StorageManager_instances, setItem_fn).call(this, this.car_list_key, updatedList); return true; } async batchRemoveCars(carNumList) { if (!carNumList || 0 === carNumList.length) throw new Error("未传入参数"); const carList = await this.getCarList(), initialLength = carList.length, carNumsSet = new Set(carNumList), updatedList = carList.filter(((car) => !carNumsSet.has(car.carNum))), removedCount = initialLength - updatedList.length; if (0 === removedCount) return removedCount; await __privateMethod(this, _StorageManager_instances, setItem_fn).call(this, this.car_list_key, updatedList); return removedCount; } async getBlacklist() { return await this.forage.getItem(this.blacklist_key) || []; } async addBlacklistItem(item) { let {starId, name: name2, allName, role, movieType, url} = item; if (!starId) throw new Error("缺失starId"); if (!name2) throw new Error("缺失name"); if (!role) throw new Error("缺失role"); const blacklist = await this.getBlacklist(), existData = blacklist.find(((item2) => item2.starId === starId)); if (existData) { existData.url = url; existData.role = role; existData.movieType = movieType; clog.log("更新黑名单演员信息", existData); } else { const info = { starId, name: name2, allName: allName || [name2], createTime: utils.getNowStr(), role, movieType, url }; blacklist.push(info); clog.log("增加黑名单演员信息", info); } await __privateMethod(this, _StorageManager_instances, setItem_fn).call(this, this.blacklist_key, blacklist); } async updateBlacklistItem(item) { if (!item || !item.starId) throw new Error("参数不全"); const filterActorActressInfoList = await this.getBlacklist(), waitUpdateObj = filterActorActressInfoList.find(((i) => i.starId === item.starId)); if (!waitUpdateObj) throw new Error(`未找到黑名单演员信息:${item.name} ${item.starId}`); item.checkTime && (waitUpdateObj.checkTime = item.checkTime); item.lastPublishTime && (waitUpdateObj.lastPublishTime = item.lastPublishTime); await __privateMethod(this, _StorageManager_instances, setItem_fn).call(this, this.blacklist_key, filterActorActressInfoList); } async deleteBlacklistItem(starId) { const blacklist = await this.getBlacklist(), updatedList = blacklist.filter(((item) => item.starId !== starId)); blacklist.length !== updatedList.length && await __privateMethod(this, _StorageManager_instances, setItem_fn).call(this, this.blacklist_key, updatedList); } async getBlacklistCarList() { if (this.cacheBlacklistCarList && this.cacheBlacklistCarList.length > 0) return utils.deepFreeze(this.cacheBlacklistCarList); this.cacheBlacklistCarList = await this.forage.getItem(this.blacklist_car_list_key) || []; setTimeout((() => { utils.deepFreeze(this.cacheBlacklistCarList); }), 0); return this.cacheBlacklistCarList; } async batchSaveBlacklistCarList(carDataList) { const carList = await this.getCarList(); let blacklistCarList = await this.getBlacklistCarList(), hasChanged = false, copyBlacklistCarList = null, carNumList = []; for (const carData of carDataList) { let existBlacklistCarData = blacklistCarList.find(((item) => item.carNum === carData.carNum)); if (existBlacklistCarData) { console.log("已在鉴定记录中", existBlacklistCarData); continue; } let existCarData = carList.find(((item) => item.carNum === carData.carNum)); if (existCarData) console.log("已在鉴定记录中", existCarData); else { copyBlacklistCarList || (copyBlacklistCarList = utils.copyObj(blacklistCarList)); this._handleSingleCar(carData, copyBlacklistCarList); clog.log(`屏蔽演员番号: ${carData.names} ${carData.carNum}`); hasChanged = true; carNumList.push(carData.carNum); } } if (hasChanged) { if (!copyBlacklistCarList) throw new Error("程序异常, 黑名单番号数据对象为空!"); await __privateMethod(this, _StorageManager_instances, setItem_fn).call(this, this.blacklist_car_list_key, copyBlacklistCarList); await this.removeNewVideoList(carNumList); } } async removeBlacklistCarList(starId) { const filterActorActressCarList = await this.getBlacklistCarList(), newList = filterActorActressCarList.filter(((car) => car.starId !== starId)); newList.length !== filterActorActressCarList.length && await __privateMethod(this, _StorageManager_instances, setItem_fn).call(this, this.blacklist_car_list_key, newList); } async batchRemoveBlacklistCars(carNumList) { if (!carNumList || 0 === carNumList.length) throw new Error("未传入参数"); const blacklistCarList = await this.getBlacklistCarList(), initialLength = blacklistCarList.length, carNumsSet = new Set(carNumList), updatedList = blacklistCarList.filter(((car) => !carNumsSet.has(car.carNum))), removedCount = initialLength - updatedList.length; if (0 === removedCount) return removedCount; await __privateMethod(this, _StorageManager_instances, setItem_fn).call(this, this.blacklist_car_list_key, updatedList); return removedCount; } async getFavoriteActressList() { if (this.cacheFavoriteActressList) return utils.copyObj(this.cacheFavoriteActressList); this.cacheFavoriteActressList = await this.forage.getItem(this.favorite_actresses_key) || []; return utils.copyObj(this.cacheFavoriteActressList); } async addFavoriteActressList(actressList) { const favoriteActressesInfoList = await this.getFavoriteActressList(); let resultCount = 0; for (const actress of actressList) { let {starId, name: name2, allName, avatar, lastCheckTime, lastPublishTime, actressType} = actress; if (!starId) throw new Error("缺失starId"); if (!name2) throw new Error("缺失name"); allName || (allName = [name2]); const uncensoredText = "(無碼)"; if (!actressType) { actressType = name2.includes(uncensoredText) || allName.some(((element) => element.includes(uncensoredText))) ? "uncensored" : "censored"; } name2 = name2.replace(uncensoredText, ""); allName = allName.map(((n) => n.replace(uncensoredText, ""))); let favoriteActresses = favoriteActressesInfoList.find(((item) => item.starId === starId)); if (favoriteActresses) { if ((!favoriteActresses.avatar || !favoriteActresses.avatar.includes("https")) && avatar) { clog.log(avatar); favoriteActresses.avatar = avatar; clog.log(`补全女优头像: ${name2}`); resultCount++; } if (!favoriteActresses.actressType && actressType) { favoriteActresses.actressType = actressType; clog.log(`补全女优类别: ${name2} ${actressType}`); resultCount++; } if (favoriteActresses.name.includes(uncensoredText)) { favoriteActresses.name = name2; favoriteActresses.allName = allName; clog.log(`更正女优名字: ${name2} ${allName}`); resultCount++; } continue; } const nowStr = utils.getNowStr(); favoriteActressesInfoList.push({ starId, name: name2, allName, avatar, lastCheckTime, lastPublishTime, createDate: nowStr, updateDate: nowStr, actressType }); clog.log(`同步JavDB已收藏的演员: ${name2}`); resultCount++; } resultCount > 0 ? await __privateMethod(this, _StorageManager_instances, setItem_fn).call(this, this.favorite_actresses_key, favoriteActressesInfoList) : clog.log("信息已记录, 无需要进行同步收藏的演员"); return resultCount; } async removeFavoriteActress(starId) { const favoriteActressesInfoList = await this.getFavoriteActressList(), initialLength = favoriteActressesInfoList.length, updatedList = favoriteActressesInfoList.filter(((car) => car.starId !== starId)); if (updatedList.length === initialLength) { clog.error(`移除演员失败, ${starId} 不存在`); return false; } await __privateMethod(this, _StorageManager_instances, setItem_fn).call(this, this.favorite_actresses_key, updatedList); return true; } async updateFavoriteActress(actress) { const favoriteActressesInfoList = await this.getFavoriteActressList(), { starId, name: name2, allName, avatar, lastCheckTime, newVideoList, lastPublishTime, actressType, remark } = actress; if (!starId) throw new Error("缺失starId"); let favoriteActresses = favoriteActressesInfoList.find(((item) => item.starId === starId)); if (!favoriteActresses) { clog.error("未找到演员信息", starId, name2); return false; } name2 && (favoriteActresses.name = name2); allName && (favoriteActresses.allName = allName); avatar && (favoriteActresses.avatar = avatar); null != actressType && (favoriteActresses.actressType = actressType); lastCheckTime && (favoriteActresses.lastCheckTime = lastCheckTime); newVideoList && (favoriteActresses.newVideoList = newVideoList); lastPublishTime && (favoriteActresses.lastPublishTime = lastPublishTime); remark && (favoriteActresses.remark = remark); favoriteActresses.updateDate = utils.getNowStr(); await __privateMethod(this, _StorageManager_instances, setItem_fn).call(this, this.favorite_actresses_key, favoriteActressesInfoList); } async getHighlightedTags() { return await this.forage.getItem(this.highlighted_tags_key) || []; } async setHighlightedTags(highlightedTags) { return await __privateMethod(this, _StorageManager_instances, setItem_fn).call(this, this.highlighted_tags_key, highlightedTags); } async saveTitleFilterKeyword(keywords) { await __privateMethod(this, _StorageManager_instances, saveFilterItem_fn).call(this, keywords, this.filter_keyword_title_key, "标题关键词"); if (Array.isArray(keywords)) return null; const favoriteActressesList = await this.getFavoriteActressList(); let hasAnyListBeenModified = false; const updatedActressList = favoriteActressesList.map(((actress) => { if (!actress.newVideoList || !Array.isArray(actress.newVideoList)) return actress; const newFilteredVideoList = actress.newVideoList.filter(((carNumString) => { const isRemoved = carNumString.startsWith(keywords); if (isRemoved) { clog.log("移除关联女优新作品", actress.name, carNumString); hasAnyListBeenModified = true; } return !isRemoved; })); return { ...actress, newVideoList: newFilteredVideoList }; })); hasAnyListBeenModified && await __privateMethod(this, _StorageManager_instances, setItem_fn).call(this, this.favorite_actresses_key, updatedActressList); } async getTitleFilterKeyword() { return await this.forage.getItem(this.filter_keyword_title_key) || []; } async getReviewFilterKeywordList() { return await this.forage.getItem(this.filter_keyword_review_key) || []; } async saveReviewFilterKeyword(keywords) { return __privateMethod(this, _StorageManager_instances, saveFilterItem_fn).call(this, keywords, this.filter_keyword_review_key, "评论关键词"); } async getSetting(attribute = null, defaultVal) { this.cacheSettingObj || (this.cacheSettingObj = await this.forage.getItem(this.setting_key) || {}); let settingObj = utils.copyObj(this.cacheSettingObj); if (null === attribute) return settingObj; const value = settingObj[attribute]; return value ? "true" === value || "false" === value ? "true" === value.toLowerCase() : "string" != typeof value || "" === value.trim() || isNaN(Number(value)) ? value : Number(value) : defaultVal; } async saveSetting(settingObj) { settingObj ? await __privateMethod(this, _StorageManager_instances, setItem_fn).call(this, this.setting_key, settingObj) : show.error("设置对象为空"); } async saveSettingItem(key, value) { if (!key) { show.error("key 不能为空"); return; } let settingObj = await this.getSetting(); settingObj[key] = value; await this.saveSetting(settingObj); } async importData(jsonData) { await this.forage.clear(); const importPromises = []; for (const key in jsonData) { const value = jsonData[key], setPromise = __privateMethod(this, _StorageManager_instances, setItem_fn).call(this, key, value); importPromises.push(setPromise); } await Promise.all(importPromises); } async exportData() { const dataMap = {}; await this.forage.iterate(((value, key) => { dataMap[key] = value; })); if (0 === Object.keys(dataMap).length) throw new Error("没有可导出的数据"); return dataMap; } }; const apiUrl = "https://jdforrepam.com/api"; function buildSignature() { const curr = Math.floor(Date.now() / 1e3), stored_sign = localStorage.getItem("jhs_jdsignature"); if (stored_sign) { const parts = stored_sign.split("."); if (3 === parts.length) { if (curr - parseInt(parts[0]) <= 300) return stored_sign; } } const sign = `${curr}.lpw6vgqzsp.${md5(`${curr}71cf27bb3c0bcdf207b64abecddc970098c7421ee7203b9cdae54478478a199e7d5a6e1a57691123c1a931c057842fb73ba3b3c83bcd69c17ccf174081e3d8aa`)}`; localStorage.setItem("jhs_jdsignature", sign); return sign; } const javDbApi = { getReviews: async (movieId, pageNum = 1, pageSize = 20) => { let url = `${apiUrl}/v1/movies/${movieId}/reviews`, headers = { jdSignature: await buildSignature() }; return (await gmHttp.get(url, { page: pageNum, sort_by: "hotly", limit: pageSize }, headers)).data.reviews; }, searchMovie: async (keyword) => { let url = `${apiUrl}/v2/search`, headers = { "user-agent": "Dart/3.5 (dart:io)", "accept-language": "zh-TW", host: "jdforrepam.com", jdsignature: await buildSignature() }, params = { q: keyword, page: 1, type: "movie", limit: 1, movie_type: "all", from_recent: "false", movie_filter_by: "all", movie_sort_by: "relevance" }; return (await gmHttp.get(url, params, headers)).data.movies; }, getMovieDetail: async (movieId) => { let url = `${apiUrl}/v4/movies/${movieId}`, headers = { jdSignature: await buildSignature() }; const res = await gmHttp.get(url, null, headers); if (!res.data) { show.error("获取视频详情失败: " + res.message); throw new Error(res.message); } const movie = res.data.movie, preview_images = movie.preview_images, imgList = []; preview_images.forEach(((item) => { imgList.push(item.large_url.replace("https://tp.spfcas.com/rhe951l4q", "https://c0.jdbstatic.com")); })); return { movieId: movie.id, actors: movie.actors, duration: movie.duration, title: movie.origin_title, carNum: movie.number, score: movie.score, releaseDate: movie.release_date, watchedCount: movie.watched_count, imgList }; }, related: async (movieId, page = 1, limit = 20) => { let url = `${apiUrl}/v1/lists/related?movie_id=${movieId}&page=${page}&limit=${limit}`, headers = { jdSignature: await buildSignature() }; const res = await gmHttp.get(url, null, headers), dataList = []; res.data.lists.forEach(((item) => { dataList.push({ relatedId: item.id, name: item.name, movieCount: item.movies_count, collectionCount: item.collections_count, viewCount: item.views_count, createTime: utils.formatDate(item.created_at) }); })); return dataList; }, getMagnets: async (movieId) => { let url = `${apiUrl}/v1/movies/${movieId}/magnets`, headers = { jdSignature: await buildSignature() }; return (await gmHttp.get(url, null, headers)).data.magnets; }, playback: async (period = "daily", filter_by = "high_score") => { let url = `${apiUrl}/v1/rankings/playback?period=${period}&filter_by=${filter_by}`, headers = { jdSignature: await buildSignature() }; return (await gmHttp.get(url, null, headers)).data.movies; }, login: async (username, password) => { let url = `${apiUrl}/v1/sessions?username=${encodeURIComponent(username)}&password=${encodeURIComponent(password)}&device_uuid=04b9534d-5118-53de-9f87-2ddded77111e&device_name=iPhone&device_model=iPhone&platform=ios&system_version=17.4&app_version=official&app_version_number=1.9.29&app_channel=official`, headers = { "user-agent": "Dart/3.5 (dart:io)", "accept-language": "zh-TW", "content-type": "multipart/form-data; boundary=--dio-boundary-2210433284", jdsignature: await buildSignature() }; return await gmHttp.post(url, null, headers); }, top250: async (type = "all", type_value = "", page = 1, limit = 40) => { let url = `${apiUrl}/v1/movies/top?start_rank=1&type=${type}&type_value=${type_value}&ignore_watched=false&page=${page}&limit=${limit}`, headers = { "user-agent": "Dart/3.5 (dart:io)", "accept-language": "zh-TW", host: "jdforrepam.com", authorization: "Bearer " + localStorage.getItem("jhs_appAuthorization"), jdsignature: await buildSignature() }; return await gmHttp.get(url, null, headers); }, buildSignature, markDataListHtml: (movies) => { let moviesHtml = ""; movies.forEach(((movie) => { moviesHtml += `
`; })); return moviesHtml; } }; var _GM_openInTab = /* @__PURE__ */ (() => typeof GM_openInTab != "undefined" ? GM_openInTab : void 0)(); var _GM_xmlhttpRequest = /* @__PURE__ */ (() => typeof GM_xmlhttpRequest != "undefined" ? GM_xmlhttpRequest : void 0)(); class Utils { constructor() { __publicField2(this, "intervalContainer", {}); __publicField2(this, "mimeTypes", { txt: "text/plain", html: "text/html", css: "text/css", csv: "text/csv", json: "application/json", xml: "application/xml", jpg: "image/jpeg", jpeg: "image/jpeg", png: "image/png", gif: "image/gif", webp: "image/webp", svg: "image/svg+xml", pdf: "application/pdf", doc: "application/msword", docx: "application/vnd.openxmlformats-officedocument.wordprocessingml.document", xls: "application/vnd.ms-excel", xlsx: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", ppt: "application/vnd.ms-powerpoint", pptx: "application/vnd.openxmlformats-officedocument.presentationml.presentation", zip: "application/zip", rar: "application/x-rar-compressed", "7z": "application/x-7z-compressed", mp3: "audio/mpeg", wav: "audio/wav", mp4: "video/mp4", webm: "video/webm", ogg: "audio/ogg" }); __publicField2(this, "timers", /* @__PURE__ */ new Map()); __publicField2(this, "insertStyle", ((css) => { if (css) { -1 === css.indexOf(""); $("head").append(css); } })); __publicField2(this, "layerIndexStack", []); Utils.instance || (Utils.instance = this); return Utils.instance; } importResource(url) { let tag; if (url.indexOf("css") >= 0) { tag = document.createElement("link"); tag.setAttribute("rel", "stylesheet"); tag.href = url; } else { tag = document.createElement("script"); tag.setAttribute("type", "text/javascript"); tag.src = url; } document.documentElement.appendChild(tag); } openPage(url, title, shadeClose, event) { if (!url) throw new Error("未传入url"); shadeClose = shadeClose ?? true; if (event && (event.ctrlKey || event.metaKey)) { _GM_openInTab(url.includes("http") ? url : window.location.origin + url, { insert: 0 }); return; } let finalUrl = url; url.includes("/actors/") || url.includes("/star/") || (finalUrl = url.includes("?") ? `${url}&hideNav=1` : `${url}?hideNav=1`); layer.open({ type: 2, title, content: finalUrl, scrollbar: false, shadeClose, area: this.getResponsiveArea(["85%", "90%"]), isOutAnim: false, anim: -1, success: (layero, index) => { this.setupEscClose(index); } }); } _handleGlobalEscKey(e) { if ("Escape" !== e.key && 27 !== e.keyCode) return; if (0 === this.layerIndexStack.length) return; const topLayerIndex = this.layerIndexStack[this.layerIndexStack.length - 1], $layer = $(`#layui-layer${topLayerIndex}`); let viewerExists = false; if ($layer.find(".viewer-container").length > 0) viewerExists = true; else { const iframe = $layer.find(`#layui-layer-iframe${topLayerIndex}`)[0]; if (iframe && iframe.contentDocument) try { $(iframe.contentDocument).find(".viewer-container").length > 0 && (viewerExists = true); } catch (error) { clog.warn("无法检查跨域 iframe 内的 .viewer-container"); } } if (!viewerExists) { this.layerIndexStack.pop(); typeof layer !== "undefined" && layer.close(topLayerIndex); } } setupEscClose(layerIndex) { var _a2; if (!this._boundHandler) { this._boundHandler = this._handleGlobalEscKey.bind(this); $(document).off("keydown.globalLayerEsc"); $(document).on("keydown.globalLayerEsc", this._boundHandler); } -1 === this.layerIndexStack.indexOf(layerIndex) && this.layerIndexStack.push(layerIndex); const $iframe = $(`#layui-layer-iframe${layerIndex}`), eventNamespace = `keydown.layerEsc${layerIndex}`; try { const iframeDocument = null == (_a2 = $iframe[0]) ? void 0 : _a2.contentDocument; if (iframeDocument) { if ("yes" === $iframe.attr("data-esc-bound")) return; $(iframeDocument).off(eventNamespace); $(iframeDocument).on(eventNamespace, this._boundHandler); $iframe.attr("data-esc-bound", "yes"); } } catch (e) { clog.error("iframe监听失败 (跨域或未加载完毕):", e); } } closePage() { storageManager.getSetting("needClosePage", "yes").then(((needClosePage) => { if ("yes" !== needClosePage) return; parent.document.documentElement.style.overflow = "auto"; [".layui-layer-shade", ".layui-layer-move", ".layui-layer"].forEach((function (selector) { const elements = parent.document.querySelectorAll(selector); if (elements.length > 0) { const elementToRemove = elements.length > 1 ? elements[elements.length - 1] : elements[0]; elementToRemove.parentNode.removeChild(elementToRemove); } })); window.close(); })); } loopDetector(condition, after, detectInterval = 20, timeout = 1e4, runWhenTimeout = true) { const uuid = Math.random(), start = (/* @__PURE__ */ new Date()).getTime(), stopAndRun = (shouldRun) => { clearInterval(this.intervalContainer[uuid]); shouldRun && after && after(); delete this.intervalContainer[uuid]; }; this.intervalContainer[uuid] = setInterval((() => { const timeElapsed = (/* @__PURE__ */ new Date()).getTime() - start; condition() ? stopAndRun(true) : timeElapsed >= timeout && stopAndRun(runWhenTimeout); }), detectInterval); } rightClick(container, targetSelector, callback) { let containerElement; "string" == typeof container ? containerElement = document.querySelector(container) : container instanceof HTMLElement && (containerElement = container); if (!containerElement) { console.warn("rightClick(), 容器无效或未提供,将使用 document.body 进行全局委托。"); containerElement = document.body; } "string" == typeof targetSelector && "" !== targetSelector.trim() ? containerElement.addEventListener("contextmenu", ((event) => { const targetElement = event.target.closest(targetSelector); targetElement && callback(event, targetElement); })) : console.error("rightClick(), 必须提供有效的 targetSelector。"); } q(event, msg, fun, cancelFun) { let x, y; if (event) { x = event.clientX - 130; y = event.clientY - 120; } else { x = window.innerWidth / 2 - 120; y = window.innerHeight / 2 - 120; } let confirmIndex = layer.confirm(msg, { offset: [y, x], title: "提示", btn: ["确定", "取消"], shade: 0, zIndex: 999999991 }, (function () { fun && fun(); layer.close(confirmIndex); }), (function () { cancelFun && cancelFun(); })); } alert(event, msg, yesFun) { let offset; event && (offset = [event.clientX - 200, event.clientY - 120]); let confirmIndex = layer.alert(msg, { offset, shade: 0, zIndex: 999999991 }, (function () { yesFun && yesFun(); layer.close(confirmIndex); })); } getNowStr(dateSplitStr = "-", timeSplitStr = ":", dateString = null) { let now; now = dateString ? new Date(dateString) : /* @__PURE__ */ new Date(); const year = now.getFullYear(), month = String(now.getMonth() + 1).padStart(2, "0"), day = String(now.getDate()).padStart(2, "0"), hours = String(now.getHours()).padStart(2, "0"), minutes = String(now.getMinutes()).padStart(2, "0"), seconds = String(now.getSeconds()).padStart(2, "0"); return `${[year, month, day].join(dateSplitStr)} ${[hours, minutes, seconds].join(timeSplitStr)}`; } formatDate(date2, dateSplitStr = "-", timeSplitStr = ":") { let targetDate; if (date2 instanceof Date) targetDate = date2; else { if ("string" != typeof date2) throw new Error("Invalid date input: must be Date object or date string"); targetDate = new Date(date2); if (isNaN(targetDate.getTime())) throw new Error("Invalid date string"); } const year = targetDate.getFullYear(), month = String(targetDate.getMonth() + 1).padStart(2, "0"), day = String(targetDate.getDate()).padStart(2, "0"), hours = String(targetDate.getHours()).padStart(2, "0"), minutes = String(targetDate.getMinutes()).padStart(2, "0"), seconds = String(targetDate.getSeconds()).padStart(2, "0"); return `${[year, month, day].join(dateSplitStr)} ${[hours, minutes, seconds].join(timeSplitStr)}`; } getHourDifference(date1, date2) { const timestamp1 = date1.getTime(), timestamp2 = date2.getTime(), differenceInHours = Math.abs(timestamp2 - timestamp1) / 36e5; return Math.floor(differenceInHours); } download(data, fileName) { show.info("开始请求下载..."); const fileExtension = fileName.split(".").pop().toLowerCase(); let blob, mimeType = this.mimeTypes[fileExtension] || "application/octet-stream"; if (data instanceof Blob) blob = data; else if (data instanceof ArrayBuffer || ArrayBuffer.isView(data)) blob = new Blob([data], { type: mimeType }); else if ("string" == typeof data && data.startsWith("data:")) { const byteString = atob(data.split(",")[1]), arrayBuffer = new ArrayBuffer(byteString.length), uintArray = new Uint8Array(arrayBuffer); for (let i = 0; i < byteString.length; i++) uintArray[i] = byteString.charCodeAt(i); blob = new Blob([uintArray], { type: mimeType }); } else blob = new Blob([data], { type: mimeType }); const url = URL.createObjectURL(blob), a = document.createElement("a"); a.href = url; a.download = fileName; document.body.appendChild(a); a.click(); setTimeout((() => { document.body.removeChild(a); URL.revokeObjectURL(url); }), 100); } smoothScrollToTop(duration = 500) { return new Promise(((resolve) => { const start = performance.now(), startPosition = window.pageYOffset; window.requestAnimationFrame((function scrollStep(timestamp) { const elapsed = timestamp - start, progress2 = Math.min(elapsed / duration, 1), easeInOutCubic = progress2 < 0.5 ? 4 * progress2 * progress2 * progress2 : 1 - Math.pow(-2 * progress2 + 2, 3) / 2; window.scrollTo(0, startPosition * (1 - easeInOutCubic)); progress2 < 1 ? window.requestAnimationFrame(scrollStep) : resolve(); })); })); } simpleId() { return crypto.randomUUID().replace("-", ""); } isUrl(urlString) { try { new URL(urlString); return true; } catch (_) { return false; } } setHrefParam(key, val) { const newUrl = new URL(window.location.href); newUrl.searchParams.set(key, val); window.history.pushState({}, "", newUrl.toString()); } getUrlParam(url, key) { const searchString = url.split("?")[1]; if (!searchString) return null; const regex = new RegExp(`(?:^|&)${key}=([^&]*)`), match = searchString.match(regex); let value = ""; match && match[1] && (value = decodeURIComponent(match[1].replace(/\+/g, " "))); return value ? "true" === value || "false" === value ? "true" === value.toLowerCase() : "string" != typeof value || "" === value.trim() || isNaN(Number(value)) ? value : Number(value) : value; } reBuildSignature() { return javDbApi.buildSignature(); } getResponsiveArea(defaultArea) { const screenWidth = window.innerWidth; return screenWidth >= 1200 ? defaultArea || this.getDefaultArea() : screenWidth >= 768 ? ["70%", "90%"] : ["95%", "95%"]; } getDefaultArea() { return ["85%", "90%"]; } isMobile() { const userAgent = navigator.userAgent.toLowerCase(); return ["iphone", "ipod", "ipad", "android", "blackberry", "windows phone", "nokia", "webos", "opera mini", "mobile", "mobi", "tablet"].some(((keyword) => userAgent.includes(keyword))); } copyToClipboard(type, text) { navigator.clipboard.writeText(text).then((() => show.info(`${type}已复制到剪切板, ${text}`))).catch(((err) => console.error("复制失败: ", err))); } htmlTo$dom(html2) { const parser = new DOMParser(); return $(parser.parseFromString(html2, "text/html")); } addCookie(cookieStr, options = {}) { const {maxAge = 604800, path = "/", domain = "", secure = false, sameSite = "Lax"} = options; cookieStr.split(";").forEach(((cookie) => { const trimmed = cookie.trim(); if (trimmed) { const parts = trimmed.split("="); if (parts.length >= 2 && parts[0].trim()) { let cookieParts = [`${parts[0].trim()}=${parts.slice(1).join("=")}`]; maxAge > 0 && cookieParts.push(`max-age=${maxAge}`); cookieParts.push(`path=${path}`); domain && cookieParts.push(`domain=${domain}`); secure && cookieParts.push("Secure"); sameSite && cookieParts.push(`SameSite=${sameSite}`); console.log("document.cookie = '" + cookieParts.join("; ") + "'"); document.cookie = cookieParts.join("; "); } } })); } isHidden(el) { const element = el.jquery ? el[0] : el; return !element || (element.offsetWidth <= 0 && element.offsetHeight <= 0 || "none" === window.getComputedStyle(element).display); } time(label = "default", unit = "s", precision = 2) { if (this.timers.has(label)) { const timer = this.timers.get(label), elapsedTime = performance.now() - timer.startTime; let formattedTime, unitLabel; if ("s" === timer.unit) { formattedTime = (elapsedTime / 1e3).toFixed(timer.precision); unitLabel = "秒"; } else { formattedTime = elapsedTime.toFixed(timer.precision); unitLabel = "毫秒"; } this.timers.delete(label); return `${label}: ${formattedTime}${unitLabel}`; } this.timers.set(label, { startTime: performance.now(), unit, precision }); } sleep(ms = 1e3) { return new Promise(((resolve) => setTimeout(resolve, ms))); } genericSort(arr, sortRules, emptyLast = true) { if (!Array.isArray(arr) || 0 === arr.length) return []; if (!Array.isArray(sortRules) || 0 === sortRules.length) return [...arr]; const sortedArr = [...arr], safeDateConvert = (value) => { if (value instanceof Date) return value; if ("string" == typeof value) { const date2 = new Date(value); if (!isNaN(date2.getTime())) return date2; } return value; }; return sortedArr.sort(((a, b) => { for (const rule of sortRules) { const {key, order = "asc"} = rule; let valA = a, valB = b; if (null != key) if ("function" == typeof key) { valA = key(a); valB = key(b); } else { valA = a && "object" == typeof a ? a[key] : void 0; valB = b && "object" == typeof b ? b[key] : void 0; } const dateA = safeDateConvert(valA), dateB = safeDateConvert(valB); let comparison = 0; const aIsNull = null == valA, bIsNull = null == valB; if (aIsNull && bIsNull) return 0; if (aIsNull) return emptyLast ? 1 : -1; if (bIsNull) return emptyLast ? 1 : -1; comparison = dateA instanceof Date && dateB instanceof Date ? dateA.getTime() - dateB.getTime() : "number" == typeof valA && "number" == typeof valB ? valA - valB : "string" == typeof valA && "string" == typeof valB ? valA.localeCompare(valB) : String(valA).localeCompare(String(valB)); "desc" === order && (comparison *= -1); if (0 !== comparison) return comparison; } return 0; })); } async retry(fun, tryCount = 3) { let runCount = 0; for (; runCount < tryCount;) try { const result = await fun(); runCount > 0 && clog.debug(`[重试] 成功,共发起 ${runCount + 1} 次。`); return result; } catch (e) { let errorString = String(e); errorString.startsWith("Error: ") && (errorString = errorString.replace("Error: ", "")); if (errorString.includes("Just a moment") || errorString.includes("重定向") || errorString.toLowerCase().includes("404 page not found") || errorString.toLowerCase().includes("404 not found")) throw e; runCount++; if (runCount === tryCount) { clog.debug(`[重试] 达到最大重试次数 (${tryCount}),最终失败:`, e); throw e; } clog.debug(`[重试] 准备第 ${runCount + 1} 次重试, 错误信息: ${errorString}`); } } copyObj(data) { return JSON.parse(JSON.stringify(data)); } deepFreeze(obj) { if (null === obj || "object" != typeof obj || Object.isFrozen(obj)) return obj; const propNames = Object.getOwnPropertyNames(obj); for (const name2 of propNames) { const value = obj[name2]; value && "object" == typeof value && this.deepFreeze(value); } return Object.freeze(obj); } } class AsyncQueue { constructor() { this.queue = Promise.resolve(); } addTask(fun) { this.queue = this.queue.then((() => fun())).catch(((e) => { console.error("执行异步队列任务失败:", e); })); } async waitAllFinished() { return this.queue; } } class GmHttp { async get(url, params = {}, headers = {}, noRedirect) { return this.gmRequest("GET", url, null, params, headers, noRedirect); } post(url, data = {}, headers = {}) { headers = { "Content-Type": "application/json", ...headers }; let jsonData = JSON.stringify(data); return this.gmRequest("POST", url, jsonData, null, headers); } postForm(url, data = {}, headers = {}) { headers || (headers = {}); headers["Content-Type"] || (headers["Content-Type"] = "application/x-www-form-urlencoded"); let body = ""; data && Object.keys(data).length > 0 && (body = Object.entries(data).map((([key, value]) => `${key}=${value}`)).join("&")); return this.gmRequest("POST", url, body, null, headers); } postFileFormData(url, data = {}, headers = {}) { headers || (headers = {}); const boundary = `----WebKitFormBoundary${Math.random().toString(36).substring(2)}`; headers["Content-Type"] = `multipart/form-data; boundary=${boundary}`; let body = ""; data && Object.keys(data).length > 0 && (body = Object.entries(data).map((([key, value]) => `--${boundary}\r Content-Disposition: form-data; name="${key}"\r \r ${value}\r `)).join("")); body += `--${boundary}--`; return this.gmRequest("POST", url, body, null, headers); } async downloadFileInChunks(url, headers = {}) { const httpTimeout = await storageManager.getSetting("httpTimeout", 5e3), httpRetryCount = await storageManager.getSetting("httpRetryCount", 3); clog.log("正在获取文件大小..."); let fileSize, mimeType; try { const sizeResponse = await utils.retry((() => new Promise(((resolve, reject) => { _GM_xmlhttpRequest({ method: "GET", url, headers: { ...headers, Range: "bytes=0-0" }, timeout: httpTimeout, onload: resolve, onerror: (e) => reject(new Error("网络错误:无法获取文件大小")), ontimeout: () => reject(new Error("超时:获取文件大小")) }); }))), httpRetryCount); if (206 !== sizeResponse.status && 200 !== sizeResponse.status) throw new Error(`请求文件大小失败,状态码: ${sizeResponse.status}`); { const rangeHeader = sizeResponse.responseHeaders.match(/content-range:\s*bytes\s*\d+-\d+\/(\d+)/i), typeHeader = sizeResponse.responseHeaders.match(/content-type:\s*([^\s;]+)/i); if (rangeHeader && rangeHeader[1]) fileSize = parseInt(rangeHeader[1], 10); else { if (!sizeResponse.responseHeaders.match(/content-length:\s*(\d+)/i) || 200 !== sizeResponse.status) throw new Error("无法从响应头中获取文件总大小,服务器可能不支持 Range 请求。"); { const lengthHeader = sizeResponse.responseHeaders.match(/content-length:\s*(\d+)/i); fileSize = parseInt(lengthHeader[1], 10); clog.warn("服务器返回 200 状态码,可能不支持 Range 请求。将尝试完整下载。"); } } typeHeader && typeHeader[1] && (mimeType = typeHeader[1]); clog.log(`文件总大小:${(fileSize / 1024 / 1024).toFixed(2)} MB, MIME 类型: ${mimeType || "未知"}`); } } catch (e) { clog.error("获取文件大小失败:", e.message); throw e; } if (!fileSize || fileSize <= 0) throw new Error("获取到的文件大小无效或服务器拒绝提供大小信息。"); const numChunks = Math.ceil(fileSize / 1048576), chunkPromises = [], downloadedChunks = new Array(numChunks); clog.log(`文件将被分为 ${numChunks} 块进行下载 (每块约 ${1.toFixed(2)} MB)`); for (let i = 0; i < numChunks; i++) { const start = 1048576 * i, rangeHeader = `bytes=${start}-${Math.min(start + 1048576 - 1, fileSize - 1)}`, chunkPromise = await utils.retry((() => new Promise(((resolve, reject) => { const currentHeaders = { ...headers, Range: rangeHeader, Accept: "application/octet-stream" }; _GM_xmlhttpRequest({ method: "GET", url, headers: currentHeaders, timeout: httpTimeout, responseType: "arraybuffer", onload: (response) => { if (206 === response.status || 200 === response.status) if (response.response instanceof ArrayBuffer) { downloadedChunks[i] = response.response; clog.log(`成功下载第 ${i + 1}/${numChunks} 块 (${rangeHeader})`); resolve(); } else reject(new Error(`第 ${i + 1} 块响应不是 ArrayBuffer。`)); else reject(new Error(`第 ${i + 1} 块请求失败,状态码: ${response.status}`)); }, onerror: (error) => reject(new Error(`第 ${i + 1} 块网络错误: ${error.error}`)), ontimeout: () => reject(new Error(`第 ${i + 1} 块超时。`)) }); }))), httpRetryCount); chunkPromises.push(chunkPromise); } try { await Promise.all(chunkPromises); clog.log("所有分块下载完成,开始合并..."); } catch (e) { clog.error("分块下载过程中发生错误:", e.message); throw e; } const finalBlob = new Blob(downloadedChunks); finalBlob.size !== fileSize && clog.warn(`警告:合并后的 Blob 大小 (${finalBlob.size}) 与预期文件大小 (${fileSize}) 不匹配!`); return await finalBlob.text(); } async gmRequest(method, url, data = {}, params = {}, headers = {}, noRedirect = false) { if (params && Object.keys(params).length) { const queryString = new URLSearchParams(params).toString(); url += (url.includes("?") ? "&" : "?") + queryString; } const httpTimeout = await storageManager.getSetting("httpTimeout", 5e3), httpRetryCount = await storageManager.getSetting("httpRetryCount", 3); data || (data = void 0); return await utils.retry((() => new Promise(((resolve, reject) => { _GM_xmlhttpRequest({ method, url, headers, timeout: httpTimeout, data, onload: (response) => { try { noRedirect && response.finalUrl !== url && reject("请求被重定向了,URL是:" + response.finalUrl); if (response.status >= 200 && response.status < 300) if (response.responseText) try { resolve(JSON.parse(response.responseText)); } catch (e) { resolve(response.responseText); } else resolve(response.responseText || response); else { clog.error("请求失败,状态码:", response.status, url); if (response.responseText) try { const errorData = JSON.parse(response.responseText); reject(errorData); } catch { reject(new Error(response.responseText || `请求发生错误 ${response.status}`)); } else reject(new Error(`请求发生错误 ${response.status}`)); } } catch (e) { reject(e); } }, onerror: (error) => { clog.error("网络错误:", url); reject(new Error(error.error || "网络错误")); }, ontimeout: () => { reject(new Error("请求超时: " + url)); } }); }))), httpRetryCount); } } class PluginManager { constructor() { this.plugins = /* @__PURE__ */ new Map(); } register(pluginClass) { if ("function" != typeof pluginClass) throw new Error("插件必须是一个类"); const instance = new pluginClass(); instance.pluginManager = this; const lowerName = instance.getName(); if (this.plugins.has(lowerName)) throw new Error(`插件"${name}"已注册`); this.plugins.set(lowerName, instance); } getBean(name2) { return this.plugins.get(name2); } async processCss() { const failedCssLoads = (await Promise.allSettled(Array.from(this.plugins).map((async ([name2, instance]) => { try { if ("function" == typeof instance.initCss) { const css = await instance.initCss(); css && utils.insertStyle(css); return { name: name2, status: "fulfilled" }; } return { name: name2, status: "skipped" }; } catch (e) { console.error(`插件 ${name2} 加载 CSS 失败`, e); return { name: name2, status: "rejected", error: e }; } })))).filter(((r) => "rejected" === r.status)); failedCssLoads.length && console.error("以下插件的 CSS 加载失败:", failedCssLoads.map(((p) => p.value.name))); } async processPlugins() { const failedPlugins = (await Promise.allSettled(Array.from(this.plugins).map((async ([name2, instance]) => { try { if ("function" == typeof instance.handle) { await instance.handle(); return { name: name2, status: "fulfilled" }; } } catch (e) { clog.error(`插件 ${name2} 执行失败`, e); return { name: name2, status: "rejected", error: e }; } })))).filter(((r) => "rejected" === r.status)); failedPlugins.length && console.error("以下插件执行失败:", failedPlugins.map(((p) => p.value.name))); } } class BasePlugin { constructor() { __publicField2(this, "pluginManager", null); __publicField2(this, "settingSvg", ''); __publicField2(this, "editSvg", ''); __publicField2(this, "deleteSvg", ''); __publicField2(this, "checkSvg", ''); __publicField2(this, "actressSvg", ''); __publicField2(this, "newSvg", ''); __publicField2(this, "refreshSvg", ''); __publicField2(this, "blacklistSvg", ''); __publicField2(this, "removeSvg", ''); __publicField2(this, "copySvg", ''); __publicField2(this, "titleSvg", ''); __publicField2(this, "carNumSvg", ''); __publicField2(this, "downSvg", ''); __publicField2(this, "handleSvg", ''); __publicField2(this, "siteSvg", ''); __publicField2(this, "videoSvg", ''); __publicField2(this, "screenSvg", ''); __publicField2(this, "recoveryVideoSvg", ''); __publicField2(this, "markDeleteSvg", ''); } getName() { throw new Error(`${this.constructor.name} 未显示getName()`); } getBean(name2) { return this.pluginManager.getBean(name2); } async initCss() { return ""; } async handle() { } getPageInfo() { let carNum2, url, actress, actors, publishTime, currentHref2 = window.location.href; if (isJavDb) { carNum2 = $('a[title="複製番號"]').attr("data-clipboard-text"); url = currentHref2.split("?")[0].split("#")[0]; actress = $(".female").prev().map(((i, el) => $(el).text())).get().join(" "); actors = $(".male").prev().map(((i, el) => $(el).text())).get().join(" "); publishTime = $('strong:contains("日期:")').parent(".panel-block").find(".value").text().trim(); } if (isJavBus) { url = currentHref2.split("?")[0]; carNum2 = url.split("/").filter(Boolean).pop().replace(/_\d{4}-\d{2}-\d{2}$/, ""); actress = $('span[onmouseover*="star_"] a').map(((i, el) => $(el).text())).get().join(" "); actors = ""; publishTime = $('span.header:contains("發行日期:")').parent("p").text().trim().replace("發行日期:", "").trim(); } return { carNum: carNum2, url, actress, actors, publishTime }; } getActressId() { const match = currentHref.match(/\/actors\/([^/?]+)/); return match && match.length > 1 ? match[1] : null; } getActressPageInfo() { let currentHref2 = window.location.href; if (!currentHref2.includes("/actors/") && !currentHref2.includes("/star/")) throw new Error("接口调用错误, 非演员详情页"); let nameList = [], $actor = isJavDb ? $(".actor-section-name") : $(".avatar-box .photo-info .pb10"); $actor.length && $actor.text().trim().split(",").forEach(((name2) => { nameList.push(name2.trim()); })); let $sectionMeta = $(".section-meta:not(:contains('影片'))"); $sectionMeta.length && $sectionMeta.text().trim().split(",").forEach(((name2) => { nameList.push(name2.trim()); })); let role = $(".section-meta:contains('男優')").length > 0 ? "actor" : "actress", movieType = "censored"; nameList.some(((n) => n.includes("無碼"))) && (movieType = "uncensored"); currentHref2.includes("uncensored") && (movieType = "uncensored"); let blacklistUrl = null, starId = null; const urlObj = new URL(currentHref2); if (isJavDb) { starId = urlObj.pathname.split("/").filter(((segment) => "" !== segment.trim())).pop(); const params = urlObj.searchParams; params.delete("sort_type"); params.delete("page"); blacklistUrl = urlObj.toString(); } else if (isJavBus) { const splitStr = "/star/", parts = currentHref2.split(splitStr); if (parts.length < 2) throw new Error("提取演员url失败"); const host = parts[0]; starId = parts[1].split("/")[0]; blacklistUrl = host + splitStr + starId; } return { starId, name: nameList[0], allName: nameList, role, movieType, blacklistUrl }; } getSelector(type) { const key = type || (isJavDb ? "javdb" : isJavBus ? "javbus" : null), selectors = { javdb: { boxSelector: ".movie-list", itemSelector: ".movie-list .item", coverImgSelector: ".cover img", requestDomItemSelector: ".movie-list .item", nextPageSelector: ".pagination-next" }, javbus: { boxSelector: ".masonry", itemSelector: ".masonry .item", coverImgSelector: ".masonry .movie-box .photo-frame img", requestDomItemSelector: "#waterfall .item", nextPageSelector: "#next" } }; if (!key || !selectors[key]) throw new Error("类型错误: 无法确定选择器类型 (JavDb 或 JavBus)"); return selectors[key]; } parseMovieId(href) { return href.split("/").pop().split(/[?#]/)[0]; } getBoxCarInfo($box2) { var _a2, _b, _c; const $aLink = $box2.find("a"), url = $aLink.attr("href"); let carNum2 = null, title = null, publishTime = null; const $videoTitleEle = $box2.find(".video-title"); if ($videoTitleEle.length > 0) { const $strongEle = $videoTitleEle.find("strong"); $strongEle.length > 0 && (carNum2 = $strongEle.text().trim()); title = null == (_a2 = $aLink.attr("title")) ? void 0 : _a2.trim(); if (!title) { const fullTitleText = $videoTitleEle.text().trim(); title = carNum2 && fullTitleText.includes(carNum2) ? fullTitleText.replace(carNum2, "").trim() : fullTitleText; } publishTime = $box2.find(".meta").text().trim(); } if (!carNum2) { const $imgEle = $box2.find("img"); $imgEle.length > 0 && (title = (null == (_b = $imgEle.attr("title")) ? void 0 : _b.trim()) || (null == (_c = $imgEle.attr("data-title")) ? void 0 : _c.trim())); const dateElements = $box2.find("date").map(((i, el) => $(el).text().trim())).get(), isDate = (s) => /^\d{4}-\d{1,2}-\d{1,2}$/.test(s); publishTime = dateElements.find(isDate) || null; carNum2 = dateElements.find(((i) => !isDate(i))) || null; } if (!carNum2) { return null; } return { carNum: carNum2, url: url || "", aHref: url || "", title: title || "", publishTime: publishTime || "" }; } getBoxCarInfoList($boxList = null) { $boxList || ($boxList = $(this.getSelector().itemSelector)); if (0 === $boxList.length) { clog.error("获取当前列表页所有item的番号信息失败!"); return []; } const results = []; $boxList.each(((index, element) => { const $box2 = $(element); try { const carInfo = this.getBoxCarInfo($box2); results.push(carInfo); } catch (error) { clog.error("[getBoxCarInfoList] 提取单个 boxCar 信息失败:", error.message, "元素索引:", index); } })); return results; } checkDuplicateCarNumbers(currentList, newList) { if (!isJavDb) return false; if (!currentList || 0 === currentList.length || !newList || 0 === newList.length) return false; const currentCarNums = new Set(currentList.map(((item) => item.carNum)).filter(((n) => n))); if (0 === currentCarNums.size) return false; let consecutiveDuplicates = 0; for (let i = 0; i < newList.length; i++) { const newCarNum = newList[i] ? newList[i].carNum : null; if (newCarNum && currentCarNums.has(newCarNum)) { consecutiveDuplicates++; if (consecutiveDuplicates >= 2) { clog.warn("警告: 检测到连续番号信息重复, 该类别可能已被限制页码。"); return true; } } else consecutiveDuplicates = 0; } return false; } } class CoreFeature { constructor(table) { this.table = table; } ////////////////////////////////////////// /////////////// DataLoad ///////////////// ////////////////////////////////////////// reloadData(data, silent, columnsChanged) { return this.table.dataLoader.load(data, void 0, void 0, void 0, silent, columnsChanged); } ////////////////////////////////////////// ///////////// Localization /////////////// ////////////////////////////////////////// langText() { return this.table.modules.localize.getText(...arguments); } langBind() { return this.table.modules.localize.bind(...arguments); } langLocale() { return this.table.modules.localize.getLocale(...arguments); } ////////////////////////////////////////// ////////// Inter Table Comms ///////////// ////////////////////////////////////////// commsConnections() { return this.table.modules.comms.getConnections(...arguments); } commsSend() { return this.table.modules.comms.send(...arguments); } ////////////////////////////////////////// //////////////// Layout ///////////////// ////////////////////////////////////////// /** @returns {("fitData" | "fitDataFill" | "fitDataTable" | "fitDataStretch" | "fitColumns")} */ layoutMode() { return this.table.modules.layout.getMode(); } layoutRefresh(force) { return this.table.modules.layout.layout(force); } ////////////////////////////////////////// /////////////// Event Bus //////////////// ////////////////////////////////////////// subscribe() { return this.table.eventBus.subscribe(...arguments); } unsubscribe() { return this.table.eventBus.unsubscribe(...arguments); } subscribed(key) { return this.table.eventBus.subscribed(key); } subscriptionChange() { return this.table.eventBus.subscriptionChange(...arguments); } dispatch() { return this.table.eventBus.dispatch(...arguments); } chain() { return this.table.eventBus.chain(...arguments); } confirm() { return this.table.eventBus.confirm(...arguments); } dispatchExternal() { return this.table.externalEvents.dispatch(...arguments); } subscribedExternal(key) { return this.table.externalEvents.subscribed(key); } subscriptionChangeExternal() { return this.table.externalEvents.subscriptionChange(...arguments); } ////////////////////////////////////////// //////////////// Options ///////////////// ////////////////////////////////////////// options(key) { return this.table.options[key]; } setOption(key, value) { if (typeof value !== "undefined") { this.table.options[key] = value; } return this.table.options[key]; } ////////////////////////////////////////// /////////// Deprecation Checks /////////// ////////////////////////////////////////// deprecationCheck(oldOption, newOption, convert) { return this.table.deprecationAdvisor.check(oldOption, newOption, convert); } deprecationCheckMsg(oldOption, msg) { return this.table.deprecationAdvisor.checkMsg(oldOption, msg); } deprecationMsg(msg) { return this.table.deprecationAdvisor.msg(msg); } ////////////////////////////////////////// //////////////// Modules ///////////////// ////////////////////////////////////////// module(key) { return this.table.module(key); } } class Helpers { static elVisible(el) { return !(el.offsetWidth <= 0 && el.offsetHeight <= 0); } static elOffset(el) { var box = el.getBoundingClientRect(); return { top: box.top + window.pageYOffset - document.documentElement.clientTop, left: box.left + window.pageXOffset - document.documentElement.clientLeft }; } static retrieveNestedData(separator, field, data) { var structure = separator ? field.split(separator) : [field], length = structure.length, output; for (let i = 0; i < length; i++) { data = data[structure[i]]; output = data; if (!data) { break; } } return output; } static deepClone(obj, clone, list2 = []) { var objectProto = {}.__proto__, arrayProto = [].__proto__; if (!clone) { clone = Object.assign(Array.isArray(obj) ? [] : {}, obj); } for (var i in obj) { let subject = obj[i], match, copy; if (subject != null && typeof subject === "object" && (subject.__proto__ === objectProto || subject.__proto__ === arrayProto)) { match = list2.findIndex((item) => { return item.subject === subject; }); if (match > -1) { clone[i] = list2[match].copy; } else { copy = Object.assign(Array.isArray(subject) ? [] : {}, subject); list2.unshift({subject, copy}); clone[i] = this.deepClone(subject, copy, list2); } } } return clone; } } let Popup$1 = class Popup extends CoreFeature { constructor(table, element, parent2) { super(table); this.element = element; this.container = this._lookupContainer(); this.parent = parent2; this.reversedX = false; this.childPopup = null; this.blurable = false; this.blurCallback = null; this.blurEventsBound = false; this.renderedCallback = null; this.visible = false; this.hideable = true; this.element.classList.add("tabulator-popup-container"); this.blurEvent = this.hide.bind(this, false); this.escEvent = this._escapeCheck.bind(this); this.destroyBinding = this.tableDestroyed.bind(this); this.destroyed = false; } tableDestroyed() { this.destroyed = true; this.hide(true); } _lookupContainer() { var container = this.table.options.popupContainer; if (typeof container === "string") { container = document.querySelector(container); if (!container) { console.warn("Menu Error - no container element found matching selector:", this.table.options.popupContainer, "(defaulting to document body)"); } } else if (container === true) { container = this.table.element; } if (container && !this._checkContainerIsParent(container)) { container = false; console.warn("Menu Error - container element does not contain this table:", this.table.options.popupContainer, "(defaulting to document body)"); } if (!container) { container = document.body; } return container; } _checkContainerIsParent(container, element = this.table.element) { if (container === element) { return true; } else { return element.parentNode ? this._checkContainerIsParent(container, element.parentNode) : false; } } renderCallback(callback) { this.renderedCallback = callback; } containerEventCoords(e) { var touch = !(e instanceof MouseEvent); var x = touch ? e.touches[0].pageX : e.pageX; var y = touch ? e.touches[0].pageY : e.pageY; if (this.container !== document.body) { let parentOffset = Helpers.elOffset(this.container); x -= parentOffset.left; y -= parentOffset.top; } return {x, y}; } elementPositionCoords(element, position = "right") { var offset = Helpers.elOffset(element), containerOffset, x, y; if (this.container !== document.body) { containerOffset = Helpers.elOffset(this.container); offset.left -= containerOffset.left; offset.top -= containerOffset.top; } switch (position) { case "right": x = offset.left + element.offsetWidth; y = offset.top - 1; break; case "bottom": x = offset.left; y = offset.top + element.offsetHeight; break; case "left": x = offset.left; y = offset.top - 1; break; case "top": x = offset.left; y = offset.top; break; case "center": x = offset.left + element.offsetWidth / 2; y = offset.top + element.offsetHeight / 2; break; } return {x, y, offset}; } show(origin, position) { var x, y, parentEl, parentOffset, coords; if (this.destroyed || this.table.destroyed) { return this; } if (origin instanceof HTMLElement) { parentEl = origin; coords = this.elementPositionCoords(origin, position); parentOffset = coords.offset; x = coords.x; y = coords.y; } else if (typeof origin === "number") { parentOffset = {top: 0, left: 0}; x = origin; y = position; } else { coords = this.containerEventCoords(origin); x = coords.x; y = coords.y; this.reversedX = false; } this.element.style.top = y + "px"; this.element.style.left = x + "px"; this.container.appendChild(this.element); if (typeof this.renderedCallback === "function") { this.renderedCallback(); } this._fitToScreen(x, y, parentEl, parentOffset, position); this.visible = true; this.subscribe("table-destroy", this.destroyBinding); this.element.addEventListener("mousedown", (e) => { e.stopPropagation(); }); return this; } _fitToScreen(x, y, parentEl, parentOffset, position) { var scrollTop = this.container === document.body ? document.documentElement.scrollTop : this.container.scrollTop; if (x + this.element.offsetWidth >= this.container.offsetWidth || this.reversedX) { this.element.style.left = ""; if (parentEl) { this.element.style.right = this.container.offsetWidth - parentOffset.left + "px"; } else { this.element.style.right = this.container.offsetWidth - x + "px"; } this.reversedX = true; } let offsetHeight = Math.max(this.container.offsetHeight, scrollTop ? this.container.scrollHeight : 0); if (y + this.element.offsetHeight > offsetHeight) { if (parentEl) { switch (position) { case "bottom": this.element.style.top = parseInt(this.element.style.top) - this.element.offsetHeight - parentEl.offsetHeight - 1 + "px"; break; default: this.element.style.top = parseInt(this.element.style.top) - this.element.offsetHeight + parentEl.offsetHeight + 1 + "px"; } } else { let menuHeight = this.element.offsetHeight; if (menuHeight > offsetHeight) { this.element.style.top = "0px"; this.element.style.height = offsetHeight + "px"; } else { let newTop = y - menuHeight; if (newTop < 0) { newTop = offsetHeight - menuHeight; } this.element.style.top = newTop + "px"; } } } } isVisible() { return this.visible; } hideOnBlur(callback) { this.blurable = true; if (this.visible) { setTimeout(() => { if (this.visible) { this.table.rowManager.element.addEventListener("scroll", this.blurEvent); this.subscribe("cell-editing", this.blurEvent); document.body.addEventListener("click", this.blurEvent); document.body.addEventListener("contextmenu", this.blurEvent); document.body.addEventListener("mousedown", this.blurEvent); window.addEventListener("resize", this.blurEvent); document.body.addEventListener("keydown", this.escEvent); this.blurEventsBound = true; } }, 100); this.blurCallback = callback; } return this; } /** @param {KeyboardEvent} e */ _escapeCheck(e) { if (e.key == 27) { this.hide(); } } blockHide() { this.hideable = false; } restoreHide() { this.hideable = true; } hide(silent = false) { if (this.visible && this.hideable) { if (this.blurable && this.blurEventsBound) { document.body.removeEventListener("keydown", this.escEvent); document.body.removeEventListener("click", this.blurEvent); document.body.removeEventListener("contextmenu", this.blurEvent); document.body.removeEventListener("mousedown", this.blurEvent); window.removeEventListener("resize", this.blurEvent); this.table.rowManager.element.removeEventListener("scroll", this.blurEvent); this.unsubscribe("cell-editing", this.blurEvent); this.blurEventsBound = false; } if (this.childPopup) { this.childPopup.hide(); } if (this.parent) { this.parent.childPopup = null; } if (this.element.parentNode) { this.element.parentNode.removeChild(this.element); } this.visible = false; if (this.blurCallback && !silent) { this.blurCallback(); } this.unsubscribe("table-destroy", this.destroyBinding); } return this; } child(element) { if (this.childPopup) { this.childPopup.hide(); } this.childPopup = new Popup(this.table, element, this); return this.childPopup; } }; class Module extends CoreFeature { constructor(table, name2) { super(table); this._handler = null; } initialize() { } /////////////////////////////////// ////// Options Registration /////// /////////////////////////////////// registerTableOption(key, value) { this.table.optionsList.register(key, value); } registerColumnOption(key, value) { this.table.columnManager.optionsList.register(key, value); } /////////////////////////////////// /// Public Function Registration /// /////////////////////////////////// registerTableFunction(name2, func) { if (typeof this.table[name2] === "undefined") { this.table[name2] = (...args) => { this.table.initGuard(name2); return func(...args); }; } else { console.warn("Unable to bind table function, name already in use", name2); } } registerComponentFunction(component, func, handler) { return this.table.componentFunctionBinder.bind(component, func, handler); } /////////////////////////////////// ////////// Data Pipeline ////////// /////////////////////////////////// registerDataHandler(handler, priority) { this.table.rowManager.registerDataPipelineHandler(handler, priority); this._handler = handler; } registerDisplayHandler(handler, priority) { this.table.rowManager.registerDisplayPipelineHandler(handler, priority); this._handler = handler; } displayRows(adjust) { var index = this.table.rowManager.displayRows.length - 1, lookupIndex; if (this._handler) { lookupIndex = this.table.rowManager.displayPipeline.findIndex((item) => { return item.handler === this._handler; }); if (lookupIndex > -1) { index = lookupIndex; } } if (adjust) { index = index + adjust; } if (this._handler) { if (index > -1) { return this.table.rowManager.getDisplayRows(index); } else { return this.activeRows(); } } } activeRows() { return this.table.rowManager.activeRows; } refreshData(renderInPosition, handler) { if (!handler) { handler = this._handler; } if (handler) { this.table.rowManager.refreshActiveData(handler, false, renderInPosition); } } /////////////////////////////////// //////// Footer Management //////// /////////////////////////////////// footerAppend(element) { return this.table.footerManager.append(element); } footerPrepend(element) { return this.table.footerManager.prepend(element); } footerRemove(element) { return this.table.footerManager.remove(element); } /////////////////////////////////// //////// Popups Management //////// /////////////////////////////////// popup(menuEl, menuContainer) { return new Popup$1(this.table, menuEl, menuContainer); } /////////////////////////////////// //////// Alert Management //////// /////////////////////////////////// alert(content, type) { return this.table.alertManager.alert(content, type); } clearAlert() { return this.table.alertManager.clear(); } } var defaultAccessors = { rownum: function (value, data, type, params, column, row) { return row.getPosition(); } }; const _Accessor = class _Accessor extends Module { constructor(table) { super(table); this.allowedTypes = ["", "data", "download", "clipboard", "print", "htmlOutput"]; this.registerColumnOption("accessor"); this.registerColumnOption("accessorParams"); this.registerColumnOption("accessorData"); this.registerColumnOption("accessorDataParams"); this.registerColumnOption("accessorDownload"); this.registerColumnOption("accessorDownloadParams"); this.registerColumnOption("accessorClipboard"); this.registerColumnOption("accessorClipboardParams"); this.registerColumnOption("accessorPrint"); this.registerColumnOption("accessorPrintParams"); this.registerColumnOption("accessorHtmlOutput"); this.registerColumnOption("accessorHtmlOutputParams"); } initialize() { this.subscribe("column-layout", this.initializeColumn.bind(this)); this.subscribe("row-data-retrieve", this.transformRow.bind(this)); } //initialize column accessor initializeColumn(column) { var match = false, config = {}; this.allowedTypes.forEach((type) => { var key = "accessor" + (type.charAt(0).toUpperCase() + type.slice(1)), accessor; if (column.definition[key]) { accessor = this.lookupAccessor(column.definition[key]); if (accessor) { match = true; config[key] = { accessor, params: column.definition[key + "Params"] || {} }; } } }); if (match) { column.modules.accessor = config; } } lookupAccessor(value) { var accessor = false; switch (typeof value) { case "string": if (_Accessor.accessors[value]) { accessor = _Accessor.accessors[value]; } else { console.warn("Accessor Error - No such accessor found, ignoring: ", value); } break; case "function": accessor = value; break; } return accessor; } //apply accessor to row transformRow(row, type) { var key = "accessor" + (type.charAt(0).toUpperCase() + type.slice(1)), rowComponent = row.getComponent(); var data = Helpers.deepClone(row.data || {}); this.table.columnManager.traverse(function (column) { var value, accessor, params, colComponent; if (column.modules.accessor) { accessor = column.modules.accessor[key] || column.modules.accessor.accessor || false; if (accessor) { value = column.getFieldValue(data); if (value != "undefined") { colComponent = column.getComponent(); params = typeof accessor.params === "function" ? accessor.params(value, data, type, colComponent, rowComponent) : accessor.params; column.setFieldValue(data, accessor.accessor(value, data, type, params, colComponent, rowComponent)); } } } }); return data; } }; __publicField(_Accessor, "moduleName", "accessor"); //load defaults __publicField(_Accessor, "accessors", defaultAccessors); let Accessor = _Accessor; var defaultConfig = { method: "GET" }; function generateParamsList$1(data, prefix) { var output = []; prefix = prefix || ""; if (Array.isArray(data)) { data.forEach((item, i) => { output = output.concat(generateParamsList$1(item, prefix ? prefix + "[" + i + "]" : i)); }); } else if (typeof data === "object") { for (var key in data) { output = output.concat(generateParamsList$1(data[key], prefix ? prefix + "[" + key + "]" : key)); } } else { output.push({key: prefix, value: data}); } return output; } function serializeParams(params) { var output = generateParamsList$1(params), encoded = []; output.forEach(function (item) { encoded.push(encodeURIComponent(item.key) + "=" + encodeURIComponent(item.value)); }); return encoded.join("&"); } function urlBuilder(url, config, params) { if (url) { if (params && Object.keys(params).length) { if (!config.method || config.method.toLowerCase() == "get") { config.method = "get"; url += (url.includes("?") ? "&" : "?") + serializeParams(params); } } } return url; } function defaultLoaderPromise(url, config, params) { var contentType; return new Promise((resolve, reject) => { url = this.urlGenerator.call(this.table, url, config, params); if (config.method.toUpperCase() != "GET") { contentType = typeof this.table.options.ajaxContentType === "object" ? this.table.options.ajaxContentType : this.contentTypeFormatters[this.table.options.ajaxContentType]; if (contentType) { for (var key in contentType.headers) { if (!config.headers) { config.headers = {}; } if (typeof config.headers[key] === "undefined") { config.headers[key] = contentType.headers[key]; } } config.body = contentType.body.call(this, url, config, params); } else { console.warn("Ajax Error - Invalid ajaxContentType value:", this.table.options.ajaxContentType); } } if (url) { if (typeof config.headers === "undefined") { config.headers = {}; } if (typeof config.headers.Accept === "undefined") { config.headers.Accept = "application/json"; } if (typeof config.headers["X-Requested-With"] === "undefined") { config.headers["X-Requested-With"] = "XMLHttpRequest"; } if (typeof config.mode === "undefined") { config.mode = "cors"; } if (config.mode == "cors") { if (typeof config.headers["Origin"] === "undefined") { config.headers["Origin"] = window.location.origin; } if (typeof config.credentials === "undefined") { config.credentials = "same-origin"; } } else { if (typeof config.credentials === "undefined") { config.credentials = "include"; } } fetch(url, config).then((response) => { if (response.ok) { response.json().then((data) => { resolve(data); }).catch((error) => { reject(error); console.warn("Ajax Load Error - Invalid JSON returned", error); }); } else { console.error("Ajax Load Error - Connection Error: " + response.status, response.statusText); reject(response); } }).catch((error) => { console.error("Ajax Load Error - Connection Error: ", error); reject(error); }); } else { console.warn("Ajax Load Error - No URL Set"); resolve([]); } }); } function generateParamsList(data, prefix) { var output = []; prefix = prefix || ""; if (Array.isArray(data)) { data.forEach((item, i) => { output = output.concat(generateParamsList(item, prefix ? prefix + "[" + i + "]" : i)); }); } else if (typeof data === "object") { for (var key in data) { output = output.concat(generateParamsList(data[key], prefix ? prefix + "[" + key + "]" : key)); } } else { output.push({key: prefix, value: data}); } return output; } var defaultContentTypeFormatters = { "json": { headers: { "Content-Type": "application/json" }, body: function (url, config, params) { return JSON.stringify(params); } }, "form": { headers: {}, body: function (url, config, params) { var output = generateParamsList(params), form = new FormData(); output.forEach(function (item) { form.append(item.key, item.value); }); return form; } } }; const _Ajax = class _Ajax extends Module { constructor(table) { super(table); this.config = {}; this.url = ""; this.urlGenerator = false; this.params = false; this.loaderPromise = false; this.registerTableOption("ajaxURL", false); this.registerTableOption("ajaxURLGenerator", false); this.registerTableOption("ajaxParams", {}); this.registerTableOption("ajaxConfig", "get"); this.registerTableOption("ajaxContentType", "form"); this.registerTableOption("ajaxRequestFunc", false); this.registerTableOption("ajaxRequesting", function () { }); this.registerTableOption("ajaxResponse", false); this.contentTypeFormatters = _Ajax.contentTypeFormatters; } //initialize setup options initialize() { this.loaderPromise = this.table.options.ajaxRequestFunc || _Ajax.defaultLoaderPromise; this.urlGenerator = this.table.options.ajaxURLGenerator || _Ajax.defaultURLGenerator; if (this.table.options.ajaxURL) { this.setUrl(this.table.options.ajaxURL); } this.setDefaultConfig(this.table.options.ajaxConfig); this.registerTableFunction("getAjaxUrl", this.getUrl.bind(this)); this.subscribe("data-loading", this.requestDataCheck.bind(this)); this.subscribe("data-params", this.requestParams.bind(this)); this.subscribe("data-load", this.requestData.bind(this)); } requestParams(data, config, silent, params) { var ajaxParams = this.table.options.ajaxParams; if (ajaxParams) { if (typeof ajaxParams === "function") { ajaxParams = ajaxParams.call(this.table); } params = Object.assign(Object.assign({}, ajaxParams), params); } return params; } requestDataCheck(data, params, config, silent) { return !!(!data && this.url || typeof data === "string"); } requestData(url, params, config, silent, previousData) { var ajaxConfig; if (!previousData && this.requestDataCheck(url)) { if (url) { this.setUrl(url); } ajaxConfig = this.generateConfig(config); return this.sendRequest(this.url, params, ajaxConfig); } else { return previousData; } } setDefaultConfig(config = {}) { this.config = Object.assign({}, _Ajax.defaultConfig); if (typeof config == "string") { this.config.method = config; } else { Object.assign(this.config, config); } } //load config object generateConfig(config = {}) { var ajaxConfig = Object.assign({}, this.config); if (typeof config == "string") { ajaxConfig.method = config; } else { Object.assign(ajaxConfig, config); } return ajaxConfig; } //set request url setUrl(url) { this.url = url; } //get request url getUrl() { return this.url; } //send ajax request sendRequest(url, params, config) { if (this.table.options.ajaxRequesting.call(this.table, url, params) !== false) { return this.loaderPromise(url, config, params).then((data) => { if (this.table.options.ajaxResponse) { data = this.table.options.ajaxResponse.call(this.table, url, params, data); } return data; }); } else { return Promise.reject(); } } }; __publicField(_Ajax, "moduleName", "ajax"); //load defaults __publicField(_Ajax, "defaultConfig", defaultConfig); __publicField(_Ajax, "defaultURLGenerator", urlBuilder); __publicField(_Ajax, "defaultLoaderPromise", defaultLoaderPromise); __publicField(_Ajax, "contentTypeFormatters", defaultContentTypeFormatters); let Ajax = _Ajax; var defaultPasteActions = { replace: function (data) { return this.table.setData(data); }, update: function (data) { return this.table.updateOrAddData(data); }, insert: function (data) { return this.table.addData(data); } }; var defaultPasteParsers = { table: function (clipboard) { var data = [], headerFindSuccess = true, columns = this.table.columnManager.columns, columnMap = [], rows2 = []; clipboard = clipboard.split("\n"); clipboard.forEach(function (row) { data.push(row.split(" ")); }); if (data.length && !(data.length === 1 && data[0].length < 2)) { data[0].forEach(function (value) { var column = columns.find(function (column2) { return value && column2.definition.title && value.trim() && column2.definition.title.trim() === value.trim(); }); if (column) { columnMap.push(column); } else { headerFindSuccess = false; } }); if (!headerFindSuccess) { headerFindSuccess = true; columnMap = []; data[0].forEach(function (value) { var column = columns.find(function (column2) { return value && column2.field && value.trim() && column2.field.trim() === value.trim(); }); if (column) { columnMap.push(column); } else { headerFindSuccess = false; } }); if (!headerFindSuccess) { columnMap = this.table.columnManager.columnsByIndex; } } if (headerFindSuccess) { data.shift(); } data.forEach(function (item) { var row = {}; item.forEach(function (value, i) { if (columnMap[i]) { row[columnMap[i].field] = value; } }); rows2.push(row); }); return rows2; } else { return false; } } }; var bindings$2 = { copyToClipboard: ["ctrl + 67", "meta + 67"] }; var actions$2 = { copyToClipboard: function (e) { if (!this.table.modules.edit.currentCell) { if (this.table.modExists("clipboard", true)) { this.table.modules.clipboard.copy(false, true); } } } }; var extensions$4 = { keybindings: { bindings: bindings$2, actions: actions$2 } }; const _Clipboard = class _Clipboard extends Module { constructor(table) { super(table); this.mode = true; this.pasteParser = function () { }; this.pasteAction = function () { }; this.customSelection = false; this.rowRange = false; this.blocked = true; this.registerTableOption("clipboard", false); this.registerTableOption("clipboardCopyStyled", true); this.registerTableOption("clipboardCopyConfig", false); this.registerTableOption("clipboardCopyFormatter", false); this.registerTableOption("clipboardCopyRowRange", "active"); this.registerTableOption("clipboardPasteParser", "table"); this.registerTableOption("clipboardPasteAction", "insert"); this.registerColumnOption("clipboard"); this.registerColumnOption("titleClipboard"); } initialize() { this.mode = this.table.options.clipboard; this.rowRange = this.table.options.clipboardCopyRowRange; if (this.mode === true || this.mode === "copy") { this.table.element.addEventListener("copy", (e) => { var plain, html2, list2; if (!this.blocked) { e.preventDefault(); if (this.customSelection) { plain = this.customSelection; if (this.table.options.clipboardCopyFormatter) { plain = this.table.options.clipboardCopyFormatter("plain", plain); } } else { list2 = this.table.modules.export.generateExportList(this.table.options.clipboardCopyConfig, this.table.options.clipboardCopyStyled, this.rowRange, "clipboard"); html2 = this.table.modules.export.generateHTMLTable(list2); plain = html2 ? this.generatePlainContent(list2) : ""; if (this.table.options.clipboardCopyFormatter) { plain = this.table.options.clipboardCopyFormatter("plain", plain); html2 = this.table.options.clipboardCopyFormatter("html", html2); } } if (window.clipboardData && window.clipboardData.setData) { window.clipboardData.setData("Text", plain); } else if (e.clipboardData && e.clipboardData.setData) { e.clipboardData.setData("text/plain", plain); if (html2) { e.clipboardData.setData("text/html", html2); } } else if (e.originalEvent && e.originalEvent.clipboardData.setData) { e.originalEvent.clipboardData.setData("text/plain", plain); if (html2) { e.originalEvent.clipboardData.setData("text/html", html2); } } this.dispatchExternal("clipboardCopied", plain, html2); this.reset(); } }); } if (this.mode === true || this.mode === "paste") { this.table.element.addEventListener("paste", (e) => { this.paste(e); }); } this.setPasteParser(this.table.options.clipboardPasteParser); this.setPasteAction(this.table.options.clipboardPasteAction); this.registerTableFunction("copyToClipboard", this.copy.bind(this)); } reset() { this.blocked = true; this.customSelection = false; } generatePlainContent(list2) { var output = []; list2.forEach((row) => { var rowData = []; row.columns.forEach((col) => { var value = ""; if (col) { if (row.type === "group") { col.value = col.component.getKey(); } if (col.value === null) { value = ""; } else { switch (typeof col.value) { case "object": value = JSON.stringify(col.value); break; case "undefined": value = ""; break; default: value = col.value; } } } rowData.push(value); }); output.push(rowData.join(" ")); }); return output.join("\n"); } copy(range2, internal) { var sel, textRange; this.blocked = false; this.customSelection = false; if (this.mode === true || this.mode === "copy") { this.rowRange = range2 || this.table.options.clipboardCopyRowRange; if (typeof window.getSelection != "undefined" && typeof document.createRange != "undefined") { range2 = document.createRange(); range2.selectNodeContents(this.table.element); sel = window.getSelection(); if (sel.toString() && internal) { this.customSelection = sel.toString(); } sel.removeAllRanges(); sel.addRange(range2); } else if (typeof document.selection != "undefined" && typeof document.body.createTextRange != "undefined") { textRange = document.body.createTextRange(); textRange.moveToElementText(this.table.element); textRange.select(); } document.execCommand("copy"); if (sel) { sel.removeAllRanges(); } } } //PASTE EVENT HANDLING setPasteAction(action) { switch (typeof action) { case "string": this.pasteAction = _Clipboard.pasteActions[action]; if (!this.pasteAction) { console.warn("Clipboard Error - No such paste action found:", action); } break; case "function": this.pasteAction = action; break; } } setPasteParser(parser) { switch (typeof parser) { case "string": this.pasteParser = _Clipboard.pasteParsers[parser]; if (!this.pasteParser) { console.warn("Clipboard Error - No such paste parser found:", parser); } break; case "function": this.pasteParser = parser; break; } } paste(e) { var data, rowData, rows2; if (this.checkPasteOrigin(e)) { data = this.getPasteData(e); rowData = this.pasteParser.call(this, data); if (rowData) { e.preventDefault(); if (this.table.modExists("mutator")) { rowData = this.mutateData(rowData); } rows2 = this.pasteAction.call(this, rowData); this.dispatchExternal("clipboardPasted", data, rowData, rows2); } else { this.dispatchExternal("clipboardPasteError", data); } } } mutateData(data) { var output = []; if (Array.isArray(data)) { data.forEach((row) => { output.push(this.table.modules.mutator.transformRow(row, "clipboard")); }); } else { output = data; } return output; } checkPasteOrigin(e) { var valid = true; var blocked = this.confirm("clipboard-paste", [e]); if (blocked || !["DIV", "SPAN"].includes(e.target.tagName)) { valid = false; } return valid; } getPasteData(e) { var data; if (window.clipboardData && window.clipboardData.getData) { data = window.clipboardData.getData("Text"); } else if (e.clipboardData && e.clipboardData.getData) { data = e.clipboardData.getData("text/plain"); } else if (e.originalEvent && e.originalEvent.clipboardData.getData) { data = e.originalEvent.clipboardData.getData("text/plain"); } return data; } }; __publicField(_Clipboard, "moduleName", "clipboard"); __publicField(_Clipboard, "moduleExtensions", extensions$4); //load defaults __publicField(_Clipboard, "pasteActions", defaultPasteActions); __publicField(_Clipboard, "pasteParsers", defaultPasteParsers); let Clipboard = _Clipboard; class CalcComponent { constructor(row) { this._row = row; return new Proxy(this, { get: function (target, name2, receiver) { if (typeof target[name2] !== "undefined") { return target[name2]; } else { return target._row.table.componentFunctionBinder.handle("row", target._row, name2); } } }); } getData(transform) { return this._row.getData(transform); } getElement() { return this._row.getElement(); } getTable() { return this._row.table; } getCells() { var cells = []; this._row.getCells().forEach(function (cell) { cells.push(cell.getComponent()); }); return cells; } getCell(column) { var cell = this._row.getCell(column); return cell ? cell.getComponent() : false; } _getSelf() { return this._row; } } class CellComponent { constructor(cell) { this._cell = cell; return new Proxy(this, { get: function (target, name2, receiver) { if (typeof target[name2] !== "undefined") { return target[name2]; } else { return target._cell.table.componentFunctionBinder.handle("cell", target._cell, name2); } } }); } getValue() { return this._cell.getValue(); } getOldValue() { return this._cell.getOldValue(); } getInitialValue() { return this._cell.initialValue; } getElement() { return this._cell.getElement(); } getRow() { return this._cell.row.getComponent(); } getData(transform) { return this._cell.row.getData(transform); } getType() { return "cell"; } getField() { return this._cell.column.getField(); } getColumn() { return this._cell.column.getComponent(); } setValue(value, mutate) { if (typeof mutate == "undefined") { mutate = true; } this._cell.setValue(value, mutate); } restoreOldValue() { this._cell.setValueActual(this._cell.getOldValue()); } restoreInitialValue() { this._cell.setValueActual(this._cell.initialValue); } checkHeight() { this._cell.checkHeight(); } getTable() { return this._cell.table; } _getSelf() { return this._cell; } } class Cell extends CoreFeature { constructor(column, row) { super(column.table); this.table = column.table; this.column = column; this.row = row; this.element = null; this.value = null; this.initialValue; this.oldValue = null; this.modules = {}; this.height = null; this.width = null; this.minWidth = null; this.component = null; this.loaded = false; this.build(); } //////////////// Setup Functions ///////////////// //generate element build() { this.generateElement(); this.setWidth(); this._configureCell(); this.setValueActual(this.column.getFieldValue(this.row.data)); this.initialValue = this.value; } generateElement() { this.element = document.createElement("div"); this.element.className = "tabulator-cell"; this.element.setAttribute("role", "gridcell"); if (this.column.isRowHeader) { this.element.classList.add("tabulator-row-header"); } } _configureCell() { var element = this.element, field = this.column.getField(), vertAligns = { top: "flex-start", bottom: "flex-end", middle: "center" }, hozAligns = { left: "flex-start", right: "flex-end", center: "center" }; element.style.textAlign = this.column.hozAlign; if (this.column.vertAlign) { element.style.display = "inline-flex"; element.style.alignItems = vertAligns[this.column.vertAlign] || ""; if (this.column.hozAlign) { element.style.justifyContent = hozAligns[this.column.hozAlign] || ""; } } if (field) { element.setAttribute("tabulator-field", field); } if (this.column.definition.cssClass) { var classNames = this.column.definition.cssClass.split(" "); classNames.forEach((className) => { element.classList.add(className); }); } this.dispatch("cell-init", this); if (!this.column.visible) { this.hide(); } } //generate cell contents _generateContents() { var val; val = this.chain("cell-format", this, null, () => { return this.element.innerHTML = this.value; }); switch (typeof val) { case "object": if (val instanceof Node) { while (this.element.firstChild) this.element.removeChild(this.element.firstChild); this.element.appendChild(val); } else { this.element.innerHTML = ""; if (val != null) { console.warn("Format Error - Formatter has returned a type of object, the only valid formatter object return is an instance of Node, the formatter returned:", val); } } break; case "undefined": this.element.innerHTML = ""; break; default: this.element.innerHTML = val; } } cellRendered() { this.dispatch("cell-rendered", this); } //////////////////// Getters //////////////////// getElement(containerOnly) { if (!this.loaded) { this.loaded = true; if (!containerOnly) { this.layoutElement(); } } return this.element; } getValue() { return this.value; } getOldValue() { return this.oldValue; } //////////////////// Actions //////////////////// setValue(value, mutate, force) { var changed = this.setValueProcessData(value, mutate, force); if (changed) { this.dispatch("cell-value-updated", this); this.cellRendered(); if (this.column.definition.cellEdited) { this.column.definition.cellEdited.call(this.table, this.getComponent()); } this.dispatchExternal("cellEdited", this.getComponent()); if (this.subscribedExternal("dataChanged")) { this.dispatchExternal("dataChanged", this.table.rowManager.getData()); } } } setValueProcessData(value, mutate, force) { var changed = false; if (this.value !== value || force) { changed = true; if (mutate) { value = this.chain("cell-value-changing", [this, value], null, value); } } this.setValueActual(value); if (changed) { this.dispatch("cell-value-changed", this); } return changed; } setValueActual(value) { this.oldValue = this.value; this.value = value; this.dispatch("cell-value-save-before", this); this.column.setFieldValue(this.row.data, value); this.dispatch("cell-value-save-after", this); if (this.loaded) { this.layoutElement(); } } layoutElement() { this._generateContents(); this.dispatch("cell-layout", this); } setWidth() { this.width = this.column.width; this.element.style.width = this.column.widthStyled; } clearWidth() { this.width = ""; this.element.style.width = ""; } getWidth() { return this.width || this.element.offsetWidth; } setMinWidth() { this.minWidth = this.column.minWidth; this.element.style.minWidth = this.column.minWidthStyled; } setMaxWidth() { this.maxWidth = this.column.maxWidth; this.element.style.maxWidth = this.column.maxWidthStyled; } checkHeight() { this.row.reinitializeHeight(); } clearHeight() { this.element.style.height = ""; this.height = null; this.dispatch("cell-height", this, ""); } setHeight() { this.height = this.row.height; this.element.style.height = this.row.heightStyled; this.dispatch("cell-height", this, this.row.heightStyled); } getHeight() { return this.height || this.element.offsetHeight; } show() { this.element.style.display = this.column.vertAlign ? "inline-flex" : ""; } hide() { this.element.style.display = "none"; } delete() { this.dispatch("cell-delete", this); if (!this.table.rowManager.redrawBlock && this.element.parentNode) { this.element.parentNode.removeChild(this.element); } this.element = false; this.column.deleteCell(this); this.row.deleteCell(this); this.calcs = {}; } getIndex() { return this.row.getCellIndex(this); } //////////////// Object Generation ///////////////// getComponent() { if (!this.component) { this.component = new CellComponent(this); } return this.component; } } class ColumnComponent { constructor(column) { this._column = column; this.type = "ColumnComponent"; return new Proxy(this, { get: function (target, name2, receiver) { if (typeof target[name2] !== "undefined") { return target[name2]; } else { return target._column.table.componentFunctionBinder.handle("column", target._column, name2); } } }); } getElement() { return this._column.getElement(); } getDefinition() { return this._column.getDefinition(); } getField() { return this._column.getField(); } getTitleDownload() { return this._column.getTitleDownload(); } getCells() { var cells = []; this._column.cells.forEach(function (cell) { cells.push(cell.getComponent()); }); return cells; } isVisible() { return this._column.visible; } show() { if (this._column.isGroup) { this._column.columns.forEach(function (column) { column.show(); }); } else { this._column.show(); } } hide() { if (this._column.isGroup) { this._column.columns.forEach(function (column) { column.hide(); }); } else { this._column.hide(); } } toggle() { if (this._column.visible) { this.hide(); } else { this.show(); } } delete() { return this._column.delete(); } getSubColumns() { var output = []; if (this._column.columns.length) { this._column.columns.forEach(function (column) { output.push(column.getComponent()); }); } return output; } getParentColumn() { return this._column.getParentComponent(); } _getSelf() { return this._column; } scrollTo(position, ifVisible) { return this._column.table.columnManager.scrollToColumn(this._column, position, ifVisible); } getTable() { return this._column.table; } move(to, after) { var toColumn = this._column.table.columnManager.findColumn(to); if (toColumn) { this._column.table.columnManager.moveColumn(this._column, toColumn, after); } else { console.warn("Move Error - No matching column found:", toColumn); } } getNextColumn() { var nextCol = this._column.nextColumn(); return nextCol ? nextCol.getComponent() : false; } getPrevColumn() { var prevCol = this._column.prevColumn(); return prevCol ? prevCol.getComponent() : false; } updateDefinition(updates) { return this._column.updateDefinition(updates); } getWidth() { return this._column.getWidth(); } setWidth(width) { var result; if (width === true) { result = this._column.reinitializeWidth(true); } else { result = this._column.setWidth(width); } this._column.table.columnManager.rerenderColumns(true); return result; } } var defaultColumnOptions = { "title": void 0, "field": void 0, "columns": void 0, "visible": void 0, "hozAlign": void 0, "vertAlign": void 0, "width": void 0, "minWidth": 40, "maxWidth": void 0, "maxInitialWidth": void 0, "cssClass": void 0, "variableHeight": void 0, "headerVertical": void 0, "headerHozAlign": void 0, "headerWordWrap": false, "editableTitle": void 0 }; const _Column = class _Column extends CoreFeature { constructor(def, parent2, rowHeader) { super(parent2.table); this.definition = def; this.parent = parent2; this.type = "column"; this.columns = []; this.cells = []; this.isGroup = false; this.isRowHeader = rowHeader; this.element = this.createElement(); this.contentElement = false; this.titleHolderElement = false; this.titleElement = false; this.groupElement = this.createGroupElement(); this.hozAlign = ""; this.vertAlign = ""; this.field = ""; this.fieldStructure = ""; this.getFieldValue = ""; this.setFieldValue = ""; this.titleDownload = null; this.titleFormatterRendered = false; this.mapDefinitions(); this.setField(this.definition.field); this.modules = {}; this.width = null; this.widthStyled = ""; this.maxWidth = null; this.maxWidthStyled = ""; this.maxInitialWidth = null; this.minWidth = null; this.minWidthStyled = ""; this.widthFixed = false; this.visible = true; this.component = null; if (this.definition.columns) { this.isGroup = true; this.definition.columns.forEach((def2, i) => { var newCol = new _Column(def2, this); this.attachColumn(newCol); }); this.checkColumnVisibility(); } else { parent2.registerColumnField(this); } this._initialize(); } createElement() { var el = document.createElement("div"); el.classList.add("tabulator-col"); el.setAttribute("role", "columnheader"); el.setAttribute("aria-sort", "none"); if (this.isRowHeader) { el.classList.add("tabulator-row-header"); } switch (this.table.options.columnHeaderVertAlign) { case "middle": el.style.justifyContent = "center"; break; case "bottom": el.style.justifyContent = "flex-end"; break; } return el; } createGroupElement() { var el = document.createElement("div"); el.classList.add("tabulator-col-group-cols"); return el; } mapDefinitions() { var defaults = this.table.options.columnDefaults; if (defaults) { for (let key in defaults) { if (typeof this.definition[key] === "undefined") { this.definition[key] = defaults[key]; } } } this.definition = this.table.columnManager.optionsList.generate(_Column.defaultOptionList, this.definition); } checkDefinition() { Object.keys(this.definition).forEach((key) => { if (_Column.defaultOptionList.indexOf(key) === -1) { console.warn("Invalid column definition option in '" + (this.field || this.definition.title) + "' column:", key); } }); } setField(field) { this.field = field; this.fieldStructure = field ? this.table.options.nestedFieldSeparator ? field.split(this.table.options.nestedFieldSeparator) : [field] : []; this.getFieldValue = this.fieldStructure.length > 1 ? this._getNestedData : this._getFlatData; this.setFieldValue = this.fieldStructure.length > 1 ? this._setNestedData : this._setFlatData; } //register column position with column manager registerColumnPosition(column) { this.parent.registerColumnPosition(column); } //register column position with column manager registerColumnField(column) { this.parent.registerColumnField(column); } //trigger position registration reRegisterPosition() { if (this.isGroup) { this.columns.forEach(function (column) { column.reRegisterPosition(); }); } else { this.registerColumnPosition(this); } } //build header element _initialize() { var def = this.definition; while (this.element.firstChild) this.element.removeChild(this.element.firstChild); if (def.headerVertical) { this.element.classList.add("tabulator-col-vertical"); if (def.headerVertical === "flip") { this.element.classList.add("tabulator-col-vertical-flip"); } } this.contentElement = this._buildColumnHeaderContent(); this.element.appendChild(this.contentElement); if (this.isGroup) { this._buildGroupHeader(); } else { this._buildColumnHeader(); } this.dispatch("column-init", this); } //build header element for header _buildColumnHeader() { var def = this.definition; this.dispatch("column-layout", this); if (typeof def.visible != "undefined") { if (def.visible) { this.show(true); } else { this.hide(true); } } if (def.cssClass) { var classNames = def.cssClass.split(" "); classNames.forEach((className) => { this.element.classList.add(className); }); } if (def.field) { this.element.setAttribute("tabulator-field", def.field); } this.setMinWidth(parseInt(def.minWidth)); if (def.maxInitialWidth) { this.maxInitialWidth = parseInt(def.maxInitialWidth); } if (def.maxWidth) { this.setMaxWidth(parseInt(def.maxWidth)); } this.reinitializeWidth(); this.hozAlign = this.definition.hozAlign; this.vertAlign = this.definition.vertAlign; this.titleElement.style.textAlign = this.definition.headerHozAlign; } _buildColumnHeaderContent() { var contentElement = document.createElement("div"); contentElement.classList.add("tabulator-col-content"); this.titleHolderElement = document.createElement("div"); this.titleHolderElement.classList.add("tabulator-col-title-holder"); contentElement.appendChild(this.titleHolderElement); this.titleElement = this._buildColumnHeaderTitle(); this.titleHolderElement.appendChild(this.titleElement); return contentElement; } //build title element of column _buildColumnHeaderTitle() { var def = this.definition; var titleHolderElement = document.createElement("div"); titleHolderElement.classList.add("tabulator-col-title"); if (def.headerWordWrap) { titleHolderElement.classList.add("tabulator-col-title-wrap"); } if (def.editableTitle) { var titleElement = document.createElement("input"); titleElement.classList.add("tabulator-title-editor"); titleElement.addEventListener("click", (e) => { e.stopPropagation(); titleElement.focus(); }); titleElement.addEventListener("mousedown", (e) => { e.stopPropagation(); }); titleElement.addEventListener("change", () => { def.title = titleElement.value; this.dispatchExternal("columnTitleChanged", this.getComponent()); }); titleHolderElement.appendChild(titleElement); if (def.field) { this.langBind("columns|" + def.field, (text) => { titleElement.value = text || (def.title || " "); }); } else { titleElement.value = def.title || " "; } } else { if (def.field) { this.langBind("columns|" + def.field, (text) => { this._formatColumnHeaderTitle(titleHolderElement, text || (def.title || " ")); }); } else { this._formatColumnHeaderTitle(titleHolderElement, def.title || " "); } } return titleHolderElement; } _formatColumnHeaderTitle(el, title) { var contents = this.chain("column-format", [this, title, el], null, () => { return title; }); switch (typeof contents) { case "object": if (contents instanceof Node) { el.appendChild(contents); } else { el.innerHTML = ""; console.warn("Format Error - Title formatter has returned a type of object, the only valid formatter object return is an instance of Node, the formatter returned:", contents); } break; case "undefined": el.innerHTML = ""; break; default: el.innerHTML = contents; } } //build header element for column group _buildGroupHeader() { this.element.classList.add("tabulator-col-group"); this.element.setAttribute("role", "columngroup"); this.element.setAttribute("aria-title", this.definition.title); if (this.definition.cssClass) { var classNames = this.definition.cssClass.split(" "); classNames.forEach((className) => { this.element.classList.add(className); }); } this.titleElement.style.textAlign = this.definition.headerHozAlign; this.element.appendChild(this.groupElement); } //flat field lookup _getFlatData(data) { return data[this.field]; } //nested field lookup _getNestedData(data) { var dataObj = data, structure = this.fieldStructure, length = structure.length, output; for (let i = 0; i < length; i++) { dataObj = dataObj[structure[i]]; output = dataObj; if (!dataObj) { break; } } return output; } //flat field set _setFlatData(data, value) { if (this.field) { data[this.field] = value; } } //nested field set _setNestedData(data, value) { var dataObj = data, structure = this.fieldStructure, length = structure.length; for (let i = 0; i < length; i++) { if (i == length - 1) { dataObj[structure[i]] = value; } else { if (!dataObj[structure[i]]) { if (typeof value !== "undefined") { dataObj[structure[i]] = {}; } else { break; } } dataObj = dataObj[structure[i]]; } } } //attach column to this group attachColumn(column) { if (this.groupElement) { this.columns.push(column); this.groupElement.appendChild(column.getElement()); column.columnRendered(); } else { console.warn("Column Warning - Column being attached to another column instead of column group"); } } //vertically align header in column verticalAlign(alignment, height) { var parentHeight = this.parent.isGroup ? this.parent.getGroupElement().clientHeight : height || this.parent.getHeadersElement().clientHeight; this.element.style.height = parentHeight + "px"; this.dispatch("column-height", this, this.element.style.height); if (this.isGroup) { this.groupElement.style.minHeight = parentHeight - this.contentElement.offsetHeight + "px"; } this.columns.forEach(function (column) { column.verticalAlign(alignment); }); } //clear vertical alignment clearVerticalAlign() { this.element.style.paddingTop = ""; this.element.style.height = ""; this.element.style.minHeight = ""; this.groupElement.style.minHeight = ""; this.columns.forEach(function (column) { column.clearVerticalAlign(); }); this.dispatch("column-height", this, ""); } //// Retrieve Column Information //// //return column header element getElement() { return this.element; } //return column group element getGroupElement() { return this.groupElement; } //return field name getField() { return this.field; } getTitleDownload() { return this.titleDownload; } //return the first column in a group getFirstColumn() { if (!this.isGroup) { return this; } else { if (this.columns.length) { return this.columns[0].getFirstColumn(); } else { return false; } } } //return the last column in a group getLastColumn() { if (!this.isGroup) { return this; } else { if (this.columns.length) { return this.columns[this.columns.length - 1].getLastColumn(); } else { return false; } } } //return all columns in a group getColumns(traverse) { var columns = []; if (traverse) { this.columns.forEach((column) => { columns.push(column); columns = columns.concat(column.getColumns(true)); }); } else { columns = this.columns; } return columns; } //return all columns in a group getCells() { return this.cells; } //retrieve the top column in a group of columns getTopColumn() { if (this.parent.isGroup) { return this.parent.getTopColumn(); } else { return this; } } //return column definition object getDefinition(updateBranches) { var colDefs = []; if (this.isGroup && updateBranches) { this.columns.forEach(function (column) { colDefs.push(column.getDefinition(true)); }); this.definition.columns = colDefs; } return this.definition; } //////////////////// Actions //////////////////// checkColumnVisibility() { var visible = false; this.columns.forEach(function (column) { if (column.visible) { visible = true; } }); if (visible) { this.show(); this.dispatchExternal("columnVisibilityChanged", this.getComponent(), false); } else { this.hide(); } } //show column show(silent, responsiveToggle) { if (!this.visible) { this.visible = true; this.element.style.display = ""; if (this.parent.isGroup) { this.parent.checkColumnVisibility(); } this.cells.forEach(function (cell) { cell.show(); }); if (!this.isGroup && this.width === null) { this.reinitializeWidth(); } this.table.columnManager.verticalAlignHeaders(); this.dispatch("column-show", this, responsiveToggle); if (!silent) { this.dispatchExternal("columnVisibilityChanged", this.getComponent(), true); } if (this.parent.isGroup) { this.parent.matchChildWidths(); } if (!this.silent) { this.table.columnManager.rerenderColumns(); } } } //hide column hide(silent, responsiveToggle) { if (this.visible) { this.visible = false; this.element.style.display = "none"; this.table.columnManager.verticalAlignHeaders(); if (this.parent.isGroup) { this.parent.checkColumnVisibility(); } this.cells.forEach(function (cell) { cell.hide(); }); this.dispatch("column-hide", this, responsiveToggle); if (!silent) { this.dispatchExternal("columnVisibilityChanged", this.getComponent(), false); } if (this.parent.isGroup) { this.parent.matchChildWidths(); } if (!this.silent) { this.table.columnManager.rerenderColumns(); } } } matchChildWidths() { var childWidth = 0; if (this.contentElement && this.columns.length) { this.columns.forEach(function (column) { if (column.visible) { childWidth += column.getWidth(); } }); this.contentElement.style.maxWidth = childWidth - 1 + "px"; if (this.table.initialized) { this.element.style.width = childWidth + "px"; } if (this.parent.isGroup) { this.parent.matchChildWidths(); } } } removeChild(child) { var index = this.columns.indexOf(child); if (index > -1) { this.columns.splice(index, 1); } if (!this.columns.length) { this.delete(); } } setWidth(width) { this.widthFixed = true; this.setWidthActual(width); } setWidthActual(width) { if (isNaN(width)) { width = Math.floor(this.table.element.clientWidth / 100 * parseInt(width)); } width = Math.max(this.minWidth, width); if (this.maxWidth) { width = Math.min(this.maxWidth, width); } this.width = width; this.widthStyled = width ? width + "px" : ""; this.element.style.width = this.widthStyled; if (!this.isGroup) { this.cells.forEach(function (cell) { cell.setWidth(); }); } if (this.parent.isGroup) { this.parent.matchChildWidths(); } this.dispatch("column-width", this); if (this.subscribedExternal("columnWidth")) { this.dispatchExternal("columnWidth", this.getComponent()); } } checkCellHeights() { var rows2 = []; this.cells.forEach(function (cell) { if (cell.row.heightInitialized) { if (cell.row.getElement().offsetParent !== null) { rows2.push(cell.row); cell.row.clearCellHeight(); } else { cell.row.heightInitialized = false; } } }); rows2.forEach(function (row) { row.calcHeight(); }); rows2.forEach(function (row) { row.setCellHeight(); }); } getWidth() { var width = 0; if (this.isGroup) { this.columns.forEach(function (column) { if (column.visible) { width += column.getWidth(); } }); } else { width = this.width; } return width; } getLeftOffset() { var offset = this.element.offsetLeft; if (this.parent.isGroup) { offset += this.parent.getLeftOffset(); } return offset; } getHeight() { return Math.ceil(this.element.getBoundingClientRect().height); } setMinWidth(minWidth) { if (this.maxWidth && minWidth > this.maxWidth) { minWidth = this.maxWidth; console.warn("the minWidth (" + minWidth + "px) for column '" + this.field + "' cannot be bigger that its maxWidth (" + this.maxWidthStyled + ")"); } this.minWidth = minWidth; this.minWidthStyled = minWidth ? minWidth + "px" : ""; this.element.style.minWidth = this.minWidthStyled; this.cells.forEach(function (cell) { cell.setMinWidth(); }); } setMaxWidth(maxWidth) { if (this.minWidth && maxWidth < this.minWidth) { maxWidth = this.minWidth; console.warn("the maxWidth (" + maxWidth + "px) for column '" + this.field + "' cannot be smaller that its minWidth (" + this.minWidthStyled + ")"); } this.maxWidth = maxWidth; this.maxWidthStyled = maxWidth ? maxWidth + "px" : ""; this.element.style.maxWidth = this.maxWidthStyled; this.cells.forEach(function (cell) { cell.setMaxWidth(); }); } delete() { return new Promise((resolve, reject) => { if (this.isGroup) { this.columns.forEach(function (column) { column.delete(); }); } this.dispatch("column-delete", this); var cellCount = this.cells.length; for (let i = 0; i < cellCount; i++) { this.cells[0].delete(); } if (this.element.parentNode) { this.element.parentNode.removeChild(this.element); } this.element = false; this.contentElement = false; this.titleElement = false; this.groupElement = false; if (this.parent.isGroup) { this.parent.removeChild(this); } this.table.columnManager.deregisterColumn(this); this.table.columnManager.rerenderColumns(true); this.dispatch("column-deleted", this); resolve(); }); } columnRendered() { if (this.titleFormatterRendered) { this.titleFormatterRendered(); } this.dispatch("column-rendered", this); } //////////////// Cell Management ///////////////// //generate cell for this column generateCell(row) { var cell = new Cell(this, row); this.cells.push(cell); return cell; } nextColumn() { var index = this.table.columnManager.findColumnIndex(this); return index > -1 ? this._nextVisibleColumn(index + 1) : false; } _nextVisibleColumn(index) { var column = this.table.columnManager.getColumnByIndex(index); return !column || column.visible ? column : this._nextVisibleColumn(index + 1); } prevColumn() { var index = this.table.columnManager.findColumnIndex(this); return index > -1 ? this._prevVisibleColumn(index - 1) : false; } _prevVisibleColumn(index) { var column = this.table.columnManager.getColumnByIndex(index); return !column || column.visible ? column : this._prevVisibleColumn(index - 1); } reinitializeWidth(force) { this.widthFixed = false; if (typeof this.definition.width !== "undefined" && !force) { this.setWidth(this.definition.width); } this.dispatch("column-width-fit-before", this); this.fitToData(force); this.dispatch("column-width-fit-after", this); } //set column width to maximum cell width for non group columns fitToData(force) { if (this.isGroup) { return; } if (!this.widthFixed) { this.element.style.width = ""; this.cells.forEach((cell) => { cell.clearWidth(); }); } var maxWidth = this.element.offsetWidth; if (!this.width || !this.widthFixed) { this.cells.forEach((cell) => { var width = cell.getWidth(); if (width > maxWidth) { maxWidth = width; } }); if (maxWidth) { var setTo = maxWidth + 1; if (force) { this.setWidth(setTo); } else { if (this.maxInitialWidth && !force) { setTo = Math.min(setTo, this.maxInitialWidth); } this.setWidthActual(setTo); } } } } updateDefinition(updates) { var definition; if (!this.isGroup) { if (!this.parent.isGroup) { definition = Object.assign({}, this.getDefinition()); definition = Object.assign(definition, updates); return this.table.columnManager.addColumn(definition, false, this).then((column) => { if (definition.field == this.field) { this.field = false; } return this.delete().then(() => { return column.getComponent(); }); }); } else { console.error("Column Update Error - The updateDefinition function is only available on ungrouped columns"); return Promise.reject("Column Update Error - The updateDefinition function is only available on columns, not column groups"); } } else { console.error("Column Update Error - The updateDefinition function is only available on ungrouped columns"); return Promise.reject("Column Update Error - The updateDefinition function is only available on columns, not column groups"); } } deleteCell(cell) { var index = this.cells.indexOf(cell); if (index > -1) { this.cells.splice(index, 1); } } //////////////// Object Generation ///////////////// getComponent() { if (!this.component) { this.component = new ColumnComponent(this); } return this.component; } getPosition() { return this.table.columnManager.getVisibleColumnsByIndex().indexOf(this) + 1; } getParentComponent() { return this.parent instanceof _Column ? this.parent.getComponent() : false; } }; __publicField(_Column, "defaultOptionList", defaultColumnOptions); let Column = _Column; class RowComponent { constructor(row) { this._row = row; return new Proxy(this, { get: function (target, name2, receiver) { if (typeof target[name2] !== "undefined") { return target[name2]; } else { return target._row.table.componentFunctionBinder.handle("row", target._row, name2); } } }); } getData(transform) { return this._row.getData(transform); } getElement() { return this._row.getElement(); } getCells() { var cells = []; this._row.getCells().forEach(function (cell) { cells.push(cell.getComponent()); }); return cells; } getCell(column) { var cell = this._row.getCell(column); return cell ? cell.getComponent() : false; } getIndex() { return this._row.getData("data")[this._row.table.options.index]; } getPosition() { return this._row.getPosition(); } watchPosition(callback) { return this._row.watchPosition(callback); } delete() { return this._row.delete(); } scrollTo(position, ifVisible) { return this._row.table.rowManager.scrollToRow(this._row, position, ifVisible); } move(to, after) { this._row.moveToRow(to, after); } update(data) { return this._row.updateData(data); } normalizeHeight() { this._row.normalizeHeight(true); } _getSelf() { return this._row; } reformat() { return this._row.reinitialize(); } getTable() { return this._row.table; } getNextRow() { var row = this._row.nextRow(); return row ? row.getComponent() : row; } getPrevRow() { var row = this._row.prevRow(); return row ? row.getComponent() : row; } } class Row extends CoreFeature { constructor(data, parent2, type = "row") { super(parent2.table); this.parent = parent2; this.data = {}; this.type = type; this.element = false; this.modules = {}; this.cells = []; this.height = 0; this.heightStyled = ""; this.manualHeight = false; this.outerHeight = 0; this.initialized = false; this.heightInitialized = false; this.position = 0; this.positionWatchers = []; this.component = null; this.created = false; this.setData(data); } create() { if (!this.created) { this.created = true; this.generateElement(); } } createElement() { var el = document.createElement("div"); el.classList.add("tabulator-row"); el.setAttribute("role", "row"); this.element = el; } getElement() { this.create(); return this.element; } detachElement() { if (this.element && this.element.parentNode) { this.element.parentNode.removeChild(this.element); } } generateElement() { this.createElement(); this.dispatch("row-init", this); } generateCells() { this.cells = this.table.columnManager.generateCells(this); } //functions to setup on first render initialize(force, inFragment) { this.create(); if (!this.initialized || force) { this.deleteCells(); while (this.element.firstChild) this.element.removeChild(this.element.firstChild); this.dispatch("row-layout-before", this); this.generateCells(); this.initialized = true; this.table.columnManager.renderer.renderRowCells(this, inFragment); if (force) { this.normalizeHeight(); } this.dispatch("row-layout", this); if (this.table.options.rowFormatter) { this.table.options.rowFormatter(this.getComponent()); } this.dispatch("row-layout-after", this); } else { this.table.columnManager.renderer.rerenderRowCells(this, inFragment); } } rendered() { this.cells.forEach((cell) => { cell.cellRendered(); }); } reinitializeHeight() { this.heightInitialized = false; if (this.element && this.element.offsetParent !== null) { this.normalizeHeight(true); } } deinitialize() { this.initialized = false; } deinitializeHeight() { this.heightInitialized = false; } reinitialize(children) { this.initialized = false; this.heightInitialized = false; if (!this.manualHeight) { this.height = 0; this.heightStyled = ""; } if (this.element && this.element.offsetParent !== null) { this.initialize(true); } this.dispatch("row-relayout", this); } //get heights when doing bulk row style calcs in virtual DOM calcHeight(force) { var maxHeight = 0, minHeight = 0; if (this.table.options.rowHeight) { this.height = this.table.options.rowHeight; } else { minHeight = this.calcMinHeight(); maxHeight = this.calcMaxHeight(); if (force) { this.height = Math.max(maxHeight, minHeight); } else { this.height = this.manualHeight ? this.height : Math.max(maxHeight, minHeight); } } this.heightStyled = this.height ? this.height + "px" : ""; this.outerHeight = this.element.offsetHeight; } calcMinHeight() { return this.table.options.resizableRows ? this.element.clientHeight : 0; } calcMaxHeight() { var maxHeight = 0; this.cells.forEach(function (cell) { var height = cell.getHeight(); if (height > maxHeight) { maxHeight = height; } }); return maxHeight; } //set of cells setCellHeight() { this.cells.forEach(function (cell) { cell.setHeight(); }); this.heightInitialized = true; } clearCellHeight() { this.cells.forEach(function (cell) { cell.clearHeight(); }); } //normalize the height of elements in the row normalizeHeight(force) { if (force && !this.table.options.rowHeight) { this.clearCellHeight(); } this.calcHeight(force); this.setCellHeight(); } //set height of rows setHeight(height, force) { if (this.height != height || force) { this.manualHeight = true; this.height = height; this.heightStyled = height ? height + "px" : ""; this.setCellHeight(); this.outerHeight = this.element.offsetHeight; if (this.subscribedExternal("rowHeight")) { this.dispatchExternal("rowHeight", this.getComponent()); } } } //return rows outer height getHeight() { return this.outerHeight; } //return rows outer Width getWidth() { return this.element.offsetWidth; } //////////////// Cell Management ///////////////// deleteCell(cell) { var index = this.cells.indexOf(cell); if (index > -1) { this.cells.splice(index, 1); } } //////////////// Data Management ///////////////// setData(data) { this.data = this.chain("row-data-init-before", [this, data], void 0, data); this.dispatch("row-data-init-after", this); } //update the rows data updateData(updatedData) { var visible = this.element && Helpers.elVisible(this.element), tempData = {}, newRowData; return new Promise((resolve, reject) => { if (typeof updatedData === "string") { updatedData = JSON.parse(updatedData); } this.dispatch("row-data-save-before", this); if (this.subscribed("row-data-changing")) { tempData = Object.assign(tempData, this.data); tempData = Object.assign(tempData, updatedData); } newRowData = this.chain("row-data-changing", [this, tempData, updatedData], null, updatedData); const cellsToUpdate = []; for (let attrname in updatedData) { let columns = this.table.columnManager.getColumnsByFieldRoot(attrname); columns.forEach((column) => { let cell = this.getCell(column.getField()); if (cell) { let value = column.getFieldValue(newRowData); if (cell.getValue() !== value) { cellsToUpdate.push([cell, value]); } } }); } for (let attrname in newRowData) { this.data[attrname] = newRowData[attrname]; } this.dispatch("row-data-save-after", this); cellsToUpdate.forEach(([cell, value]) => { cell.setValueProcessData(value); if (visible) { cell.cellRendered(); } }); if (visible) { this.normalizeHeight(true); if (this.table.options.rowFormatter) { this.table.options.rowFormatter(this.getComponent()); } } else { this.initialized = false; this.height = 0; this.heightStyled = ""; } this.dispatch("row-data-changed", this, visible, updatedData); this.dispatchExternal("rowUpdated", this.getComponent()); if (this.subscribedExternal("dataChanged")) { this.dispatchExternal("dataChanged", this.table.rowManager.getData()); } resolve(); }); } getData(transform) { if (transform) { return this.chain("row-data-retrieve", [this, transform], null, this.data); } return this.data; } getCell(column) { var match = false; column = this.table.columnManager.findColumn(column); if (!this.initialized && this.cells.length === 0) { this.generateCells(); } match = this.cells.find(function (cell) { return cell.column === column; }); return match; } getCellIndex(findCell) { return this.cells.findIndex(function (cell) { return cell === findCell; }); } findCell(subject) { return this.cells.find((cell) => { return cell.element === subject; }); } getCells() { if (!this.initialized && this.cells.length === 0) { this.generateCells(); } return this.cells; } nextRow() { var row = this.table.rowManager.nextDisplayRow(this, true); return row || false; } prevRow() { var row = this.table.rowManager.prevDisplayRow(this, true); return row || false; } moveToRow(to, before) { var toRow = this.table.rowManager.findRow(to); if (toRow) { this.table.rowManager.moveRowActual(this, toRow, !before); this.table.rowManager.refreshActiveData("display", false, true); } else { console.warn("Move Error - No matching row found:", to); } } ///////////////////// Actions ///////////////////// delete() { this.dispatch("row-delete", this); this.deleteActual(); return Promise.resolve(); } deleteActual(blockRedraw) { this.detachModules(); this.table.rowManager.deleteRow(this, blockRedraw); this.deleteCells(); this.initialized = false; this.heightInitialized = false; this.element = false; this.dispatch("row-deleted", this); } detachModules() { this.dispatch("row-deleting", this); } deleteCells() { var cellCount = this.cells.length; for (let i = 0; i < cellCount; i++) { this.cells[0].delete(); } } wipe() { this.detachModules(); this.deleteCells(); if (this.element) { while (this.element.firstChild) this.element.removeChild(this.element.firstChild); if (this.element.parentNode) { this.element.parentNode.removeChild(this.element); } } this.element = false; this.modules = {}; } isDisplayed() { return this.table.rowManager.getDisplayRows().includes(this); } getPosition() { return this.isDisplayed() ? this.position : false; } setPosition(position) { if (position != this.position) { this.position = position; this.positionWatchers.forEach((callback) => { callback(this.position); }); } } watchPosition(callback) { this.positionWatchers.push(callback); callback(this.position); } getGroup() { return this.modules.group || false; } //////////////// Object Generation ///////////////// getComponent() { if (!this.component) { this.component = new RowComponent(this); } return this.component; } } var defaultCalculations = { "avg": function (values, data, calcParams) { var output = 0, precision = typeof calcParams.precision !== "undefined" ? calcParams.precision : 2; if (values.length) { output = values.reduce(function (sum, value) { return Number(sum) + Number(value); }); output = output / values.length; output = precision !== false ? output.toFixed(precision) : output; } return parseFloat(output).toString(); }, "max": function (values, data, calcParams) { var output = null, precision = typeof calcParams.precision !== "undefined" ? calcParams.precision : false; values.forEach(function (value) { value = Number(value); if (value > output || output === null) { output = value; } }); return output !== null ? precision !== false ? output.toFixed(precision) : output : ""; }, "min": function (values, data, calcParams) { var output = null, precision = typeof calcParams.precision !== "undefined" ? calcParams.precision : false; values.forEach(function (value) { value = Number(value); if (value < output || output === null) { output = value; } }); return output !== null ? precision !== false ? output.toFixed(precision) : output : ""; }, "sum": function (values, data, calcParams) { var output = 0, precision = typeof calcParams.precision !== "undefined" ? calcParams.precision : false; if (values.length) { values.forEach(function (value) { value = Number(value); output += !isNaN(value) ? Number(value) : 0; }); } return precision !== false ? output.toFixed(precision) : output; }, "concat": function (values, data, calcParams) { var output = 0; if (values.length) { output = values.reduce(function (sum, value) { return String(sum) + String(value); }); } return output; }, "count": function (values, data, calcParams) { var output = 0; if (values.length) { values.forEach(function (value) { if (value) { output++; } }); } return output; }, "unique": function (values, data, calcParams) { var unique = values.filter((value, index) => { return (values || value === 0) && values.indexOf(value) === index; }); return unique.length; } }; const _ColumnCalcs = class _ColumnCalcs extends Module { constructor(table) { super(table); this.topCalcs = []; this.botCalcs = []; this.genColumn = false; this.topElement = this.createElement(); this.botElement = this.createElement(); this.topRow = false; this.botRow = false; this.topInitialized = false; this.botInitialized = false; this.blocked = false; this.recalcAfterBlock = false; this.registerTableOption("columnCalcs", true); this.registerColumnOption("topCalc"); this.registerColumnOption("topCalcParams"); this.registerColumnOption("topCalcFormatter"); this.registerColumnOption("topCalcFormatterParams"); this.registerColumnOption("bottomCalc"); this.registerColumnOption("bottomCalcParams"); this.registerColumnOption("bottomCalcFormatter"); this.registerColumnOption("bottomCalcFormatterParams"); } createElement() { var el = document.createElement("div"); el.classList.add("tabulator-calcs-holder"); return el; } initialize() { this.genColumn = new Column({field: "value"}, this); this.subscribe("cell-value-changed", this.cellValueChanged.bind(this)); this.subscribe("column-init", this.initializeColumnCheck.bind(this)); this.subscribe("row-deleted", this.rowsUpdated.bind(this)); this.subscribe("scroll-horizontal", this.scrollHorizontal.bind(this)); this.subscribe("row-added", this.rowsUpdated.bind(this)); this.subscribe("column-moved", this.recalcActiveRows.bind(this)); this.subscribe("column-add", this.recalcActiveRows.bind(this)); this.subscribe("data-refreshed", this.recalcActiveRowsRefresh.bind(this)); this.subscribe("table-redraw", this.tableRedraw.bind(this)); this.subscribe("rows-visible", this.visibleRows.bind(this)); this.subscribe("scrollbar-vertical", this.adjustForScrollbar.bind(this)); this.subscribe("redraw-blocked", this.blockRedraw.bind(this)); this.subscribe("redraw-restored", this.restoreRedraw.bind(this)); this.subscribe("table-redrawing", this.resizeHolderWidth.bind(this)); this.subscribe("column-resized", this.resizeHolderWidth.bind(this)); this.subscribe("column-show", this.resizeHolderWidth.bind(this)); this.subscribe("column-hide", this.resizeHolderWidth.bind(this)); this.registerTableFunction("getCalcResults", this.getResults.bind(this)); this.registerTableFunction("recalc", this.userRecalc.bind(this)); this.resizeHolderWidth(); } resizeHolderWidth() { this.topElement.style.minWidth = this.table.columnManager.headersElement.offsetWidth + "px"; } tableRedraw(force) { this.recalc(this.table.rowManager.activeRows); if (force) { this.redraw(); } } blockRedraw() { this.blocked = true; this.recalcAfterBlock = false; } restoreRedraw() { this.blocked = false; if (this.recalcAfterBlock) { this.recalcAfterBlock = false; this.recalcActiveRowsRefresh(); } } /////////////////////////////////// ///////// Table Functions ///////// /////////////////////////////////// userRecalc() { this.recalc(this.table.rowManager.activeRows); } /////////////////////////////////// ///////// Internal Logic ////////// /////////////////////////////////// blockCheck() { if (this.blocked) { this.recalcAfterBlock = true; } return this.blocked; } visibleRows(viewable, rows2) { if (this.topRow) { rows2.unshift(this.topRow); } if (this.botRow) { rows2.push(this.botRow); } return rows2; } rowsUpdated(row) { if (this.table.options.groupBy) { this.recalcRowGroup(row); } else { this.recalcActiveRows(); } } recalcActiveRowsRefresh() { if (this.table.options.groupBy && this.table.options.dataTreeStartExpanded && this.table.options.dataTree) { this.recalcAll(); } else { this.recalcActiveRows(); } } recalcActiveRows() { this.recalc(this.table.rowManager.activeRows); } cellValueChanged(cell) { if (cell.column.definition.topCalc || cell.column.definition.bottomCalc) { if (this.table.options.groupBy) { if (this.table.options.columnCalcs == "table" || this.table.options.columnCalcs == "both") { this.recalcActiveRows(); } if (this.table.options.columnCalcs != "table") { this.recalcRowGroup(cell.row); } } else { this.recalcActiveRows(); } } } initializeColumnCheck(column) { if (column.definition.topCalc || column.definition.bottomCalc) { this.initializeColumn(column); } } //initialize column calcs initializeColumn(column) { var def = column.definition; var config = { topCalcParams: def.topCalcParams || {}, botCalcParams: def.bottomCalcParams || {} }; if (def.topCalc) { switch (typeof def.topCalc) { case "string": if (_ColumnCalcs.calculations[def.topCalc]) { config.topCalc = _ColumnCalcs.calculations[def.topCalc]; } else { console.warn("Column Calc Error - No such calculation found, ignoring: ", def.topCalc); } break; case "function": config.topCalc = def.topCalc; break; } if (config.topCalc) { column.modules.columnCalcs = config; this.topCalcs.push(column); if (this.table.options.columnCalcs != "group") { this.initializeTopRow(); } } } if (def.bottomCalc) { switch (typeof def.bottomCalc) { case "string": if (_ColumnCalcs.calculations[def.bottomCalc]) { config.botCalc = _ColumnCalcs.calculations[def.bottomCalc]; } else { console.warn("Column Calc Error - No such calculation found, ignoring: ", def.bottomCalc); } break; case "function": config.botCalc = def.bottomCalc; break; } if (config.botCalc) { column.modules.columnCalcs = config; this.botCalcs.push(column); if (this.table.options.columnCalcs != "group") { this.initializeBottomRow(); } } } } //dummy functions to handle being mock column manager registerColumnField() { } removeCalcs() { var changed = false; if (this.topInitialized) { this.topInitialized = false; this.topElement.parentNode.removeChild(this.topElement); changed = true; } if (this.botInitialized) { this.botInitialized = false; this.footerRemove(this.botElement); changed = true; } if (changed) { this.table.rowManager.adjustTableSize(); } } reinitializeCalcs() { if (this.topCalcs.length) { this.initializeTopRow(); } if (this.botCalcs.length) { this.initializeBottomRow(); } } initializeTopRow() { var fragment = document.createDocumentFragment(); if (!this.topInitialized) { fragment.appendChild(document.createElement("br")); fragment.appendChild(this.topElement); this.table.columnManager.getContentsElement().insertBefore(fragment, this.table.columnManager.headersElement.nextSibling); this.topInitialized = true; } } initializeBottomRow() { if (!this.botInitialized) { this.footerPrepend(this.botElement); this.botInitialized = true; } } scrollHorizontal(left) { if (this.botInitialized && this.botRow) { this.botElement.scrollLeft = left; } } recalc(rows2) { var data, row; if (!this.blockCheck()) { if (this.topInitialized || this.botInitialized) { data = this.rowsToData(rows2); if (this.topInitialized) { if (this.topRow) { this.topRow.deleteCells(); } row = this.generateRow("top", data); this.topRow = row; while (this.topElement.firstChild) this.topElement.removeChild(this.topElement.firstChild); this.topElement.appendChild(row.getElement()); row.initialize(true); } if (this.botInitialized) { if (this.botRow) { this.botRow.deleteCells(); } row = this.generateRow("bottom", data); this.botRow = row; while (this.botElement.firstChild) this.botElement.removeChild(this.botElement.firstChild); this.botElement.appendChild(row.getElement()); row.initialize(true); } this.table.rowManager.adjustTableSize(); if (this.table.modExists("frozenColumns")) { this.table.modules.frozenColumns.layout(); } } } } recalcRowGroup(row) { this.recalcGroup(this.table.modules.groupRows.getRowGroup(row)); } recalcAll() { if (this.topCalcs.length || this.botCalcs.length) { if (this.table.options.columnCalcs !== "group") { this.recalcActiveRows(); } if (this.table.options.groupBy && this.table.options.columnCalcs !== "table") { var groups = this.table.modules.groupRows.getChildGroups(); groups.forEach((group) => { this.recalcGroup(group); }); } } } recalcGroup(group) { var data, rowData; if (!this.blockCheck()) { if (group) { if (group.calcs) { if (group.calcs.bottom) { data = this.rowsToData(group.rows); rowData = this.generateRowData("bottom", data); group.calcs.bottom.updateData(rowData); group.calcs.bottom.reinitialize(); } if (group.calcs.top) { data = this.rowsToData(group.rows); rowData = this.generateRowData("top", data); group.calcs.top.updateData(rowData); group.calcs.top.reinitialize(); } } } } } //generate top stats row generateTopRow(rows2) { return this.generateRow("top", this.rowsToData(rows2)); } //generate bottom stats row generateBottomRow(rows2) { return this.generateRow("bottom", this.rowsToData(rows2)); } rowsToData(rows2) { var data = [], hasDataTreeColumnCalcs = this.table.options.dataTree && this.table.options.dataTreeChildColumnCalcs, dataTree = this.table.modules.dataTree; rows2.forEach((row) => { var _a2; data.push(row.getData()); if (hasDataTreeColumnCalcs && ((_a2 = row.modules.dataTree) == null ? void 0 : _a2.open)) { this.rowsToData(dataTree.getFilteredTreeChildren(row)).forEach((dataRow) => { data.push(dataRow); }); } }); return data; } //generate stats row generateRow(pos, data) { var rowData = this.generateRowData(pos, data), row; if (this.table.modExists("mutator")) { this.table.modules.mutator.disable(); } row = new Row(rowData, this, "calc"); if (this.table.modExists("mutator")) { this.table.modules.mutator.enable(); } row.getElement().classList.add("tabulator-calcs", "tabulator-calcs-" + pos); row.component = false; row.getComponent = () => { if (!row.component) { row.component = new CalcComponent(row); } return row.component; }; row.generateCells = () => { var cells = []; this.table.columnManager.columnsByIndex.forEach((column) => { this.genColumn.setField(column.getField()); this.genColumn.hozAlign = column.hozAlign; if (column.definition[pos + "CalcFormatter"] && this.table.modExists("format")) { this.genColumn.modules.format = { formatter: this.table.modules.format.lookupFormatter(column.definition[pos + "CalcFormatter"]), params: column.definition[pos + "CalcFormatterParams"] || {} }; } else { this.genColumn.modules.format = { formatter: this.table.modules.format.lookupFormatter("plaintext"), params: {} }; } this.genColumn.definition.cssClass = column.definition.cssClass; var cell = new Cell(this.genColumn, row); cell.getElement(); cell.column = column; cell.setWidth(); column.cells.push(cell); cells.push(cell); if (!column.visible) { cell.hide(); } }); row.cells = cells; }; return row; } //generate stats row generateRowData(pos, data) { var rowData = {}, calcs = pos == "top" ? this.topCalcs : this.botCalcs, type = pos == "top" ? "topCalc" : "botCalc", params, paramKey; calcs.forEach(function (column) { var values = []; if (column.modules.columnCalcs && column.modules.columnCalcs[type]) { data.forEach(function (item) { values.push(column.getFieldValue(item)); }); paramKey = type + "Params"; params = typeof column.modules.columnCalcs[paramKey] === "function" ? column.modules.columnCalcs[paramKey](values, data) : column.modules.columnCalcs[paramKey]; column.setFieldValue(rowData, column.modules.columnCalcs[type](values, data, params)); } }); return rowData; } hasTopCalcs() { return !!this.topCalcs.length; } hasBottomCalcs() { return !!this.botCalcs.length; } //handle table redraw redraw() { if (this.topRow) { this.topRow.normalizeHeight(true); } if (this.botRow) { this.botRow.normalizeHeight(true); } } //return the calculated getResults() { var results = {}, groups; if (this.table.options.groupBy && this.table.modExists("groupRows")) { groups = this.table.modules.groupRows.getGroups(true); groups.forEach((group) => { results[group.getKey()] = this.getGroupResults(group); }); } else { results = { top: this.topRow ? this.topRow.getData() : {}, bottom: this.botRow ? this.botRow.getData() : {} }; } return results; } //get results from a group getGroupResults(group) { var groupObj = group._getSelf(), subGroups = group.getSubGroups(), subGroupResults = {}, results = {}; subGroups.forEach((subgroup) => { subGroupResults[subgroup.getKey()] = this.getGroupResults(subgroup); }); results = { top: groupObj.calcs.top ? groupObj.calcs.top.getData() : {}, bottom: groupObj.calcs.bottom ? groupObj.calcs.bottom.getData() : {}, groups: subGroupResults }; return results; } adjustForScrollbar(width) { if (this.botRow) { if (this.table.rtl) { this.botElement.style.paddingLeft = width + "px"; } else { this.botElement.style.paddingRight = width + "px"; } } } }; __publicField(_ColumnCalcs, "moduleName", "columnCalcs"); //load defaults __publicField(_ColumnCalcs, "calculations", defaultCalculations); let ColumnCalcs = _ColumnCalcs; class DataTree extends Module { constructor(table) { super(table); this.indent = 10; this.field = ""; this.collapseEl = null; this.expandEl = null; this.branchEl = null; this.elementField = false; this.startOpen = function () { }; this.registerTableOption("dataTree", false); this.registerTableOption("dataTreeFilter", true); this.registerTableOption("dataTreeSort", true); this.registerTableOption("dataTreeElementColumn", false); this.registerTableOption("dataTreeBranchElement", true); this.registerTableOption("dataTreeChildIndent", 9); this.registerTableOption("dataTreeChildField", "_children"); this.registerTableOption("dataTreeCollapseElement", false); this.registerTableOption("dataTreeExpandElement", false); this.registerTableOption("dataTreeStartExpanded", false); this.registerTableOption("dataTreeChildColumnCalcs", false); this.registerTableOption("dataTreeSelectPropagate", false); this.registerComponentFunction("row", "treeCollapse", this.collapseRow.bind(this)); this.registerComponentFunction("row", "treeExpand", this.expandRow.bind(this)); this.registerComponentFunction("row", "treeToggle", this.toggleRow.bind(this)); this.registerComponentFunction("row", "getTreeParent", this.getTreeParent.bind(this)); this.registerComponentFunction("row", "getTreeChildren", this.getRowChildren.bind(this)); this.registerComponentFunction("row", "addTreeChild", this.addTreeChildRow.bind(this)); this.registerComponentFunction("row", "isTreeExpanded", this.isRowExpanded.bind(this)); } initialize() { if (this.table.options.dataTree) { var dummyEl = null, options = this.table.options; this.field = options.dataTreeChildField; this.indent = options.dataTreeChildIndent; if (this.options("movableRows")) { console.warn("The movableRows option is not available with dataTree enabled, moving of child rows could result in unpredictable behavior"); } if (options.dataTreeBranchElement) { if (options.dataTreeBranchElement === true) { this.branchEl = document.createElement("div"); this.branchEl.classList.add("tabulator-data-tree-branch"); } else { if (typeof options.dataTreeBranchElement === "string") { dummyEl = document.createElement("div"); dummyEl.innerHTML = options.dataTreeBranchElement; this.branchEl = dummyEl.firstChild; } else { this.branchEl = options.dataTreeBranchElement; } } } else { this.branchEl = document.createElement("div"); this.branchEl.classList.add("tabulator-data-tree-branch-empty"); } if (options.dataTreeCollapseElement) { if (typeof options.dataTreeCollapseElement === "string") { dummyEl = document.createElement("div"); dummyEl.innerHTML = options.dataTreeCollapseElement; this.collapseEl = dummyEl.firstChild; } else { this.collapseEl = options.dataTreeCollapseElement; } } else { this.collapseEl = document.createElement("div"); this.collapseEl.classList.add("tabulator-data-tree-control"); this.collapseEl.tabIndex = 0; this.collapseEl.innerHTML = ""; } if (options.dataTreeExpandElement) { if (typeof options.dataTreeExpandElement === "string") { dummyEl = document.createElement("div"); dummyEl.innerHTML = options.dataTreeExpandElement; this.expandEl = dummyEl.firstChild; } else { this.expandEl = options.dataTreeExpandElement; } } else { this.expandEl = document.createElement("div"); this.expandEl.classList.add("tabulator-data-tree-control"); this.expandEl.tabIndex = 0; this.expandEl.innerHTML = ""; } switch (typeof options.dataTreeStartExpanded) { case "boolean": this.startOpen = function (row, index) { return options.dataTreeStartExpanded; }; break; case "function": this.startOpen = options.dataTreeStartExpanded; break; default: this.startOpen = function (row, index) { return options.dataTreeStartExpanded[index]; }; break; } this.subscribe("row-init", this.initializeRow.bind(this)); this.subscribe("row-layout-after", this.layoutRow.bind(this)); this.subscribe("row-deleting", this.rowDeleting.bind(this)); this.subscribe("row-deleted", this.rowDelete.bind(this), 0); this.subscribe("row-data-changed", this.rowDataChanged.bind(this), 10); this.subscribe("cell-value-updated", this.cellValueChanged.bind(this)); this.subscribe("edit-cancelled", this.cellValueChanged.bind(this)); this.subscribe("column-moving-rows", this.columnMoving.bind(this)); this.subscribe("table-built", this.initializeElementField.bind(this)); this.subscribe("table-redrawing", this.tableRedrawing.bind(this)); this.registerDisplayHandler(this.getRows.bind(this), 30); } } tableRedrawing(force) { var rows2; if (force) { rows2 = this.table.rowManager.getRows(); rows2.forEach((row) => { this.reinitializeRowChildren(row); }); } } initializeElementField() { var firstCol = this.table.columnManager.getFirstVisibleColumn(); this.elementField = this.table.options.dataTreeElementColumn || (firstCol ? firstCol.field : false); } getRowChildren(row) { return this.getTreeChildren(row, true); } columnMoving() { var rows2 = []; this.table.rowManager.rows.forEach((row) => { rows2 = rows2.concat(this.getTreeChildren(row, false, true)); }); return rows2; } rowDataChanged(row, visible, updatedData) { if (this.redrawNeeded(updatedData)) { this.initializeRow(row); if (visible) { this.layoutRow(row); this.refreshData(true); } } } cellValueChanged(cell) { var field = cell.column.getField(); if (field === this.elementField) { this.layoutRow(cell.row); } } initializeRow(row) { var childArray = row.getData()[this.field]; var isArray = Array.isArray(childArray); var children = isArray || !isArray && typeof childArray === "object" && childArray !== null; if (!children && row.modules.dataTree && row.modules.dataTree.branchEl && row.modules.dataTree.branchEl.parentNode) { row.modules.dataTree.branchEl.parentNode.removeChild(row.modules.dataTree.branchEl); } if (!children && row.modules.dataTree && row.modules.dataTree.controlEl && row.modules.dataTree.controlEl.parentNode) { row.modules.dataTree.controlEl.parentNode.removeChild(row.modules.dataTree.controlEl); } row.modules.dataTree = { index: row.modules.dataTree ? row.modules.dataTree.index : 0, open: children ? row.modules.dataTree ? row.modules.dataTree.open : this.startOpen(row.getComponent(), 0) : false, controlEl: row.modules.dataTree && children ? row.modules.dataTree.controlEl : false, branchEl: row.modules.dataTree && children ? row.modules.dataTree.branchEl : false, parent: row.modules.dataTree ? row.modules.dataTree.parent : false, children }; } reinitializeRowChildren(row) { var children = this.getTreeChildren(row, false, true); children.forEach(function (child) { child.reinitialize(true); }); } layoutRow(row) { var cell = this.elementField ? row.getCell(this.elementField) : row.getCells()[0], el = cell.getElement(), config = row.modules.dataTree; if (config.branchEl) { if (config.branchEl.parentNode) { config.branchEl.parentNode.removeChild(config.branchEl); } config.branchEl = false; } if (config.controlEl) { if (config.controlEl.parentNode) { config.controlEl.parentNode.removeChild(config.controlEl); } config.controlEl = false; } this.generateControlElement(row, el); row.getElement().classList.add("tabulator-tree-level-" + config.index); if (config.index) { if (this.branchEl) { config.branchEl = this.branchEl.cloneNode(true); el.insertBefore(config.branchEl, el.firstChild); if (this.table.rtl) { config.branchEl.style.marginRight = (config.branchEl.offsetWidth + config.branchEl.style.marginLeft) * (config.index - 1) + config.index * this.indent + "px"; } else { config.branchEl.style.marginLeft = (config.branchEl.offsetWidth + config.branchEl.style.marginRight) * (config.index - 1) + config.index * this.indent + "px"; } } else { if (this.table.rtl) { el.style.paddingRight = parseInt(window.getComputedStyle(el, null).getPropertyValue("padding-right")) + config.index * this.indent + "px"; } else { el.style.paddingLeft = parseInt(window.getComputedStyle(el, null).getPropertyValue("padding-left")) + config.index * this.indent + "px"; } } } } generateControlElement(row, el) { var config = row.modules.dataTree, oldControl = config.controlEl; el = el || row.getCells()[0].getElement(); if (config.children !== false) { if (config.open) { config.controlEl = this.collapseEl.cloneNode(true); config.controlEl.addEventListener("click", (e) => { e.stopPropagation(); this.collapseRow(row); }); } else { config.controlEl = this.expandEl.cloneNode(true); config.controlEl.addEventListener("click", (e) => { e.stopPropagation(); this.expandRow(row); }); } config.controlEl.addEventListener("mousedown", (e) => { e.stopPropagation(); }); if (oldControl && oldControl.parentNode === el) { oldControl.parentNode.replaceChild(config.controlEl, oldControl); } else { el.insertBefore(config.controlEl, el.firstChild); } } } getRows(rows2) { var output = []; rows2.forEach((row, i) => { var config, children; output.push(row); if (row instanceof Row) { row.create(); config = row.modules.dataTree; if (!config.index && config.children !== false) { children = this.getChildren(row, false, true); children.forEach((child) => { child.create(); output.push(child); }); } } }); return output; } getChildren(row, allChildren, sortOnly) { var config = row.modules.dataTree, children = [], output = []; if (config.children !== false && (config.open || allChildren)) { if (!Array.isArray(config.children)) { config.children = this.generateChildren(row); } if (this.table.modExists("filter") && this.table.options.dataTreeFilter) { children = this.table.modules.filter.filter(config.children); } else { children = config.children; } if (this.table.modExists("sort") && this.table.options.dataTreeSort) { this.table.modules.sort.sort(children, sortOnly); } children.forEach((child) => { output.push(child); var subChildren = this.getChildren(child, false, true); subChildren.forEach((sub) => { output.push(sub); }); }); } return output; } generateChildren(row) { var children = []; var childArray = row.getData()[this.field]; if (!Array.isArray(childArray)) { childArray = [childArray]; } childArray.forEach((childData) => { var childRow = new Row(childData || {}, this.table.rowManager); childRow.create(); childRow.modules.dataTree.index = row.modules.dataTree.index + 1; childRow.modules.dataTree.parent = row; if (childRow.modules.dataTree.children) { childRow.modules.dataTree.open = this.startOpen(childRow.getComponent(), childRow.modules.dataTree.index); } children.push(childRow); }); return children; } expandRow(row, silent) { var config = row.modules.dataTree; if (config.children !== false) { config.open = true; row.reinitialize(); this.refreshData(true); this.dispatchExternal("dataTreeRowExpanded", row.getComponent(), row.modules.dataTree.index); } } collapseRow(row) { var config = row.modules.dataTree; if (config.children !== false) { config.open = false; row.reinitialize(); this.refreshData(true); this.dispatchExternal("dataTreeRowCollapsed", row.getComponent(), row.modules.dataTree.index); } } toggleRow(row) { var config = row.modules.dataTree; if (config.children !== false) { if (config.open) { this.collapseRow(row); } else { this.expandRow(row); } } } isRowExpanded(row) { return row.modules.dataTree.open; } getTreeParent(row) { return row.modules.dataTree.parent ? row.modules.dataTree.parent.getComponent() : false; } getTreeParentRoot(row) { return row.modules.dataTree && row.modules.dataTree.parent ? this.getTreeParentRoot(row.modules.dataTree.parent) : row; } getFilteredTreeChildren(row) { var config = row.modules.dataTree, output = [], children; if (config.children) { if (!Array.isArray(config.children)) { config.children = this.generateChildren(row); } if (this.table.modExists("filter") && this.table.options.dataTreeFilter) { children = this.table.modules.filter.filter(config.children); } else { children = config.children; } children.forEach((childRow) => { if (childRow instanceof Row) { output.push(childRow); } }); } return output; } rowDeleting(row) { var config = row.modules.dataTree; if (config && config.children && Array.isArray(config.children)) { config.children.forEach((childRow) => { if (childRow instanceof Row) { childRow.wipe(); } }); } } rowDelete(row) { var parent2 = row.modules.dataTree.parent, childIndex; if (parent2) { childIndex = this.findChildIndex(row, parent2); if (childIndex !== false) { parent2.data[this.field].splice(childIndex, 1); } if (!parent2.data[this.field].length) { delete parent2.data[this.field]; } this.initializeRow(parent2); this.layoutRow(parent2); } this.refreshData(true); } addTreeChildRow(row, data, top, index) { var childIndex = false; if (typeof data === "string") { data = JSON.parse(data); } if (!Array.isArray(row.data[this.field])) { row.data[this.field] = []; row.modules.dataTree.open = this.startOpen(row.getComponent(), row.modules.dataTree.index); } if (typeof index !== "undefined") { childIndex = this.findChildIndex(index, row); if (childIndex !== false) { row.data[this.field].splice(top ? childIndex : childIndex + 1, 0, data); } } if (childIndex === false) { if (top) { row.data[this.field].unshift(data); } else { row.data[this.field].push(data); } } this.initializeRow(row); this.layoutRow(row); this.refreshData(true); } findChildIndex(subject, parent2) { var match = false; if (typeof subject == "object") { if (subject instanceof Row) { match = subject.data; } else if (subject instanceof RowComponent) { match = subject._getSelf().data; } else if (typeof HTMLElement !== "undefined" && subject instanceof HTMLElement) { if (parent2.modules.dataTree) { match = parent2.modules.dataTree.children.find((childRow) => { return childRow instanceof Row ? childRow.element === subject : false; }); if (match) { match = match.data; } } } else if (subject === null) { match = false; } } else if (typeof subject == "undefined") { match = false; } else { match = parent2.data[this.field].find((row) => { return row.data[this.table.options.index] == subject; }); } if (match) { if (Array.isArray(parent2.data[this.field])) { match = parent2.data[this.field].indexOf(match); } if (match == -1) { match = false; } } return match; } getTreeChildren(row, component, recurse) { var config = row.modules.dataTree, output = []; if (config && config.children) { if (!Array.isArray(config.children)) { config.children = this.generateChildren(row); } config.children.forEach((childRow) => { if (childRow instanceof Row) { output.push(component ? childRow.getComponent() : childRow); if (recurse) { this.getTreeChildren(childRow, component, recurse).forEach((child) => { output.push(child); }); } } }); } return output; } getChildField() { return this.field; } redrawNeeded(data) { return (this.field ? typeof data[this.field] !== "undefined" : false) || (this.elementField ? typeof data[this.elementField] !== "undefined" : false); } } __publicField(DataTree, "moduleName", "dataTree"); function csv$1(list2, options = {}, setFileContents) { var delimiter = options.delimiter ? options.delimiter : ",", fileContents = [], headers = []; list2.forEach((row) => { var item = []; switch (row.type) { case "group": console.warn("Download Warning - CSV downloader cannot process row groups"); break; case "calc": console.warn("Download Warning - CSV downloader cannot process column calculations"); break; case "header": row.columns.forEach((col, i) => { if (col && col.depth === 1) { headers[i] = typeof col.value == "undefined" || col.value === null ? "" : '"' + String(col.value).split('"').join('""') + '"'; } }); break; case "row": row.columns.forEach((col) => { if (col) { switch (typeof col.value) { case "object": col.value = col.value !== null ? JSON.stringify(col.value) : ""; break; case "undefined": col.value = ""; break; } item.push('"' + String(col.value).split('"').join('""') + '"'); } }); fileContents.push(item.join(delimiter)); break; } }); if (headers.length) { fileContents.unshift(headers.join(delimiter)); } fileContents = fileContents.join("\n"); if (options.bom) { fileContents = "\uFEFF" + fileContents; } setFileContents(fileContents, "text/csv"); } function json$2(list2, options, setFileContents) { var fileContents = []; list2.forEach((row) => { var item = {}; switch (row.type) { case "header": break; case "group": console.warn("Download Warning - JSON downloader cannot process row groups"); break; case "calc": console.warn("Download Warning - JSON downloader cannot process column calculations"); break; case "row": row.columns.forEach((col) => { if (col) { item[col.component.getTitleDownload() || col.component.getField()] = col.value; } }); fileContents.push(item); break; } }); fileContents = JSON.stringify(fileContents, null, " "); setFileContents(fileContents, "application/json"); } function pdf(list2, options = {}, setFileContents) { var header = [], body = [], autoTableParams = {}, rowGroupStyles = options.rowGroupStyles || { fontStyle: "bold", fontSize: 12, cellPadding: 6, fillColor: 220 }, rowCalcStyles = options.rowCalcStyles || { fontStyle: "bold", fontSize: 10, cellPadding: 4, fillColor: 232 }, jsPDFParams = options.jsPDF || {}, title = options.title ? options.title : "", jspdfLib, doc; if (!jsPDFParams.orientation) { jsPDFParams.orientation = options.orientation || "landscape"; } if (!jsPDFParams.unit) { jsPDFParams.unit = "pt"; } list2.forEach((row) => { switch (row.type) { case "header": header.push(parseRow(row)); break; case "group": body.push(parseRow(row, rowGroupStyles)); break; case "calc": body.push(parseRow(row, rowCalcStyles)); break; case "row": body.push(parseRow(row)); break; } }); function parseRow(row, styles) { var rowData = []; row.columns.forEach((col) => { var cell; if (col) { switch (typeof col.value) { case "object": col.value = col.value !== null ? JSON.stringify(col.value) : ""; break; case "undefined": col.value = ""; break; } cell = { content: col.value, colSpan: col.width, rowSpan: col.height }; if (styles) { cell.styles = styles; } rowData.push(cell); } }); return rowData; } jspdfLib = this.dependencyRegistry.lookup("jspdf", "jsPDF"); doc = new jspdfLib(jsPDFParams); if (options.autoTable) { if (typeof options.autoTable === "function") { autoTableParams = options.autoTable(doc) || {}; } else { autoTableParams = options.autoTable; } } if (title) { autoTableParams.didDrawPage = function (data) { doc.text(title, 40, 30); }; } autoTableParams.head = header; autoTableParams.body = body; doc.autoTable(autoTableParams); if (options.documentProcessing) { options.documentProcessing(doc); } setFileContents(doc.output("arraybuffer"), "application/pdf"); } function xlsx$1(list2, options, setFileContents) { var self = this, sheetName = options.sheetName || "Sheet1", XLSXLib = this.dependencyRegistry.lookup("XLSX"), workbook = XLSXLib.utils.book_new(), tableFeatures = new CoreFeature(this), compression = "compress" in options ? options.compress : true, writeOptions = options.writeOptions || {bookType: "xlsx", bookSST: true, compression}, output; writeOptions.type = "binary"; workbook.SheetNames = []; workbook.Sheets = {}; function generateSheet() { var rows2 = [], merges = [], worksheet = {}, range2 = { s: {c: 0, r: 0}, e: { c: list2[0] ? list2[0].columns.reduce((a, b) => a + (b && b.width ? b.width : 1), 0) : 0, r: list2.length } }; list2.forEach((row, i) => { var rowData = []; row.columns.forEach(function (col, j) { if (col) { rowData.push(!(col.value instanceof Date) && typeof col.value === "object" ? JSON.stringify(col.value) : col.value); if (col.width > 1 || col.height > -1) { if (col.height > 1 || col.width > 1) { merges.push({s: {r: i, c: j}, e: {r: i + col.height - 1, c: j + col.width - 1}}); } } } else { rowData.push(""); } }); rows2.push(rowData); }); XLSXLib.utils.sheet_add_aoa(worksheet, rows2); worksheet["!ref"] = XLSXLib.utils.encode_range(range2); if (merges.length) { worksheet["!merges"] = merges; } return worksheet; } if (options.sheetOnly) { setFileContents(generateSheet()); return; } if (options.sheets) { for (var sheet in options.sheets) { if (options.sheets[sheet] === true) { workbook.SheetNames.push(sheet); workbook.Sheets[sheet] = generateSheet(); } else { workbook.SheetNames.push(sheet); tableFeatures.commsSend(options.sheets[sheet], "download", "intercept", { type: "xlsx", options: {sheetOnly: true}, active: self.active, intercept: function (data) { workbook.Sheets[sheet] = data; } }); } } } else { workbook.SheetNames.push(sheetName); workbook.Sheets[sheetName] = generateSheet(); } if (options.documentProcessing) { workbook = options.documentProcessing(workbook); } function s2ab(s) { var buf = new ArrayBuffer(s.length); var view = new Uint8Array(buf); for (var i = 0; i != s.length; ++i) view[i] = s.charCodeAt(i) & 255; return buf; } output = XLSXLib.write(workbook, writeOptions); setFileContents(s2ab(output), "application/octet-stream"); } function html$1(list2, options, setFileContents) { if (this.modExists("export", true)) { setFileContents(this.modules.export.generateHTMLTable(list2), "text/html"); } } function jsonLines(list2, options, setFileContents) { const fileContents = []; list2.forEach((row) => { const item = {}; switch (row.type) { case "header": break; case "group": console.warn("Download Warning - JSON downloader cannot process row groups"); break; case "calc": console.warn("Download Warning - JSON downloader cannot process column calculations"); break; case "row": row.columns.forEach((col) => { if (col) { item[col.component.getTitleDownload() || col.component.getField()] = col.value; } }); fileContents.push(JSON.stringify(item)); break; } }); setFileContents(fileContents.join("\n"), "application/x-ndjson"); } var defaultDownloaders = { csv: csv$1, json: json$2, jsonLines, pdf, xlsx: xlsx$1, html: html$1 }; const _Download = class _Download extends Module { constructor(table) { super(table); this.registerTableOption("downloadEncoder", function (data, mimeType) { return new Blob([data], {type: mimeType}); }); this.registerTableOption("downloadConfig", {}); this.registerTableOption("downloadRowRange", "active"); this.registerColumnOption("download"); this.registerColumnOption("titleDownload"); } initialize() { this.deprecatedOptionsCheck(); this.registerTableFunction("download", this.download.bind(this)); this.registerTableFunction("downloadToTab", this.downloadToTab.bind(this)); } deprecatedOptionsCheck() { } /////////////////////////////////// ///////// Table Functions ///////// /////////////////////////////////// downloadToTab(type, filename, options, active) { this.download(type, filename, options, active, true); } /////////////////////////////////// ///////// Internal Logic ////////// /////////////////////////////////// //trigger file download download(type, filename, options, range2, interceptCallback) { var downloadFunc = false; function buildLink(data, mime) { if (interceptCallback) { if (interceptCallback === true) { this.triggerDownload(data, mime, type, filename, true); } else { interceptCallback(data); } } else { this.triggerDownload(data, mime, type, filename); } } if (typeof type == "function") { downloadFunc = type; } else { if (_Download.downloaders[type]) { downloadFunc = _Download.downloaders[type]; } else { console.warn("Download Error - No such download type found: ", type); } } if (downloadFunc) { var list2 = this.generateExportList(range2); downloadFunc.call(this.table, list2, options || {}, buildLink.bind(this)); } } generateExportList(range2) { var list2 = this.table.modules.export.generateExportList(this.table.options.downloadConfig, false, range2 || this.table.options.downloadRowRange, "download"); var groupHeader = this.table.options.groupHeaderDownload; if (groupHeader && !Array.isArray(groupHeader)) { groupHeader = [groupHeader]; } list2.forEach((row) => { var group; if (row.type === "group") { group = row.columns[0]; if (groupHeader && groupHeader[row.indent]) { group.value = groupHeader[row.indent](group.value, row.component._group.getRowCount(), row.component._group.getData(), row.component); } } }); return list2; } triggerDownload(data, mime, type, filename, newTab) { var element = document.createElement("a"), blob = this.table.options.downloadEncoder(data, mime); if (blob) { if (newTab) { window.open(window.URL.createObjectURL(blob)); } else { filename = filename || "Tabulator." + (typeof type === "function" ? "txt" : type); if (navigator.msSaveOrOpenBlob) { navigator.msSaveOrOpenBlob(blob, filename); } else { element.setAttribute("href", window.URL.createObjectURL(blob)); element.setAttribute("download", filename); element.style.display = "none"; document.body.appendChild(element); element.click(); document.body.removeChild(element); } } this.dispatchExternal("downloadComplete"); } } commsReceived(table, action, data) { switch (action) { case "intercept": this.download(data.type, "", data.options, data.active, data.intercept); break; } } }; __publicField(_Download, "moduleName", "download"); //load defaults __publicField(_Download, "downloaders", defaultDownloaders); let Download = _Download; function maskInput(el, options) { var mask = options.mask, maskLetter = typeof options.maskLetterChar !== "undefined" ? options.maskLetterChar : "A", maskNumber = typeof options.maskNumberChar !== "undefined" ? options.maskNumberChar : "9", maskWildcard = typeof options.maskWildcardChar !== "undefined" ? options.maskWildcardChar : "*"; function fillSymbols(index) { var symbol = mask[index]; if (typeof symbol !== "undefined" && symbol !== maskWildcard && symbol !== maskLetter && symbol !== maskNumber) { el.value = el.value + "" + symbol; fillSymbols(index + 1); } } el.addEventListener("keydown", (e) => { var index = el.value.length, char = e.key; if (e.key.length === 1 && !e.ctrlKey && !e.metaKey) { if (index >= mask.length) { e.preventDefault(); e.stopPropagation(); return false; } else { switch (mask[index]) { case maskLetter: if (char.toUpperCase() == char.toLowerCase()) { e.preventDefault(); e.stopPropagation(); return false; } break; case maskNumber: if (isNaN(char)) { e.preventDefault(); e.stopPropagation(); return false; } break; case maskWildcard: break; default: if (char !== mask[index]) { e.preventDefault(); e.stopPropagation(); return false; } } } } return; }); el.addEventListener("keyup", (e) => { if (e.key.length === 1) { if (options.maskAutoFill) { fillSymbols(el.value.length); } } }); if (!el.placeholder) { el.placeholder = mask; } if (options.maskAutoFill) { fillSymbols(el.value.length); } } function input(cell, onRendered, success, cancel, editorParams) { var cellValue = cell.getValue(), input2 = document.createElement("input"); input2.setAttribute("type", editorParams.search ? "search" : "text"); input2.style.padding = "4px"; input2.style.width = "100%"; input2.style.boxSizing = "border-box"; if (editorParams.elementAttributes && typeof editorParams.elementAttributes == "object") { for (let key in editorParams.elementAttributes) { if (key.charAt(0) == "+") { key = key.slice(1); input2.setAttribute(key, input2.getAttribute(key) + editorParams.elementAttributes["+" + key]); } else { input2.setAttribute(key, editorParams.elementAttributes[key]); } } } input2.value = typeof cellValue !== "undefined" ? cellValue : ""; onRendered(function () { if (cell.getType() === "cell") { input2.focus({preventScroll: true}); input2.style.height = "100%"; if (editorParams.selectContents) { input2.select(); } } }); function onChange(e) { if ((cellValue === null || typeof cellValue === "undefined") && input2.value !== "" || input2.value !== cellValue) { if (success(input2.value)) { cellValue = input2.value; } } else { cancel(); } } input2.addEventListener("change", onChange); input2.addEventListener("blur", onChange); input2.addEventListener("keydown", function (e) { switch (e.key) { // case "Tab": case "Enter": onChange(); break; case "Escape": cancel(); break; case "End": case "Home": e.stopPropagation(); break; } }); if (editorParams.mask) { maskInput(input2, editorParams); } return input2; } function textarea$1(cell, onRendered, success, cancel, editorParams) { var cellValue = cell.getValue(), vertNav = editorParams.verticalNavigation || "hybrid", value = String(cellValue !== null && typeof cellValue !== "undefined" ? cellValue : ""), input2 = document.createElement("textarea"), scrollHeight = 0; input2.style.display = "block"; input2.style.padding = "2px"; input2.style.height = "100%"; input2.style.width = "100%"; input2.style.boxSizing = "border-box"; input2.style.whiteSpace = "pre-wrap"; input2.style.resize = "none"; if (editorParams.elementAttributes && typeof editorParams.elementAttributes == "object") { for (let key in editorParams.elementAttributes) { if (key.charAt(0) == "+") { key = key.slice(1); input2.setAttribute(key, input2.getAttribute(key) + editorParams.elementAttributes["+" + key]); } else { input2.setAttribute(key, editorParams.elementAttributes[key]); } } } input2.value = value; onRendered(function () { if (cell.getType() === "cell") { input2.focus({preventScroll: true}); input2.style.height = "100%"; input2.scrollHeight; input2.style.height = input2.scrollHeight + "px"; cell.getRow().normalizeHeight(); if (editorParams.selectContents) { input2.select(); } } }); function onChange(e) { if ((cellValue === null || typeof cellValue === "undefined") && input2.value !== "" || input2.value !== cellValue) { if (success(input2.value)) { cellValue = input2.value; } setTimeout(function () { cell.getRow().normalizeHeight(); }, 300); } else { cancel(); } } input2.addEventListener("change", onChange); input2.addEventListener("blur", onChange); input2.addEventListener("keyup", function () { input2.style.height = ""; var heightNow = input2.scrollHeight; input2.style.height = heightNow + "px"; if (heightNow != scrollHeight) { scrollHeight = heightNow; cell.getRow().normalizeHeight(); } }); input2.addEventListener("keydown", function (e) { switch (e.key) { case "Enter": if (e.shiftKey && editorParams.shiftEnterSubmit) { onChange(); } break; case "Escape": cancel(); break; case "ArrowUp": if (vertNav == "editor" || vertNav == "hybrid" && input2.selectionStart) { e.stopImmediatePropagation(); e.stopPropagation(); } break; case "ArrowDown": if (vertNav == "editor" || vertNav == "hybrid" && input2.selectionStart !== input2.value.length) { e.stopImmediatePropagation(); e.stopPropagation(); } break; case "End": case "Home": e.stopPropagation(); break; } }); if (editorParams.mask) { maskInput(input2, editorParams); } return input2; } function number$1(cell, onRendered, success, cancel, editorParams) { var cellValue = cell.getValue(), vertNav = editorParams.verticalNavigation || "editor", input2 = document.createElement("input"); input2.setAttribute("type", "number"); if (typeof editorParams.max != "undefined") { input2.setAttribute("max", editorParams.max); } if (typeof editorParams.min != "undefined") { input2.setAttribute("min", editorParams.min); } if (typeof editorParams.step != "undefined") { input2.setAttribute("step", editorParams.step); } input2.style.padding = "4px"; input2.style.width = "100%"; input2.style.boxSizing = "border-box"; if (editorParams.elementAttributes && typeof editorParams.elementAttributes == "object") { for (let key in editorParams.elementAttributes) { if (key.charAt(0) == "+") { key = key.slice(1); input2.setAttribute(key, input2.getAttribute(key) + editorParams.elementAttributes["+" + key]); } else { input2.setAttribute(key, editorParams.elementAttributes[key]); } } } input2.value = cellValue; var blurFunc = function (e) { onChange(); }; onRendered(function () { if (cell.getType() === "cell") { input2.removeEventListener("blur", blurFunc); input2.focus({preventScroll: true}); input2.style.height = "100%"; input2.addEventListener("blur", blurFunc); if (editorParams.selectContents) { input2.select(); } } }); function onChange() { var value = input2.value; if (!isNaN(value) && value !== "") { value = Number(value); } if (value !== cellValue) { if (success(value)) { cellValue = value; } } else { cancel(); } } input2.addEventListener("keydown", function (e) { switch (e.key) { case "Enter": onChange(); break; case "Escape": cancel(); break; case "ArrowUp": case "ArrowDown": if (vertNav == "editor") { e.stopImmediatePropagation(); e.stopPropagation(); } break; case "End": case "Home": e.stopPropagation(); break; } }); if (editorParams.mask) { maskInput(input2, editorParams); } return input2; } function range(cell, onRendered, success, cancel, editorParams) { var cellValue = cell.getValue(), input2 = document.createElement("input"); input2.setAttribute("type", "range"); if (typeof editorParams.max != "undefined") { input2.setAttribute("max", editorParams.max); } if (typeof editorParams.min != "undefined") { input2.setAttribute("min", editorParams.min); } if (typeof editorParams.step != "undefined") { input2.setAttribute("step", editorParams.step); } input2.style.padding = "4px"; input2.style.width = "100%"; input2.style.boxSizing = "border-box"; if (editorParams.elementAttributes && typeof editorParams.elementAttributes == "object") { for (let key in editorParams.elementAttributes) { if (key.charAt(0) == "+") { key = key.slice(1); input2.setAttribute(key, input2.getAttribute(key) + editorParams.elementAttributes["+" + key]); } else { input2.setAttribute(key, editorParams.elementAttributes[key]); } } } input2.value = cellValue; onRendered(function () { if (cell.getType() === "cell") { input2.focus({preventScroll: true}); input2.style.height = "100%"; } }); function onChange() { var value = input2.value; if (!isNaN(value) && value !== "") { value = Number(value); } if (value != cellValue) { if (success(value)) { cellValue = value; } } else { cancel(); } } input2.addEventListener("blur", function (e) { onChange(); }); input2.addEventListener("keydown", function (e) { switch (e.key) { case "Enter": onChange(); break; case "Escape": cancel(); break; } }); return input2; } function date$1(cell, onRendered, success, cancel, editorParams) { var inputFormat = editorParams.format, vertNav = editorParams.verticalNavigation || "editor", DT = inputFormat ? window.DateTime || luxon.DateTime : null; var cellValue = cell.getValue(), input2 = document.createElement("input"); function convertDate(value) { var newDatetime; if (DT.isDateTime(value)) { newDatetime = value; } else if (inputFormat === "x") { newDatetime = DT.fromMillis(value); } else if (inputFormat === "iso") { newDatetime = DT.fromISO(String(value)); } else { newDatetime = DT.fromFormat(String(value), inputFormat); } return newDatetime.toFormat("yyyy-MM-dd"); } input2.type = "date"; input2.style.padding = "4px"; input2.style.width = "100%"; input2.style.boxSizing = "border-box"; if (editorParams.max) { input2.setAttribute("max", inputFormat ? convertDate(editorParams.max) : editorParams.max); } if (editorParams.min) { input2.setAttribute("min", inputFormat ? convertDate(editorParams.min) : editorParams.min); } if (editorParams.elementAttributes && typeof editorParams.elementAttributes == "object") { for (let key in editorParams.elementAttributes) { if (key.charAt(0) == "+") { key = key.slice(1); input2.setAttribute(key, input2.getAttribute(key) + editorParams.elementAttributes["+" + key]); } else { input2.setAttribute(key, editorParams.elementAttributes[key]); } } } cellValue = typeof cellValue !== "undefined" ? cellValue : ""; if (inputFormat) { if (DT) { cellValue = convertDate(cellValue); } else { console.error("Editor Error - 'date' editor 'format' param is dependant on luxon.js"); } } input2.value = cellValue; onRendered(function () { if (cell.getType() === "cell") { input2.focus({preventScroll: true}); input2.style.height = "100%"; if (editorParams.selectContents) { input2.select(); } } }); function onChange() { var value = input2.value, luxDate; if ((cellValue === null || typeof cellValue === "undefined") && value !== "" || value !== cellValue) { if (value && inputFormat) { luxDate = DT.fromFormat(String(value), "yyyy-MM-dd"); switch (inputFormat) { case true: value = luxDate; break; case "x": value = luxDate.toMillis(); break; case "iso": value = luxDate.toISO(); break; default: value = luxDate.toFormat(inputFormat); } } if (success(value)) { cellValue = input2.value; } } else { cancel(); } } input2.addEventListener("blur", function (e) { if (e.relatedTarget || e.rangeParent || e.explicitOriginalTarget !== input2) { onChange(); } }); input2.addEventListener("keydown", function (e) { switch (e.key) { // case "Tab": case "Enter": onChange(); break; case "Escape": cancel(); break; case "End": case "Home": e.stopPropagation(); break; case "ArrowUp": case "ArrowDown": if (vertNav == "editor") { e.stopImmediatePropagation(); e.stopPropagation(); } break; } }); return input2; } function time$1(cell, onRendered, success, cancel, editorParams) { var inputFormat = editorParams.format, vertNav = editorParams.verticalNavigation || "editor", DT = inputFormat ? window.DateTime || luxon.DateTime : null, newDatetime; var cellValue = cell.getValue(), input2 = document.createElement("input"); input2.type = "time"; input2.style.padding = "4px"; input2.style.width = "100%"; input2.style.boxSizing = "border-box"; if (editorParams.elementAttributes && typeof editorParams.elementAttributes == "object") { for (let key in editorParams.elementAttributes) { if (key.charAt(0) == "+") { key = key.slice(1); input2.setAttribute(key, input2.getAttribute(key) + editorParams.elementAttributes["+" + key]); } else { input2.setAttribute(key, editorParams.elementAttributes[key]); } } } cellValue = typeof cellValue !== "undefined" ? cellValue : ""; if (inputFormat) { if (DT) { if (DT.isDateTime(cellValue)) { newDatetime = cellValue; } else if (inputFormat === "x") { newDatetime = DT.fromMillis(cellValue); } else if (inputFormat === "iso") { newDatetime = DT.fromISO(String(cellValue)); } else { newDatetime = DT.fromFormat(String(cellValue), inputFormat); } cellValue = newDatetime.toFormat("HH:mm"); } else { console.error("Editor Error - 'date' editor 'format' param is dependant on luxon.js"); } } input2.value = cellValue; onRendered(function () { if (cell.getType() == "cell") { input2.focus({preventScroll: true}); input2.style.height = "100%"; if (editorParams.selectContents) { input2.select(); } } }); function onChange() { var value = input2.value, luxTime; if ((cellValue === null || typeof cellValue === "undefined") && value !== "" || value !== cellValue) { if (value && inputFormat) { luxTime = DT.fromFormat(String(value), "hh:mm"); switch (inputFormat) { case true: value = luxTime; break; case "x": value = luxTime.toMillis(); break; case "iso": value = luxTime.toISO(); break; default: value = luxTime.toFormat(inputFormat); } } if (success(value)) { cellValue = input2.value; } } else { cancel(); } } input2.addEventListener("blur", function (e) { if (e.relatedTarget || e.rangeParent || e.explicitOriginalTarget !== input2) { onChange(); } }); input2.addEventListener("keydown", function (e) { switch (e.key) { // case "Tab": case "Enter": onChange(); break; case "Escape": cancel(); break; case "End": case "Home": e.stopPropagation(); break; case "ArrowUp": case "ArrowDown": if (vertNav == "editor") { e.stopImmediatePropagation(); e.stopPropagation(); } break; } }); return input2; } function datetime$2(cell, onRendered, success, cancel, editorParams) { var inputFormat = editorParams.format, vertNav = editorParams.verticalNavigation || "editor", DT = inputFormat ? this.table.dependencyRegistry.lookup(["luxon", "DateTime"], "DateTime") : null, newDatetime; var cellValue = cell.getValue(), input2 = document.createElement("input"); input2.type = "datetime-local"; input2.style.padding = "4px"; input2.style.width = "100%"; input2.style.boxSizing = "border-box"; if (editorParams.elementAttributes && typeof editorParams.elementAttributes == "object") { for (let key in editorParams.elementAttributes) { if (key.charAt(0) == "+") { key = key.slice(1); input2.setAttribute(key, input2.getAttribute(key) + editorParams.elementAttributes["+" + key]); } else { input2.setAttribute(key, editorParams.elementAttributes[key]); } } } cellValue = typeof cellValue !== "undefined" ? cellValue : ""; if (inputFormat) { if (DT) { if (DT.isDateTime(cellValue)) { newDatetime = cellValue; } else if (inputFormat === "x") { newDatetime = DT.fromMillis(cellValue); } else if (inputFormat === "iso") { newDatetime = DT.fromISO(String(cellValue)); } else { newDatetime = DT.fromFormat(String(cellValue), inputFormat); } cellValue = newDatetime.toFormat("yyyy-MM-dd") + "T" + newDatetime.toFormat("HH:mm"); } else { console.error("Editor Error - 'date' editor 'format' param is dependant on luxon.js"); } } input2.value = cellValue; onRendered(function () { if (cell.getType() === "cell") { input2.focus({preventScroll: true}); input2.style.height = "100%"; if (editorParams.selectContents) { input2.select(); } } }); function onChange() { var value = input2.value, luxDateTime; if ((cellValue === null || typeof cellValue === "undefined") && value !== "" || value !== cellValue) { if (value && inputFormat) { luxDateTime = DT.fromISO(String(value)); switch (inputFormat) { case true: value = luxDateTime; break; case "x": value = luxDateTime.toMillis(); break; case "iso": value = luxDateTime.toISO(); break; default: value = luxDateTime.toFormat(inputFormat); } } if (success(value)) { cellValue = input2.value; } } else { cancel(); } } input2.addEventListener("blur", function (e) { if (e.relatedTarget || e.rangeParent || e.explicitOriginalTarget !== input2) { onChange(); } }); input2.addEventListener("keydown", function (e) { switch (e.key) { // case "Tab": case "Enter": onChange(); break; case "Escape": cancel(); break; case "End": case "Home": e.stopPropagation(); break; case "ArrowUp": case "ArrowDown": if (vertNav == "editor") { e.stopImmediatePropagation(); e.stopPropagation(); } break; } }); return input2; } let Edit$1 = class Edit { constructor(editor, cell, onRendered, success, cancel, editorParams) { this.edit = editor; this.table = editor.table; this.cell = cell; this.params = this._initializeParams(editorParams); this.data = []; this.displayItems = []; this.currentItems = []; this.focusedItem = null; this.input = this._createInputElement(); this.listEl = this._createListElement(); this.initialValues = null; this.isFilter = cell.getType() === "header"; this.filterTimeout = null; this.filtered = false; this.typing = false; this.values = []; this.popup = null; this.listIteration = 0; this.lastAction = ""; this.filterTerm = ""; this.blurable = true; this.actions = { success, cancel }; this._deprecatedOptionsCheck(); this._initializeValue(); onRendered(this._onRendered.bind(this)); } _deprecatedOptionsCheck() { } _initializeValue() { var initialValue = this.cell.getValue(); if (typeof initialValue === "undefined" && typeof this.params.defaultValue !== "undefined") { initialValue = this.params.defaultValue; } this.initialValues = this.params.multiselect ? initialValue : [initialValue]; if (this.isFilter) { this.input.value = this.initialValues ? this.initialValues.join(",") : ""; this.headerFilterInitialListGen(); } } _onRendered() { var cellEl = this.cell.getElement(); function clickStop(e) { e.stopPropagation(); } if (!this.isFilter) { this.input.style.height = "100%"; this.input.focus({preventScroll: true}); } cellEl.addEventListener("click", clickStop); setTimeout(() => { cellEl.removeEventListener("click", clickStop); }, 1e3); this.input.addEventListener("mousedown", this._preventPopupBlur.bind(this)); } _createListElement() { var listEl = document.createElement("div"); listEl.classList.add("tabulator-edit-list"); listEl.addEventListener("mousedown", this._preventBlur.bind(this)); listEl.addEventListener("keydown", this._inputKeyDown.bind(this)); return listEl; } _setListWidth() { var element = this.isFilter ? this.input : this.cell.getElement(); this.listEl.style.minWidth = element.offsetWidth + "px"; if (this.params.maxWidth) { if (this.params.maxWidth === true) { this.listEl.style.maxWidth = element.offsetWidth + "px"; } else if (typeof this.params.maxWidth === "number") { this.listEl.style.maxWidth = this.params.maxWidth + "px"; } else { this.listEl.style.maxWidth = this.params.maxWidth; } } } _createInputElement() { var attribs = this.params.elementAttributes; var input2 = document.createElement("input"); input2.setAttribute("type", this.params.clearable ? "search" : "text"); input2.style.padding = "4px"; input2.style.width = "100%"; input2.style.boxSizing = "border-box"; if (!this.params.autocomplete) { input2.style.cursor = "default"; input2.style.caretColor = "transparent"; } if (attribs && typeof attribs == "object") { for (let key in attribs) { if (key.charAt(0) == "+") { key = key.slice(1); input2.setAttribute(key, input2.getAttribute(key) + attribs["+" + key]); } else { input2.setAttribute(key, attribs[key]); } } } if (this.params.mask) { maskInput(input2, this.params); } this._bindInputEvents(input2); return input2; } _initializeParams(params) { var valueKeys = ["values", "valuesURL", "valuesLookup"], valueCheck; params = Object.assign({}, params); params.verticalNavigation = params.verticalNavigation || "editor"; params.placeholderLoading = typeof params.placeholderLoading === "undefined" ? "Searching ..." : params.placeholderLoading; params.placeholderEmpty = typeof params.placeholderEmpty === "undefined" ? "No Results Found" : params.placeholderEmpty; params.filterDelay = typeof params.filterDelay === "undefined" ? 300 : params.filterDelay; params.emptyValue = Object.keys(params).includes("emptyValue") ? params.emptyValue : ""; valueCheck = Object.keys(params).filter((key) => valueKeys.includes(key)).length; if (!valueCheck) { console.warn("list editor config error - either the values, valuesURL, or valuesLookup option must be set"); } else if (valueCheck > 1) { console.warn("list editor config error - only one of the values, valuesURL, or valuesLookup options can be set on the same editor"); } if (params.autocomplete) { if (params.multiselect) { params.multiselect = false; console.warn("list editor config error - multiselect option is not available when autocomplete is enabled"); } } else { if (params.freetext) { params.freetext = false; console.warn("list editor config error - freetext option is only available when autocomplete is enabled"); } if (params.filterFunc) { params.filterFunc = false; console.warn("list editor config error - filterFunc option is only available when autocomplete is enabled"); } if (params.filterRemote) { params.filterRemote = false; console.warn("list editor config error - filterRemote option is only available when autocomplete is enabled"); } if (params.mask) { params.mask = false; console.warn("list editor config error - mask option is only available when autocomplete is enabled"); } if (params.allowEmpty) { params.allowEmpty = false; console.warn("list editor config error - allowEmpty option is only available when autocomplete is enabled"); } if (params.listOnEmpty) { params.listOnEmpty = false; console.warn("list editor config error - listOnEmpty option is only available when autocomplete is enabled"); } } if (params.filterRemote && !(typeof params.valuesLookup === "function" || params.valuesURL)) { params.filterRemote = false; console.warn("list editor config error - filterRemote option should only be used when values list is populated from a remote source"); } return params; } ////////////////////////////////////// ////////// Event Handling //////////// ////////////////////////////////////// _bindInputEvents(input2) { input2.addEventListener("focus", this._inputFocus.bind(this)); input2.addEventListener("click", this._inputClick.bind(this)); input2.addEventListener("blur", this._inputBlur.bind(this)); input2.addEventListener("keydown", this._inputKeyDown.bind(this)); input2.addEventListener("search", this._inputSearch.bind(this)); if (this.params.autocomplete) { input2.addEventListener("keyup", this._inputKeyUp.bind(this)); } } _inputFocus(e) { this.rebuildOptionsList(); } _filter() { if (this.params.filterRemote) { clearTimeout(this.filterTimeout); this.filterTimeout = setTimeout(() => { this.rebuildOptionsList(); }, this.params.filterDelay); } else { this._filterList(); } } _inputClick(e) { e.stopPropagation(); } _inputBlur(e) { if (this.blurable) { if (this.popup) { this.popup.hide(); } else { this._resolveValue(true); } } } _inputSearch() { this._clearChoices(); } _inputKeyDown(e) { switch (e.key) { case "ArrowUp": this._keyUp(e); break; case "ArrowDown": this._keyDown(e); break; case "ArrowLeft": case "ArrowRight": this._keySide(e); break; case "Enter": this._keyEnter(); break; case "Escape": this._keyEsc(); break; case "Home": case "End": this._keyHomeEnd(e); break; case "Tab": this._keyTab(e); break; default: this._keySelectLetter(e); } } _inputKeyUp(e) { switch (e.key) { case "ArrowUp": case "ArrowLeft": case "ArrowRight": case "ArrowDown": case "Enter": case "Escape": break; default: this._keyAutoCompLetter(e); } } _preventPopupBlur() { if (this.popup) { this.popup.blockHide(); } setTimeout(() => { if (this.popup) { this.popup.restoreHide(); } }, 10); } _preventBlur() { this.blurable = false; setTimeout(() => { this.blurable = true; }, 10); } ////////////////////////////////////// //////// Keyboard Navigation ///////// ////////////////////////////////////// _keyTab(e) { if (this.params.autocomplete && this.lastAction === "typing") { this._resolveValue(true); } else { if (this.focusedItem) { this._chooseItem(this.focusedItem, true); } } } _keyUp(e) { var index = this.displayItems.indexOf(this.focusedItem); if (this.params.verticalNavigation == "editor" || this.params.verticalNavigation == "hybrid" && index) { e.stopImmediatePropagation(); e.stopPropagation(); e.preventDefault(); if (index > 0) { this._focusItem(this.displayItems[index - 1]); } } } _keyDown(e) { var index = this.displayItems.indexOf(this.focusedItem); if (this.params.verticalNavigation == "editor" || this.params.verticalNavigation == "hybrid" && index < this.displayItems.length - 1) { e.stopImmediatePropagation(); e.stopPropagation(); e.preventDefault(); if (index < this.displayItems.length - 1) { if (index == -1) { this._focusItem(this.displayItems[0]); } else { this._focusItem(this.displayItems[index + 1]); } } } } _keySide(e) { if (!this.params.autocomplete) { e.stopImmediatePropagation(); e.stopPropagation(); e.preventDefault(); } } _keyEnter(e) { if (this.params.autocomplete && this.lastAction === "typing") { this._resolveValue(true); } else { if (this.focusedItem) { if (this.isFilter && !this.params.multiselect && this.focusedItem.selected) { this._resolveValue(); } else { this._chooseItem(this.focusedItem); } } } } _keyEsc(e) { this._cancel(); } _keyHomeEnd(e) { if (this.params.autocomplete) { e.stopImmediatePropagation(); } } _keySelectLetter(e) { if (!this.params.autocomplete) { e.preventDefault(); if (e.key.length === 1) { this._scrollToValue(e.key.toUpperCase().charCodeAt(0)); } } } _keyAutoCompLetter(e) { this._filter(); this.lastAction = "typing"; this.typing = true; } _scrollToValue(char) { clearTimeout(this.filterTimeout); var character = String.fromCharCode(char).toLowerCase(); this.filterTerm += character.toLowerCase(); var match = this.displayItems.find((item) => { return typeof item.label !== "undefined" && item.label.toLowerCase().startsWith(this.filterTerm); }); if (match) { this._focusItem(match); } this.filterTimeout = setTimeout(() => { this.filterTerm = ""; }, 800); } _focusItem(item) { this.lastAction = "focus"; if (this.focusedItem && this.focusedItem.element) { this.focusedItem.element.classList.remove("focused"); } this.focusedItem = item; if (item && item.element) { item.element.classList.add("focused"); item.element.scrollIntoView({behavior: "smooth", block: "nearest", inline: "start"}); } } ////////////////////////////////////// /////// Data List Generation ///////// ////////////////////////////////////// headerFilterInitialListGen() { this._generateOptions(true); } rebuildOptionsList() { this._generateOptions().then(this._sortOptions.bind(this)).then(this._buildList.bind(this)).then(this._showList.bind(this)).catch((e) => { if (!Number.isInteger(e)) { console.error("List generation error", e); } }); } _filterList() { this._buildList(this._filterOptions()); this._showList(); } _generateOptions(silent) { var values = []; var iteration = ++this.listIteration; this.filtered = false; if (this.params.values) { values = this.params.values; } else if (this.params.valuesURL) { values = this._ajaxRequest(this.params.valuesURL, this.input.value); } else { if (typeof this.params.valuesLookup === "function") { values = this.params.valuesLookup(this.cell, this.input.value); } else if (this.params.valuesLookup) { values = this._uniqueColumnValues(this.params.valuesLookupField); } } if (values instanceof Promise) { if (!silent) { this._addPlaceholder(this.params.placeholderLoading); } return values.then().then((responseValues) => { if (this.listIteration === iteration) { return this._parseList(responseValues); } else { return Promise.reject(iteration); } }); } else { return Promise.resolve(this._parseList(values)); } } _addPlaceholder(contents) { var placeholder = document.createElement("div"); if (typeof contents === "function") { contents = contents(this.cell.getComponent(), this.listEl); } if (contents) { this._clearList(); if (contents instanceof HTMLElement) { placeholder = contents; } else { placeholder.classList.add("tabulator-edit-list-placeholder"); placeholder.innerHTML = contents; } this.listEl.appendChild(placeholder); this._showList(); } } _ajaxRequest(url, term) { var params = this.params.filterRemote ? {term} : {}; url = urlBuilder(url, {}, params); return fetch(url).then((response) => { if (response.ok) { return response.json().catch((error) => { console.warn("List Ajax Load Error - Invalid JSON returned", error); return Promise.reject(error); }); } else { console.error("List Ajax Load Error - Connection Error: " + response.status, response.statusText); return Promise.reject(response); } }).catch((error) => { console.error("List Ajax Load Error - Connection Error: ", error); return Promise.reject(error); }); } _uniqueColumnValues(field) { var output = {}, data = this.table.getData(this.params.valuesLookup), column; if (field) { column = this.table.columnManager.getColumnByField(field); } else { column = this.cell.getColumn()._getSelf(); } if (column) { data.forEach((row) => { var val = column.getFieldValue(row); if (!this._emptyValueCheck(val)) { if (this.params.multiselect && Array.isArray(val)) { val.forEach((item) => { if (!this._emptyValueCheck(item)) { output[item] = true; } }); } else { output[val] = true; } } }); } else { console.warn("unable to find matching column to create select lookup list:", field); output = []; } return Object.keys(output); } _emptyValueCheck(value) { return value === null || typeof value === "undefined" || value === ""; } _parseList(inputValues) { var data = []; if (!Array.isArray(inputValues)) { inputValues = Object.entries(inputValues).map(([key, value]) => { return { label: value, value: key }; }); } inputValues.forEach((value) => { if (typeof value !== "object") { value = { label: value, value }; } this._parseListItem(value, data, 0); }); if (!this.currentItems.length && this.params.freetext) { this.input.value = this.initialValues; this.typing = true; this.lastAction = "typing"; } if (this.params.multiselect) { this.initialValues = null; } this.data = data; return data; } _parseListItem(option, data, level) { var item = {}; if (option.options) { item = this._parseListGroup(option, level + 1); } else { item = { label: option.label, value: option.value, itemParams: option.itemParams, elementAttributes: option.elementAttributes, element: false, selected: false, visible: true, level, original: option }; if (this.params.multiselect) { var existingIndex = this.currentItems.findIndex((existing) => existing.value === option.value); if (existingIndex > -1) { if (this.focusedItem === this.currentItems[existingIndex]) { this.focusedItem = item; } this.currentItems[existingIndex] = item; item.selected = true; } else if (this.initialValues && this.initialValues.indexOf(option.value) > -1) { this._chooseItem(item, true); } } else if (this.initialValues && this.initialValues.indexOf(option.value) > -1) { this._chooseItem(item, true); } } data.push(item); } _parseListGroup(option, level) { var item = { label: option.label, group: true, itemParams: option.itemParams, elementAttributes: option.elementAttributes, element: false, visible: true, level, options: [], original: option }; option.options.forEach((child) => { this._parseListItem(child, item.options, level); }); return item; } _sortOptions(options) { var sorter; if (this.params.sort) { sorter = typeof this.params.sort === "function" ? this.params.sort : this._defaultSortFunction.bind(this); this._sortGroup(sorter, options); } return options; } _sortGroup(sorter, options) { options.sort((a, b) => { return sorter(a.label, b.label, a.value, b.value, a.original, b.original); }); options.forEach((option) => { if (option.group) { this._sortGroup(sorter, option.options); } }); } _defaultSortFunction(as, bs) { var a, b, a1, b1, i = 0, L, rx = /(\d+)|(\D+)/g, rd = /\d/; var emptyAlign = 0; if (this.params.sort === "desc") { [as, bs] = [bs, as]; } if (!as && as !== 0) { emptyAlign = !bs && bs !== 0 ? 0 : -1; } else if (!bs && bs !== 0) { emptyAlign = 1; } else { if (isFinite(as) && isFinite(bs)) return as - bs; a = String(as).toLowerCase(); b = String(bs).toLowerCase(); if (a === b) return 0; if (!(rd.test(a) && rd.test(b))) return a > b ? 1 : -1; a = a.match(rx); b = b.match(rx); L = a.length > b.length ? b.length : a.length; while (i < L) { a1 = a[i]; b1 = b[i++]; if (a1 !== b1) { if (isFinite(a1) && isFinite(b1)) { if (a1.charAt(0) === "0") a1 = "." + a1; if (b1.charAt(0) === "0") b1 = "." + b1; return a1 - b1; } else return a1 > b1 ? 1 : -1; } } return a.length > b.length; } return emptyAlign; } _filterOptions() { var filterFunc = this.params.filterFunc || this._defaultFilterFunc, term = this.input.value; if (term) { this.filtered = true; this.data.forEach((item) => { this._filterItem(filterFunc, term, item); }); } else { this.filtered = false; } return this.data; } _filterItem(func, term, item) { var matches = false; if (!item.group) { item.visible = func(term, item.label, item.value, item.original); } else { item.options.forEach((option) => { if (this._filterItem(func, term, option)) { matches = true; } }); item.visible = matches; } return item.visible; } _defaultFilterFunc(term, label, value, item) { term = String(term).toLowerCase(); if (label !== null && typeof label !== "undefined") { if (String(label).toLowerCase().indexOf(term) > -1 || String(value).toLowerCase().indexOf(term) > -1) { return true; } } return false; } ////////////////////////////////////// /////////// Display List ///////////// ////////////////////////////////////// _clearList() { while (this.listEl.firstChild) this.listEl.removeChild(this.listEl.firstChild); this.displayItems = []; } _buildList(data) { this._clearList(); data.forEach((option) => { this._buildItem(option); }); if (!this.displayItems.length) { this._addPlaceholder(this.params.placeholderEmpty); } } _buildItem(item) { var el = item.element, contents; if (!this.filtered || item.visible) { if (!el) { el = document.createElement("div"); el.tabIndex = 0; contents = this.params.itemFormatter ? this.params.itemFormatter(item.label, item.value, item.original, el) : item.label; if (contents instanceof HTMLElement) { el.appendChild(contents); } else { el.innerHTML = contents; } if (item.group) { el.classList.add("tabulator-edit-list-group"); } else { el.classList.add("tabulator-edit-list-item"); } el.classList.add("tabulator-edit-list-group-level-" + item.level); if (item.elementAttributes && typeof item.elementAttributes == "object") { for (let key in item.elementAttributes) { if (key.charAt(0) == "+") { key = key.slice(1); el.setAttribute(key, this.input.getAttribute(key) + item.elementAttributes["+" + key]); } else { el.setAttribute(key, item.elementAttributes[key]); } } } if (item.group) { el.addEventListener("click", this._groupClick.bind(this, item)); } else { el.addEventListener("click", this._itemClick.bind(this, item)); } el.addEventListener("mousedown", this._preventBlur.bind(this)); item.element = el; } this._styleItem(item); this.listEl.appendChild(el); if (item.group) { item.options.forEach((option) => { this._buildItem(option); }); } else { this.displayItems.push(item); } } } _showList() { var startVis = this.popup && this.popup.isVisible(); if (this.input.parentNode) { if (this.params.autocomplete && this.input.value === "" && !this.params.listOnEmpty) { if (this.popup) { this.popup.hide(true); } return; } this._setListWidth(); if (!this.popup) { this.popup = this.edit.popup(this.listEl); } this.popup.show(this.cell.getElement(), "bottom"); if (!startVis) { setTimeout(() => { this.popup.hideOnBlur(this._resolveValue.bind(this, true)); }, 10); } } } _styleItem(item) { if (item && item.element) { if (item.selected) { item.element.classList.add("active"); } else { item.element.classList.remove("active"); } } } ////////////////////////////////////// ///////// User Interaction /////////// ////////////////////////////////////// _itemClick(item, e) { e.stopPropagation(); this._chooseItem(item); } _groupClick(item, e) { e.stopPropagation(); } ////////////////////////////////////// ////// Current Item Management /////// ////////////////////////////////////// _cancel() { this.popup.hide(true); this.actions.cancel(); } _clearChoices() { this.typing = true; this.currentItems.forEach((item) => { item.selected = false; this._styleItem(item); }); this.currentItems = []; this.focusedItem = null; } _chooseItem(item, silent) { var index; this.typing = false; if (this.params.multiselect) { index = this.currentItems.indexOf(item); if (index > -1) { this.currentItems.splice(index, 1); item.selected = false; } else { this.currentItems.push(item); item.selected = true; } this.input.value = this.currentItems.map((item2) => item2.label).join(","); this._styleItem(item); } else { if (this.isFilter && !silent && item.selected) { this._clearChoices(); this.input.value = ""; this._resolveValue(); return; } this.currentItems = [item]; item.selected = true; this.input.value = item.label; this._styleItem(item); if (!silent) { this._resolveValue(); } } this._focusItem(item); } _resolveValue(blur) { var output, initialValue; if (this.popup) { this.popup.hide(true); } if (this.params.multiselect) { output = this.currentItems.map((item) => item.value); } else { if (blur && this.params.autocomplete && this.typing) { if (this.params.freetext || this.params.allowEmpty && this.input.value === "") { output = this.input.value; } else { this.actions.cancel(); return; } } else { if (this.currentItems[0]) { output = this.currentItems[0].value; } else if (this.isFilter && this.focusedItem && this.focusedItem.selected) { output = this.focusedItem.value; } else { initialValue = Array.isArray(this.initialValues) ? this.initialValues[0] : this.initialValues; if (initialValue === null || typeof initialValue === "undefined" || initialValue === "") { output = initialValue; } else { output = this.params.emptyValue; } } } } if (output === "") { output = this.params.emptyValue; } this.actions.success(output); if (this.isFilter) { this.initialValues = output && !Array.isArray(output) ? [output] : output; this.currentItems = []; } } }; function list(cell, onRendered, success, cancel, editorParams) { var list2 = new Edit$1(this, cell, onRendered, success, cancel, editorParams); return list2.input; } function star$1(cell, onRendered, success, cancel, editorParams) { var self = this, element = cell.getElement(), value = cell.getValue(), maxStars = element.getElementsByTagName("svg").length || 5, size = element.getElementsByTagName("svg")[0] ? element.getElementsByTagName("svg")[0].getAttribute("width") : 14, stars = [], starsHolder = document.createElement("div"), star2 = document.createElementNS("http://www.w3.org/2000/svg", "svg"); function starChange(val) { stars.forEach(function (star3, i2) { if (i2 < val) { if (self.table.browser == "ie") { star3.setAttribute("class", "tabulator-star-active"); } else { star3.classList.replace("tabulator-star-inactive", "tabulator-star-active"); } star3.innerHTML = 'JavDB限制日本IP的访问,而预览视频来自DMM,需要日本IP才能访问。
这样会导致二者无法同时使用,需要对其一进行代理转发。
将 cc3001.dmm.co.jp 及 dmm.co 分流到日本ip。
Clash Verge分流规则设置 (如果你是别的代理软件,自行搜索如何分流)
方法一:设置中-添加视频标题关键词,如: VENX-
方法二:进入详情页,选中标题文字,右键可加入
屏蔽演员前,先筛选分类,再点屏蔽
① 访问115登录页, 选择JHS-扫码面板, 并扫码登录
② 进入网盘后, 右下角悬浮按钮, 复制Cookie
③ 打开另一个浏览器(需装JHS脚本), 进入登录页面, 选择JHS-扫码面板, 输入Cookie并回车
请选择头像数据源 (当前: ${CDN_SOURCES[initialIndex].name}):
${radioOptions}切换源会清除本地缓存的数据,并在下次搜索时重新加载。
点击图片即可选择(初始共 ${imageLinks.length} 张)
| 来源 | 原始字幕名称 | 语言 | 格式 | 操作 |
|---|