re-implemented display view events

This commit is contained in:
raghavan
2024-01-22 23:52:41 +05:30
parent 572fe0b061
commit 53f209943b

View File

@@ -37,7 +37,7 @@ class Logger {
class Stash extends EventTarget {
constructor({
pageUrlCheckInterval = 100,
detectReRenders = false, // detects if .main element is re-rendered. eg: When you are in scenes page and clicking the scenes nav tab the url wont change but the elements are re-rendered, So with this you can listen and alter the elements inside the .main node
detectReRenders = true,
logging = false
} = {}) {
super();
@@ -47,7 +47,6 @@ class Stash extends EventTarget {
this.fireOnHashChangesToo = true;
this._lastPathStr = "";
this._lastQueryStr = "";
this._lastHashStr = "";
this._lastHref = "";
this._lastStashPageEvent = "";
this.waitForElement(this._detectReRenders ? ".main > div" : "html").then(() => {
@@ -55,9 +54,8 @@ class Stash extends EventTarget {
// Loop every 100 ms
if (
this._lastPathStr !== location.pathname ||
this._lastQueryStr !== location.search ||
(this.fireOnHashChangesToo && this._lastHashStr !== location.hash) ||
this._lastHref !== location.href ||
this._lastQueryStr !== location.search ||
(!document.querySelector(".main > div[stashUserscriptLibrary]") && this._detectReRenders)
) {
this._dispatchPageEvent("stash:page", false)
@@ -65,19 +63,17 @@ class Stash extends EventTarget {
this._handlePageChange({
lastPathStr: this._lastPathStr,
lastQueryStr: this._lastQueryStr,
lastHashStr: this._lastHashStr,
lastHref: this._lastHref,
lastStashPageEvent: this._lastStashPageEvent,
});
this._lastPathStr = location.pathname
this._lastQueryStr = location.search
this._lastHashStr = location.hash
this._lastHref = location.href
if (this._detectReRenders) {
this.waitForElement(".main > div", 10000).then((element) => {
element.setAttribute("stashUserscriptLibrary", "");
if (element) element.setAttribute("stashUserscriptLibrary", "");
})
}
}
@@ -474,18 +470,18 @@ class Stash extends EventTarget {
}
})
}
async _listenForNonPageChanges({selector = "", location = document.body, listenType = "", event = "", recursive = false, reRunHandlePageChange = false, condition = () => true, listenDefaultTab = true, callback = () => {}} = {}){
async _listenForNonPageChanges({selector = "", location = document.body, listenType = "", event = "", recursive = false, reRunHandlePageChange = false, listenDefaultTab = true, callback = () => {}} = {}){
if (recursive) return
if (listenType === "tabs") {
const locationElement = await this.waitForElement(location, 10000, document.body, true)
const tabsContainer = await this.waitForElement(selector, 10000, location, true)
const stash = this
let previousEvent = ""
function listenForTabClicks(domEvent) {
const clickedChild = domEvent.target ? domEvent.target : domEvent;
if(!clickedChild.classList?.contains("nav-link")) return
if (!clickedChild.classList?.contains("nav-link")) return
const tagName = clickedChild.getAttribute("data-rb-event-key")
const parentEvent = tagName.split("-")[0]
@@ -493,19 +489,19 @@ class Stash extends EventTarget {
event = `stash:page:${parentEvent}:${childEvent}`
if (previousEvent === event || !condition()) return
if (previousEvent === event) return
previousEvent = event
stash._dispatchPageEvent(`stash:page:any:${childEvent}`, false)
stash._dispatchPageEvent(event)
}
if (listenDefaultTab) listenForTabClicks(locationElement.querySelector(".nav-link.active"))
if (listenDefaultTab) listenForTabClicks(tabsContainer.querySelector(".nav-link.active"))
locationElement.addEventListener("click", listenForTabClicks);
tabsContainer.addEventListener("click", listenForTabClicks);
function removeEventListenerOnPageChange() {
locationElement.removeEventListener("click", listenForTabClicks)
tabsContainer.removeEventListener("click", listenForTabClicks)
stash.removeEventListener("stash:page", removeEventListenerOnPageChange)
}
stash.addEventListener("stash:page", removeEventListenerOnPageChange)
@@ -513,20 +509,19 @@ class Stash extends EventTarget {
this._dispatchPageEvent(event)
if (await this.waitForElementDeath(selector, location, true)) {
if (this._lastPathStr === window.location.pathname && !reRunHandlePageChange) {
await this._listenForNonPageChanges({selector: selector, event: event})
} else if (this._lastPathStr === window.location.pathname && reRunHandlePageChange) {
if (this._lastPathStr === window.location.pathname && reRunHandlePageChange) {
// triggered after home, performer, studio, tag's edit page close
this._handlePageChange({
recursive: true,
lastPathStr: this._lastPathStr,
lastQueryStr: this._lastQueryStr,
lastHashStr: this._lastHashStr,
lastHref: this._lastHref,
lastStashPageEvent: this._lastStashPageEvent,
});
}
}
}
callback()
}
_dispatchPageEvent(event, addToHistory = true) {
@@ -536,25 +531,27 @@ class Stash extends EventTarget {
lastEventState: {
lastPathStr: this._lastPathStr,
lastQueryStr: this._lastQueryStr,
lastHashStr: this._lastHashStr,
lastHref: this._lastHref,
lastStashPageEvent: this._lastStashPageEvent,
}
}
}))
if (addToHistory) {
this.log.debug(`[Navigation] ${event}`);
if (event.startsWith("stash:")) {
this._lastStashPageEvent = event;
}
}
// if (event!=="stash:page" && !addToHistory) this.log.debug(`[Navigation] ${event}`); // log ":any:" events
}
addPageListener(eventData) {
const {event, regex, callBack = () => {}, manuallyHandleDispatchEvent = false} = eventData
const {event, regex, callback = () => {}, manuallyHandleDispatchEvent = false} = eventData
if (event && !event?.startsWith("stash:") && regex && this._pageListeners[event] === undefined){
this._pageListeners[event] = {
regex: regex,
callBack: callBack,
callback: callback,
manuallyHandleDispatchEvent: manuallyHandleDispatchEvent
}
@@ -572,7 +569,7 @@ class Stash extends EventTarget {
}
}
removePageListener(event) {
if(event && !event?.startsWith("stash:") && this._pageListeners[event]){
if (event && !event?.startsWith("stash:") && this._pageListeners[event]){
delete this._pageListeners[event]
return event
} else {
@@ -595,16 +592,22 @@ class Stash extends EventTarget {
// scenes tab
"stash:page:scenes": {
regex: /\/scenes\?/,
handleDisplayView: true,
callBack: () => this.processTagger()
manuallyHandleDispatchEvent: true,
handleDisplayView: "ignoreDisplayViewCondition",
callback: ({lastHref, event, regex}) => {
if (!this.matchUrl(lastHref, regex)) {
this._dispatchPageEvent(event);
this.processTagger()
}
}
},
"stash:page:scene:new": {
regex: /\/scenes\/new/
},
"stash:page:scene": {
regex: /\/scenes\/\d+\?/,
callBack: ({recursive = false}) => this._listenForNonPageChanges({
location: ".scene-tabs .nav-tabs",
callback: ({recursive = false}) => this._listenForNonPageChanges({
selector: ".scene-tabs .nav-tabs",
listenType: "tabs",
recursive: recursive
})
@@ -614,11 +617,17 @@ class Stash extends EventTarget {
"stash:page:images": {
regex: /\/images\?/,
handleDisplayView: true,
manuallyHandleDispatchEvent: true,
callback: ({lastHref, event, regex}) => {
if (!this.matchUrl(lastHref, regex)) {
this._dispatchPageEvent(event);
}
}
},
"stash:page:image": {
regex: /\/images\/\d+/,
callBack: ({recursive = false}) => this._listenForNonPageChanges({
location: ".image-tabs .nav-tabs",
callback: ({recursive = false}) => this._listenForNonPageChanges({
selector: ".image-tabs .nav-tabs",
listenType: "tabs",
recursive: recursive
})
@@ -633,7 +642,7 @@ class Stash extends EventTarget {
},
"stash:page:movie:scenes": {
regex: /\/movies\/\d+\?/,
callBack: () => this.processTagger()
callback: () => this.processTagger()
},
// markers tab
@@ -644,7 +653,13 @@ class Stash extends EventTarget {
// galleries tab
"stash:page:galleries": {
regex: /\/galleries\?/,
handleDisplayView: true,
handleDisplayView: "ignoreDisplayViewCondition",
manuallyHandleDispatchEvent: true,
callback: ({lastHref, event, regex}) => {
if (!this.matchUrl(lastHref, regex)) {
this._dispatchPageEvent(event);
}
}
},
"stash:page:gallery:new": {
regex: /\/galleries\/new/,
@@ -653,16 +668,16 @@ class Stash extends EventTarget {
regex: /\/galleries\/\d+\?/,
manuallyHandleDispatchEvent: true,
handleDisplayView: "ignoreDisplayViewCondition",
callBack: ({lastHref, recursive = false}, event) => {
if(!this.matchUrl(lastHref, /\/galleries\/\d+\//)){
callback: ({lastHref, lastPathStr, recursive = false, event}) => {
if (!this.matchUrl(lastHref, /\/galleries\/\d+\//) && lastPathStr !== window.location.pathname) {
this._dispatchPageEvent("stash:page:gallery");
this._listenForNonPageChanges({selector: ".gallery-tabs .nav-tabs .nav-link.active", event: "stash:page:gallery:details"})
this._listenForNonPageChanges({selector: ".gallery-tabs .nav-tabs .nav-link.active", event: "stash:page:gallery:details", recursive: recursive})
}
this._dispatchPageEvent(event);
this._listenForNonPageChanges({
location: ".gallery-tabs .nav-tabs",
selector: ".gallery-tabs .nav-tabs",
listenType: "tabs",
recursive: recursive,
listenDefaultTab: false
@@ -673,16 +688,16 @@ class Stash extends EventTarget {
regex: /\/galleries\/\d+\/add/,
manuallyHandleDispatchEvent: true,
handleDisplayView: "ignoreDisplayViewCondition",
callBack: ({lastHref, recursive = false}, event) => {
if(!this.matchUrl(lastHref, /\/galleries\/\d+/)){
callback: ({lastHref, lastPathStr, recursive = false, event}) => {
if (!this.matchUrl(lastHref, /\/galleries\/\d+/) && lastPathStr !== window.location.pathname) {
this._dispatchPageEvent("stash:page:gallery");
this._listenForNonPageChanges({selector: ".gallery-tabs .nav-tabs .nav-link.active", event: "stash:page:gallery:details"})
this._listenForNonPageChanges({selector: ".gallery-tabs .nav-tabs .nav-link.active", event: "stash:page:gallery:details", recursive: recursive})
}
this._dispatchPageEvent(event);
this._listenForNonPageChanges({
location: ".gallery-tabs .nav-tabs",
selector: ".gallery-tabs .nav-tabs",
listenType: "tabs",
recursive: recursive,
listenDefaultTab: false
@@ -693,9 +708,13 @@ class Stash extends EventTarget {
// performers tab
"stash:page:performers": {
regex: /\/performers\?/,
handleDisplayView: "ignoreDisplayViewCondition",
manuallyHandleDispatchEvent: true,
handleDisplayView: true,
callBack: ({lastHref}, event) => !this.matchUrl(lastHref, /\/performers\?/) || this._detectReRenders ? this._dispatchPageEvent(event) : null
callback: ({lastHref, event, regex}) => {
if (!this.matchUrl(lastHref, regex) || this._detectReRenders) {
this._dispatchPageEvent(event)
}
}
},
"stash:page:performer:new": {
regex: /\/performers\/new/
@@ -703,8 +722,8 @@ class Stash extends EventTarget {
"stash:page:performer": {
regex: /\/performers\/\d+/,
manuallyHandleDispatchEvent: true,
callBack: ({lastHref}, event) => {
if(!this.matchUrl(lastHref, /\/performers\/\d+/)){
callback: ({lastHref, event, regex}) => {
if (!this.matchUrl(lastHref, regex)) {
this._dispatchPageEvent(event);
this.processTagger();
}
@@ -719,29 +738,59 @@ class Stash extends EventTarget {
},
"stash:page:performer:scenes": {
regex: /\/performers\/\d+\?/,
handleDisplayView: true,
handleDisplayView: "ignoreDisplayViewCondition",
manuallyHandleDispatchEvent: true,
callback: ({lastHref, event, regex}) => {
if (!this.matchUrl(lastHref, regex)) {
this._dispatchPageEvent(event);
}
}
},
"stash:page:performer:galleries": {
regex: /\/performers\/\d+\/galleries/,
handleDisplayView: true
handleDisplayView: "ignoreDisplayViewCondition",
manuallyHandleDispatchEvent: true,
callback: ({lastHref, event, regex}) => {
if (!this.matchUrl(lastHref, regex)) {
this._dispatchPageEvent(event);
}
}
},
"stash:page:performer:images": {
regex: /\/performers\/\d+\/images/,
handleDisplayView: true
handleDisplayView: "ignoreDisplayViewCondition",
manuallyHandleDispatchEvent: true,
callback: ({lastHref, event, regex}) => {
if (!this.matchUrl(lastHref, regex)) {
this._dispatchPageEvent(event);
}
}
},
"stash:page:performer:movies": {
regex: /\/performers\/\d+\/movies/
},
"stash:page:performer:appearswith": {
regex: /\/performers\/\d+\/appearswith/,
handleDisplayView: true,
callBack: () => this.processTagger()
handleDisplayView: "ignoreDisplayViewCondition",
manuallyHandleDispatchEvent: true,
callback: ({lastHref, event, regex}) => {
if (!this.matchUrl(lastHref, regex)) {
this._dispatchPageEvent(event);
this.processTagger()
}
}
},
// studios tab
"stash:page:studios": {
regex: /\/studios\?/,
handleDisplayView: true,
handleDisplayView: "ignoreDisplayViewCondition",
manuallyHandleDispatchEvent: true,
callback: ({lastHref, event, regex}) => {
if (!this.matchUrl(lastHref, regex)) {
this._dispatchPageEvent(event);
}
}
},
"stash:page:studio:new": {
regex: /\/studios\/new/
@@ -749,8 +798,8 @@ class Stash extends EventTarget {
"stash:page:studio": {
regex: /\/studios\/\d+/,
manuallyHandleDispatchEvent: true,
callBack: ({lastHref}, event) => {
if(!this.matchUrl(lastHref, /\/studios\/\d+/)){
callback: ({lastHref, event, regex}) => {
if (!this.matchUrl(lastHref, regex)) {
this._dispatchPageEvent(event);
this.processTagger();
}
@@ -765,32 +814,68 @@ class Stash extends EventTarget {
},
"stash:page:studio:scenes": {
regex: /\/studios\/\d+\?/,
handleDisplayView: true,
handleDisplayView: "ignoreDisplayViewCondition",
manuallyHandleDispatchEvent: true,
callback: ({lastHref, event, regex}) => {
if (!this.matchUrl(lastHref, regex)) {
this._dispatchPageEvent(event);
}
}
},
"stash:page:studio:galleries": {
regex: /\/studios\/\d+\/galleries/,
handleDisplayView: true,
handleDisplayView: "ignoreDisplayViewCondition",
manuallyHandleDispatchEvent: true,
callback: ({lastHref, event, regex}) => {
if (!this.matchUrl(lastHref, regex)) {
this._dispatchPageEvent(event);
}
}
},
"stash:page:studio:images": {
regex: /\/studios\/\d+\/images/,
handleDisplayView: true,
handleDisplayView: "ignoreDisplayViewCondition",
manuallyHandleDispatchEvent: true,
callback: ({lastHref, event, regex}) => {
if (!this.matchUrl(lastHref, regex)) {
this._dispatchPageEvent(event);
}
}
},
"stash:page:studio:performers": {
regex: /\/studios\/\d+\/performers/,
handleDisplayView: true,
handleDisplayView: "ignoreDisplayViewCondition",
manuallyHandleDispatchEvent: true,
callback: ({lastHref, event, regex}) => {
if (!this.matchUrl(lastHref, regex)) {
this._dispatchPageEvent(event);
}
}
},
"stash:page:studio:movies": {
regex: /\/studios\/\d+\/movies/
},
"stash:page:studio:childstudios": {
regex: /\/studios\/\d+\/childstudios/,
handleDisplayView: true,
handleDisplayView: "ignoreDisplayViewCondition",
manuallyHandleDispatchEvent: true,
callback: ({lastHref, event, regex}) => {
if (!this.matchUrl(lastHref, regex)) {
this._dispatchPageEvent(event);
}
}
},
// tags tab
"stash:page:tags": {
regex: /\/tags\?/,
handleDisplayView: true,
handleDisplayView: "ignoreDisplayViewCondition",
manuallyHandleDispatchEvent: true,
callback: ({lastHref, event, regex}) => {
if (!this.matchUrl(lastHref, regex)) {
this._dispatchPageEvent(event);
}
}
},
"stash:page:tag:new": {
regex: /\/tags\/new/
@@ -798,8 +883,8 @@ class Stash extends EventTarget {
"stash:page:tag": {
regex: /\/tags\/\d+/,
manuallyHandleDispatchEvent: true,
callBack: ({lastHref}, event) => {
if(!this.matchUrl(lastHref, /\/tags\/\d+/)){
callback: ({lastHref, event, regex}) => {
if (!this.matchUrl(lastHref, regex)) {
this._dispatchPageEvent(event);
this.processTagger();
}
@@ -814,29 +899,57 @@ class Stash extends EventTarget {
},
"stash:page:tag:scenes": {
regex: /\/tags\/\d+\?/,
handleDisplayView: true,
handleDisplayView: "ignoreDisplayViewCondition",
manuallyHandleDispatchEvent: true,
callback: ({lastHref, event, regex}) => {
if (!this.matchUrl(lastHref, regex)) {
this._dispatchPageEvent(event);
}
}
},
"stash:page:tag:galleries": {
regex: /\/tags\/\d+\/galleries/,
handleDisplayView: true,
handleDisplayView: "ignoreDisplayViewCondition",
manuallyHandleDispatchEvent: true,
callback: ({lastHref, event, regex}) => {
if (!this.matchUrl(lastHref, regex)) {
this._dispatchPageEvent(event);
}
}
},
"stash:page:tag:images": {
regex: /\/tags\/\d+\/images/,
handleDisplayView: true,
handleDisplayView: "ignoreDisplayViewCondition",
manuallyHandleDispatchEvent: true,
callback: ({lastHref, event, regex}) => {
if (!this.matchUrl(lastHref, regex)) {
this._dispatchPageEvent(event);
}
}
},
"stash:page:tag:markers": {
regex: /\/tags\/\d+\/markers/
},
"stash:page:tag:performers": {
regex: /\/tags\/\d+\/performers/,
handleDisplayView: true,
handleDisplayView: "ignoreDisplayViewCondition",
manuallyHandleDispatchEvent: true,
callback: ({lastHref, event, regex}) => {
if (!this.matchUrl(lastHref, regex)) {
this._dispatchPageEvent(event);
}
}
},
// settings page
"stash:page:settings": {
regex: /\/settings/,
manuallyHandleDispatchEvent: true,
callBack: ({lastHref}, event) => !this.matchUrl(lastHref, /\/settings/) ? this._dispatchPageEvent(event) : null
callback: ({lastHref, event, regex}) => {
if (!this.matchUrl(lastHref, regex)) {
this._dispatchPageEvent(event)
}
}
},
"stash:page:settings:tasks": {
regex: /\/settings\?tab=tasks/,
@@ -859,7 +972,7 @@ class Stash extends EventTarget {
},
"stash:page:settings:system": {
regex: /\/settings\?tab=system/,
callBack: () => this.createSettings()
callback: () => this.createSettings()
},
"stash:page:settings:plugins": {
regex: /\/settings\?tab=plugins/
@@ -885,7 +998,7 @@ class Stash extends EventTarget {
// home page
"stash:page:home": {
regex: /\/$/,
callBack: () => this._listenForNonPageChanges({selector: ".recommendations-container-edit", event: "stash:page:home:edit", reRunHandlePageChange: true})
callback: () => this._listenForNonPageChanges({selector: ".recommendations-container-edit", event: "stash:page:home:edit", reRunHandlePageChange: true})
},
}
}
@@ -893,12 +1006,25 @@ class Stash extends EventTarget {
const events = Object.keys(this._pageListeners)
for (const event of events) {
const {regex, callBack = async () => {}, manuallyHandleDispatchEvent = false, handleDisplayView = false} = this._pageListeners[event]
const {regex, callback = () => {}, manuallyHandleDispatchEvent = false, handleDisplayView = false} = this._pageListeners[event]
let isDisplayViewPage = false
let isListPage, isWallPage, isTaggerPage
let isGridPage, isListPage, isWallPage, isTaggerPage
const splitEvent = event.split(":")
const tabPage = {page: "", tab: ""}
let childAnyEventCondition = false
if (splitEvent.length === 4) {
childAnyEventCondition = true
tabPage.page = splitEvent[2]
tabPage.tab = splitEvent[3]
}
splitEvent.pop()
if (handleDisplayView) {
isGridPage = this.matchUrl(window.location.href, concatRegexp(regex, /(?!.*disp=)/))
isListPage = this.matchUrl(window.location.href, concatRegexp(regex, /.*disp=1/))
isWallPage = this.matchUrl(window.location.href, concatRegexp(regex, /.*disp=2/))
isTaggerPage = this.matchUrl(window.location.href, concatRegexp(regex, /.*disp=3/))
@@ -906,24 +1032,39 @@ class Stash extends EventTarget {
if (isListPage || isWallPage || isTaggerPage) isDisplayViewPage = true
}
function dispatchViewEvent(view, stash){
stash._dispatchPageEvent(event + `:${view}`);
if (childAnyEventCondition) {
stash._dispatchPageEvent("stash:page:" + tabPage.page + `:any:${view}`, false);
stash._dispatchPageEvent("stash:page:any:" + tabPage.tab + `:${view}`, false);
} else {
stash._dispatchPageEvent(`stash:page:any:${view}`, false);
}
}
const handleDisplayViewCondition = handleDisplayView !== true || (handleDisplayView && (!isDisplayViewPage || args.lastHref === ""))
if (this.matchUrl(window.location.href, regex) && handleDisplayViewCondition) {
if (!manuallyHandleDispatchEvent) this._dispatchPageEvent(event)
callBack({...args, location: window.location}, event)
callback({...args, location: window.location, event: event, regex: regex})
if (isGridPage) dispatchViewEvent("grid", this)
}
if (handleDisplayView) {
if (isListPage) {
this._dispatchPageEvent("stash:page:any:list", false);
this._dispatchPageEvent(event + ":list");
} else if (isWallPage) {
this._dispatchPageEvent("stash:page:any:wall", false);
this._dispatchPageEvent(event + ":wall");
} else if (isTaggerPage) {
this._dispatchPageEvent("stash:page:any:tagger", false);
this._dispatchPageEvent(event + ":tagger");
let view = ""
switch(true) {
case isListPage:
view = "list"
break;
case isWallPage:
view = "wall"
break;
case isTaggerPage:
view = "tagger"
break;
}
if (view) dispatchViewEvent(view, this)
}
}
}
@@ -1291,50 +1432,50 @@ class Stash extends EventTarget {
window.stash = new Stash();
function waitForElementQuerySelector(query, callBack, time) {
function waitForElementQuerySelector(query, callback, time) {
time = (typeof time !== 'undefined') ? time : 100;
window.setTimeout(() => {
const element = document.querySelector(query);
if (element) {
callBack(query, element);
callback(query, element);
} else {
waitForElementQuerySelector(query, callBack, time);
waitForElementQuerySelector(query, callback, time);
}
}, time);
}
function waitForElementClass(elementId, callBack, time) {
function waitForElementClass(elementId, callback, time) {
time = (typeof time !== 'undefined') ? time : 100;
window.setTimeout(() => {
const element = document.getElementsByClassName(elementId);
if (element.length > 0) {
callBack(elementId, element);
callback(elementId, element);
} else {
waitForElementClass(elementId, callBack, time);
waitForElementClass(elementId, callback, time);
}
}, time);
}
function waitForElementId(elementId, callBack, time) {
function waitForElementId(elementId, callback, time) {
time = (typeof time !== 'undefined') ? time : 100;
window.setTimeout(() => {
const element = document.getElementById(elementId);
if (element != null) {
callBack(elementId, element);
callback(elementId, element);
} else {
waitForElementId(elementId, callBack, time);
waitForElementId(elementId, callback, time);
}
}, time);
}
function waitForElementByXpath(xpath, callBack, time) {
function waitForElementByXpath(xpath, callback, time) {
time = (typeof time !== 'undefined') ? time : 100;
window.setTimeout(() => {
const element = getElementByXpath(xpath);
if (element) {
callBack(xpath, element);
callback(xpath, element);
} else {
waitForElementByXpath(xpath, callBack, time);
waitForElementByXpath(xpath, callback, time);
}
}, time);
}