Instacart Ad Remover

Blocks those nasty Instacart ads on various pages, including in search, store home page, user home page, cart, etc.

目前為 2024-09-26 提交的版本,檢視 最新版本

您需要先安裝使用者腳本管理器擴展,如 TampermonkeyGreasemonkeyViolentmonkey 之後才能安裝該腳本。

You will need to install an extension such as Tampermonkey to install this script.

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyViolentmonkey 後才能安裝該腳本。

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyUserscripts 後才能安裝該腳本。

你需要先安裝一款使用者腳本管理器擴展,比如 Tampermonkey,才能安裝此腳本

您需要先安裝使用者腳本管理器擴充功能後才能安裝該腳本。

(我已經安裝了使用者腳本管理器,讓我安裝!)

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

(我已經安裝了使用者樣式管理器,讓我安裝!)

// ==UserScript==
// @name     Instacart Ad Remover
// @description Blocks those nasty Instacart ads on various pages, including in search, store home page, user home page, cart, etc.
// @version  57
// @license      MIT
// @match    https://*.instacart.ca/*
// @match    https://*.instacart.com/*
// @grant    GM_addStyle
// @namespace https://greasyfork.org/users/1354160
// ==/UserScript==

function waitForKeyElements(selectorOrFunction, callback, waitOnce, interval, maxIntervals) {
  if (typeof waitOnce === "undefined") {
      waitOnce = true;
  }
  if (typeof interval === "undefined") {
      interval = 300;
  }
  if (typeof maxIntervals === "undefined") {
      maxIntervals = -1;
  }
  var targetNodes =
      typeof selectorOrFunction === "function" ?
      selectorOrFunction() :
      document.querySelectorAll(selectorOrFunction);

  var targetsFound = targetNodes && targetNodes.length > 0;
  if (targetsFound) {
      targetNodes.forEach(function (targetNode) {
          var attrAlreadyFound = "data-userscript-alreadyFound";
          var alreadyFound = targetNode.getAttribute(attrAlreadyFound) || false;
          if (!alreadyFound) {
              var cancelFound = callback(targetNode);
              if (cancelFound) {
                  targetsFound = false;
              } else {
                  targetNode.setAttribute(attrAlreadyFound, true);
              }
          }
      });
  }

  if (maxIntervals !== 0 && !(targetsFound && waitOnce)) {
      maxIntervals -= 1;
      setTimeout(function () {
          waitForKeyElements(selectorOrFunction, callback, waitOnce, interval, maxIntervals);
      }, interval);
  }
}

let sponsoredTexts = ["sponsored", "spaahnserd", "spawhnserd", "spawnserd", "spaunsered", "spaunserd", "spauncered", "spauncerd", "spohnserd", "spohncerd", "spohncered", "spawncerd", "spawncered"]

function isSponsored(elem) {
  if (elem) {
    // var descendentDivs = elem.querySelectorAll('section, div')

    // var sponsored = Array.from(descendentDivs).find(div => div !== null && div.shadowRoot !== null)

    // if (sponsored) {
    //   return true;
    // } else return false;

    const sponsored = elem.querySelector('*[data-cfp-eligible]')

    if (sponsored) {
      return true
    } else return false;

  } else return false
}

function isSponsoredImg(img) {
  if (img) {
    let attrs = Array.from(img.attributes)

    let isSponsored = attrs.find(({name, value}) => sponsoredTexts.find(txt => value.toLowerCase().includes(txt)))

    // let ariaLabel = img.getAttribute('aria-label')
    // if (sponsoredTexts.includes(img.alt.toLowerCase().trim()) || (ariaLabel && sponsoredTexts.includes(img.getAttribute('aria-label').toLowerCase().trim()))) {
    if(isSponsored) {
      return true;
    } else return false;

  } else return false
}

function individualItems(jNode) {
  let li = jNode.closest('li')

  if (isSponsored(li)) {
    let parent = li.parentNode;
    if (parent.tagName == 'DIV') {
      parent.style.display = 'none'
    } else {
      li.style.display = 'none';
    }
  }
}

function undesiredElement(jNode) {
  jNode.style.display = 'none'
}

function blockAdsInSearch() {
  // var lists = document.querySelectorAll('#store-wrapper .e-1yrpusx:not([style*="display:none"]):not([style*="display: none"]) > ul')

  let [head, ...tail] = [].filter.call(document.querySelectorAll('#store-wrapper .e-1yrpusx:not([style*="display:none"]):not([style*="display: none"]) > ul'), function (elem) {
    return elem.querySelector('div[aria-label="Product"]')
  });

  // lists.filter(list => list.querySelector('div[aria-label="Product"]') !== null)
  if (head) {
    let mainList = head
    let otherLists = tail.map(node => node.querySelectorAll('li'))

    otherLists.forEach(itemList => itemList.forEach(item => mainList.append(item)))

    tail.forEach(node => node.style.display = "none")

    mainList.childNodes.forEach(item => {
      if (isSponsored(item)) {
        item.style.display = 'none';
      }
    })
  }
}

function blockAdsInCart(jNode) {
  let div = jNode

  if (div.innerHTML.indexOf('Suggested items') != -1) {
    div.style.display = 'none'
  }
}

function homeBanner(jNode) {
  let carousel = jNode.closest('div[aria-label="carousel"]')

  if (carousel) {
    carousel.style.display = "none"
  }
}

function getbyXpath(xpath, contextNode) {
  let results = [];
  let query = document.evaluate(xpath, contextNode || document,
    null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);
  for (let i = 0, length = query.snapshotLength; i < length; ++i) {
    results.push(query.snapshotItem(i));
  }
  return results;
}

function sponsoredCarousel(jNode) {
  let elem = jNode

  function traverseAncestors(node) {
    if (node) {
      if (node.tagName == 'DIV') {
        // let spans = node.querySelectorAll('span')
        // let sponsoredSpans = [...spans].filter(span => span.innerHTML == ' nsored')
        let imgs = node.querySelectorAll('img')
        let sponsoredImgs = [...imgs].filter(img => isSponsoredImg(img))
        let individualSponsored = isSponsored(node)
        let scrollbars = node.querySelectorAll('.u-noscrollbar')

        if ((sponsoredImgs.length > 0) && (!individualSponsored) && (scrollbars.length == 1)) {
          console.log(node)
          node.style.display = 'none';
        } else if (scrollbars.length > 1) {
          return;
        } else {
          traverseAncestors(node.parentNode);
        }
      } else traverseAncestors(node.parentNode)
    }
  }

  traverseAncestors(elem.parentNode)
}

function sponsoredPlacement(jNode) {
  let node = jNode

  let imgs = node.querySelectorAll('img')
  let sponsoredImgs = [...imgs].filter(img => isSponsoredImg(img))

  if ((sponsoredImgs.length > 0)) {
    node.style.display = 'none';
  }
}

function continueToNext(jNode) {
  let span = jNode

  if (span.innerText === 'Continue to checkout') {
    setTimeout(function () {
      span.closest('button').click();
    }, 500);
  }
}

waitForKeyElements('#store-wrapper div[aria-label="Product"]', blockAdsInSearch, false);
waitForKeyElements('#store ul li div[aria-label="Product"] a', individualItems, false);
waitForKeyElements('#store-wrapper div[data-testid="regimen-section"]', undesiredElement);
waitForKeyElements('#store-wrapper .e-efhdpf', undesiredElement); // Related recipes
waitForKeyElements('#cart-body > div', blockAdsInCart);
waitForKeyElements('#store-wrapper button[data-testid="home-announcement-banner-1"]', homeBanner)
waitForKeyElements('#store-wrapper #home-content-tab-panel section', undesiredElement, false)
waitForKeyElements('#store-wrapper div[aria-label="Treatment Tracker modal"]', undesiredElement) // offer banner at bottom
waitForKeyElements('#store div[aria-label="announcement"]', undesiredElement)
waitForKeyElements('#store-wrapper .u-noscrollbar', sponsoredCarousel, false)
waitForKeyElements('footer span', continueToNext)
waitForKeyElements('#storefront-placements-content article', sponsoredPlacement, false)
waitForKeyElements('#store-wrapper article', sponsoredPlacement, false)
waitForKeyElements('article', sponsoredPlacement)