Files
Hydro/ui/components/DOMAttachedObject.js
T
masnn f9468536de upgrade dep:
css-loader 0.28->3.5
del 4.1->5.1
eslint 5.18->6.8
eslint-config-airbnb 17.1->18.1
eslint-loader 2.1->4.0
file-loader 2.0->6.0
fs.extra 8.0->9.0
gulp 2.0->3.0
gulp-nunjucks 4.0->5.0
json-loader 0.5->Removed
style-loader 0.23->1.1
uglifyjs-webpack-plugin 1.3->2.2
yargs 13.2->15.3
katex 0.10->0.11
react-monaco-editor 0.35->0.36
timeage-react 1.2->3.0
timeago.js 3.0->4.0
uuid 3.3->7.0
2020-04-15 12:47:55 +08:00

126 lines
3.5 KiB
JavaScript

let removalChecker = null;
const res = [];
function checkResources() {
for (let i = res.length - 1; i >= 0; --i) {
if (res[i].detached || !document.body.contains(res[i].$dom[0])) {
if (!res[i].detached) res[i].detach();
res.splice(i, 1);
}
}
if (res.length === 0) {
clearInterval(removalChecker);
removalChecker = null;
}
}
function monitorResource(resource) {
res.push(resource);
if (removalChecker === null) {
removalChecker = setInterval(checkResources, 500);
}
}
export default class DOMAttachedObject {
static uniqueIdCounter = 0;
static get($obj) {
const key = this.DOMAttachKey;
return $obj.data(key);
}
static getOrConstruct($obj, ...args) {
const $singleObj = $obj.eq(0);
const key = this.DOMAttachKey;
const Protoclass = this;
const instance = this.get($singleObj);
if (instance !== undefined) return instance;
const newInstance = new Protoclass($singleObj, ...args);
// $dom may be updated in constructor so that we use $dom instead
// of $singleObj here.
if (!newInstance.$dom) return null;
newInstance.$dom.data(key, newInstance);
return newInstance;
}
static attachAll(container = document.body, ...args) {
if (process.env.NODE_ENV !== 'production') {
if (!this.DOMAttachSelector) {
// eslint-disable-next-line quotes
throw new Error(`'DOMAttachSelector' should be specified`);
}
}
if (process.env.NODE_ENV !== 'production') {
console.time(`DOMAttachedObject[${this.DOMAttachKey}]: attachAll`);
}
$(container)
.find(this.DOMAttachSelector)
.addBack(this.DOMAttachSelector)
.get()
.forEach((element) => this.getOrConstruct($(element), ...args));
if (process.env.NODE_ENV !== 'production') {
console.timeEnd(`DOMAttachedObject[${this.DOMAttachKey}]: attachAll`);
}
}
static detachAll(container = document.body) {
const selector = this.DOMDetachSelector || this.DOMAttachSelector;
if (process.env.NODE_ENV !== 'production') {
if (!selector) {
// eslint-disable-next-line quotes
throw new Error(`'DOMDetachSelector' or 'DOMAttachSelector' should be specified`);
}
}
if (process.env.NODE_ENV !== 'production') {
console.time(`DOMAttachedObject[${this.DOMAttachKey}]: detachAll`);
}
$(container)
.find(selector)
.addBack(selector)
.get()
.forEach((element) => {
const instance = this.get($(element));
if (instance) {
instance.detach();
}
});
if (process.env.NODE_ENV !== 'production') {
console.timeEnd(`DOMAttachedObject[${this.DOMAttachKey}]: detachAll`);
}
}
static registerLifeCycleHooks(attach = true) {
if (process.env.NODE_ENV !== 'production') {
if (!this.DOMAttachSelector) {
// eslint-disable-next-line quotes
throw new Error(`'DOMAttachSelector' should be specified`);
}
}
$(document).on('vjContentNew', (e) => this.attachAll(e.target));
$(document).on('vjContentRemove', (e) => this.detachAll(e.target));
if (attach) {
this.attachAll();
}
}
detach() {
if (this.constructor.DOMAttachKey) {
this.$dom.removeData(this.constructor.DOMAttachKey);
}
this.detached = true;
}
constructor($dom, monitorDetach = false) {
if ($dom == null) {
return null;
}
this.$dom = $dom;
this.id = ++DOMAttachedObject.uniqueIdCounter;
this.eventNS = `vj4obj_${this.id}`;
this.detached = false;
if (monitorDetach) {
monitorResource(this);
}
}
}