Bilibili-Evolved/client/observer.js
2019-04-20 18:25:12 +08:00

115 lines
2.9 KiB
JavaScript

let cidHooked = false;
const videoChangeCallbacks = [];
export class Observer
{
constructor(element, callback)
{
this.element = element;
this.callback = callback;
this.observer = null;
this.options = undefined;
}
start()
{
if (this.element)
{
this.observer = new MutationObserver(this.callback);
this.observer.observe(this.element, this.options);
}
return this;
}
stop()
{
this.observer && this.observer.disconnect();
return this;
}
static observe(selector, callback, options)
{
callback([]);
let elements = selector;
if (typeof selector === "string")
{
elements = [...document.querySelectorAll(selector)];
}
else if (!Array.isArray(selector))
{
elements = [selector];
}
return elements.map(
it =>
{
const observer = new Observer(it, callback);
observer.options = options;
return observer.start();
});
}
static childList(selector, callback)
{
return Observer.observe(selector, callback, {
childList: true,
subtree: false,
attributes: false,
});
}
static childListSubtree(selector, callback)
{
return Observer.observe(selector, callback, {
childList: true,
subtree: true,
attributes: false,
});
}
static attributes(selector, callback)
{
return Observer.observe(selector, callback, {
childList: false,
subtree: false,
attributes: true,
});
}
static attributesSubtree(selector, callback)
{
return Observer.observe(selector, callback, {
childList: false,
subtree: true,
attributes: true,
});
}
static all(selector, callback)
{
return Observer.observe(selector, callback, {
childList: true,
subtree: true,
attributes: true,
});
}
static async videoChange(callback)
{
const cid = await SpinQuery.select(() => unsafeWindow.cid);
if (cid === null)
{
return;
}
if (!cidHooked)
{
let hookedCid = cid;
Object.defineProperty(unsafeWindow, "cid", {
get()
{
return hookedCid;
},
set(newId)
{
hookedCid = newId;
if (!Array.isArray(newId))
{
videoChangeCallbacks.forEach(it => it());
}
}
});
cidHooked = true;
}
callback();
videoChangeCallbacks.push(callback);
}
}