@ -48,12 +48,22 @@ function isItemInStock() {
'tijdelijk uitverkocht' ,
'unavailable tickets' ,
'we do not currently have an estimate of when this product will be back in stock.' ,
'we don\'t know when or if this item will be back in stock.' ,
'zur zeit nicht an lager' ,
'品切れ' ,
'已售完' ,
'품절'
] ;
function getElementBaseText ( element ) {
// .textContent can include text from children which may give the wrong results
// scan only immediate TEXT_NODEs, which will be a child of the element
var text = "" ;
for ( var i = 0 ; i < element . childNodes . length ; ++ i )
if ( element . childNodes [ i ] . nodeType === Node . TEXT _NODE )
text += element . childNodes [ i ] . textContent ;
return text . toLowerCase ( ) . trim ( ) ;
}
const negateOutOfStockRegexs = [
'[0-9] in stock'
@ -63,18 +73,22 @@ function isItemInStock() {
negateOutOfStockRegexs _r . push ( new RegExp ( negateOutOfStockRegexs [ 0 ] , 'g' ) ) ;
}
// The out-of-stock or in-stock-text is generally always above-the-fold
// and often below-the-fold is a list of related products that may or may not contain trigger text
// so it's good to filter to just the 'above the fold' elements
// and it should be atleast 100px from the top to ignore items in the toolbar, sometimes menu items like "Coming soon" exist
const elementsToScan = Array . from ( document . getElementsByTagName ( '*' ) ) . filter ( element => element . getBoundingClientRect ( ) . top + window . scrollY <= window . innerHeight && element . getBoundingClientRect ( ) . top + window . scrollY >= 100 ) ;
const elementsWithZeroChildren = Array . from ( document . getElementsByTagName ( '*' ) ) . filter ( element => element . children . length === 0 ) ;
var elementText = "" ;
// REGEXS THAT REALLY MEAN IT'S IN STOCK
for ( let i = elementsWithZeroChildren . length - 1 ; i >= 0 ; i -- ) {
const element = elementsWithZeroChildren [ i ] ;
if ( element . offsetWidth > 0 || element . offsetHeight > 0 || element . getClientRects ( ) . length > 0 ) {
var elementText = "" ;
for ( let i = elementsToScan . length - 1 ; i >= 0 ; i -- ) {
const element = elementsToScan [ i ] ;
elementText = "" ;
if ( element . tagName . toLowerCase ( ) === "input" ) {
elementText = element . value . toLowerCase ( ) ;
} else {
elementText = element . textContent . toLowerCase ( ) ;
elementText = getElementBaseText ( element ) ;
}
if ( elementText . length ) {
@ -86,24 +100,23 @@ function isItemInStock() {
}
}
}
}
// OTHER STUFF THAT COULD BE THAT IT'S OUT OF STOCK
for ( let i = elements WithZeroChildre n. length - 1 ; i >= 0 ; i -- ) {
const element = elements WithZeroChildre n[ i ] ;
for ( let i = elements ToSca n. length - 1 ; i >= 0 ; i -- ) {
const element = elements ToSca n[ i ] ;
if ( element . offsetWidth > 0 || element . offsetHeight > 0 || element . getClientRects ( ) . length > 0 ) {
var elementText = "" ;
elementText = "" ;
if ( element . tagName . toLowerCase ( ) === "input" ) {
elementText = element . value . toLowerCase ( ) ;
} else {
elementText = element . textContent . toLowerCase ( ) ;
elementText = getElementBaseText ( element ) ;
}
if ( elementText . length ) {
// and these mean its out of stock
for ( const outOfStockText of outOfStockTexts ) {
if ( elementText . includes ( outOfStockText ) ) {
return element Text; // item is out of stock
return outOfStock Text; // item is out of stock
}
}
}
@ -114,4 +127,5 @@ function isItemInStock() {
}
// returns the element text that makes it think it's out of stock
return isItemInStock ( ) ;
return isItemInStock ( ) . trim ( )