Greasy Fork is available in English.

Muting on Twitter

Mutes texts/links/tags/userIDs on Twitter and changes tweets' style

2014-08-22 일자. 최신 버전을 확인하세요.

질문, 리뷰하거나, 이 스크립트를 신고하세요.
// ==UserScript==
// @name        Muting on Twitter
// @namespace   https://github.com/mosaicer
// @author      mosaicer
// @description Mutes texts/links/tags/userIDs on Twitter and changes tweets' style
// @version     5.2
// @include     https://twitter.com/
// @include     https://twitter.com/search?*
// @grant       GM_getValue
// @grant       GM_setValue
// @grant       GM_registerMenuCommand
// ==/UserScript==
(function () {
  var Init = function() {
        this.menu_jp = {
          autoRefresh_flag: ["自動更新を", {}],
          style_flag: ["各ツイートの装飾を", {}],
          mute_text_flag: ["ツイート本文についてのミュートを", {}],
          mute_link_flag: ["リンクについてのミュートを", {}],
          mute_tag_flag: ["ハッシュタグについてのミュートを", {}],
          mute_userId_flag: ["ユーザーIDについてのミュートを", {}]
        };
        this.menu_en = {
          autoRefresh_flag: [" auto refresh", {}],
          style_flag: [" change tweet style", {}],
          mute_text_flag: [" mute for texts in tweet", {}],
          mute_link_flag: [" mute for links in tweet", {}],
          mute_tag_flag: [" mute for hashtags in tweet", {}],
          mute_userId_flag: [" mute for userIDs in tweet", {}]
        };
        this.timeSetMsg = {
          ja: "時間の設定",
          en: "Set time"
        };
        this.msgFlag = false;
        this.msg = "";
        this.muteNameArray = {
          mute_words: [],
          mute_links: [],
          mute_tags: [],
          mute_ids: []
        };
      },
      setting,
      HeaderStruct = function() {
        this.contentHeader = document.querySelector(".content-header");
        this.headerInner = document.querySelector(".header-inner");
        this.previousNode = pageURL === "https://twitter.com/" ?
          document.querySelector("[class='DashboardProfileCard  module']") :
          document.querySelector("[class='module'][role='navigation']");
        this.parentFormNode = pageURL === "https://twitter.com/" ?
          document.querySelector("[class='dashboard dashboard-left ']") :
          document.querySelector("[class='dashboard dashboard-left']");
        this.formNode = document.createElement("div");
        this.formContainer = "";
        this.headerWidth = pageURL === "https://twitter.com/" ? 418 : 440;
        this.openClose_msg = {
          ja: "▶ フォーム欄の開閉 ◀",
          en: "▶ Open/Close input form ◀"
        };
        this.openClose_btn = document.createElement("div");
        this.btnAry = {
          ja: ["追加", "削除", "確認"],
          en: ["Add", "Del", "Conf"]
        };
        this.placeholderAry = {
          ja: [
                "ミュートする文字を入力してください",
                "テキスト",
                "リンク",
                "ハッシュタグ",
                "ユーザーID",
                "ミュートするタイプを選んでください"
              ],
          en: [
                "Please input letters you want mute in tweet",
                "texts",
                "links",
                "hashtags",
                "userIDs",
                "Please choose a type of muting"
              ]
        };
      },
      header,
      ButtonSet = function() {
        this.muteFlag = 0;
        this.pluralFlag = 0;
        this.btnFlag = "";
        this.muteListTemp = "";
        this.altMsgAry = {
          ja: [
                "' はすでに設定されています",
                "' は設定した文字列とマッチしませんでした",
                "↓ミュートする文字列をカンマ区切りで表示しています↓\n\n",
                "ミュートする文字列が設定されていません",
                "申し訳ないですが、ミュートする文字列に,/は使うことができません"
              ],
          en: [
                "' is already set for mute word",
                "' is not set for mute word",
                "↓The mute words separated by conmma↓\n\n",
                "The mute words are not found",
                "Sorry, the mute words which contains the word ',/' can not be set"
              ]
        };
      },
      buttonAction,
      MuteFeatures = function() {
        this.homeTweets = "";
        this.replyPrnt = ""; // parent nodes of tweets of reply
        this.flag = "";
        this.i = 0;
        this.j = 0;
        // use when judging elements
        this.tweetPrnt = "";
        this.tweetElement = "";
      },
      muteAction,
      key = "",
      pageURL = location.href,
      userLang = window.navigator.language === "ja" ? "ja" : "en",
      splitWord = ",/",
      // MutationObserver
      MutationObserver = window.MutationObserver || window.WebKitMutationObserver || window.MozMutationObserver,
      observer,
      observerSub,
      // MouseEvent
      mouse_event,
      // move scroll bar
      flag_autoRef = 0,
      scrHeight,
      // decorate all tweets, not constructer
      tweetStyleChange = function() {
        // make font-weight of tweets' letters bold
        if (pageURL === "https://twitter.com/") {
          Array.prototype.slice.call(document.querySelectorAll("[class='js-tweet-text tweet-text']")).forEach(
            function (targetNode) {
              targetNode.style.fontWeight = "bold";
            }
          );
        }
        // make color of tweets' usernames and userIDs red
        Array.prototype.slice.call(document.querySelectorAll("[class*='js-action-profile-name']")).forEach(
          function (targetNode) {
            targetNode.style.color = "red";
          }
        );
        // make color of tweets' time blue
        Array.prototype.slice.call(document.querySelectorAll("[data-long-form='true']")).forEach(
          function (targetNode) {
            targetNode.style.color = "blue";
          }
        );
        Array.prototype.slice.call(document.querySelectorAll("[class='twitter-timeline-link']")).forEach(
          function (targetNode) {
            targetNode.setAttribute("target", "_blank");
          }
        );
      };

  Init.prototype = {
    accessSet: function() {
      if (userLang === "ja") {
        for (key in this.menu_jp) {
          if (this.menu_jp.hasOwnProperty(key)) {
            // set each flags, once after installing this user script
            if (typeof GM_getValue(key) === "undefined") {
              GM_setValue(key, true);
            }
            // construct command menus
            this.msgFlag = GM_getValue(key) === true ? "無効" : "有効";
            this.msg = this.menu_jp[key][0] + this.msgFlag + "にする";
            GM_registerMenuCommand(this.msg, this.featuresChg.bind(this.menu_jp[key][1][key + "Change"], key));
          }
        }
      } else {
        for (key in this.menu_en) {
          if (this.menu_jp.hasOwnProperty(key)) {
            // set each flags, once after installing this user script
            if (typeof GM_getValue(key) === "undefined") {
              GM_setValue(key, true);
            }
            // construct command menus
            this.msgFlag = GM_getValue(key) === true ? "Disable" : "Enable";
            this.msg = this.msgFlag + this.menu_en[key][0];
            GM_registerMenuCommand(this.msg, this.featuresChg.bind(this.menu_en[key][1][key + "Change"], key));
          }
        }
      }
      for (key in this.muteNameArray) {
        if (this.muteNameArray.hasOwnProperty(key) && typeof GM_getValue(key) !== "undefined") {
          if (GM_getValue(key).indexOf(splitWord) >= 0) {
            this.muteNameArray[key] = GM_getValue(key).split(splitWord);
          } else {
            this.muteNameArray[key].push(GM_getValue(key));
          }
        }
      }
      if (typeof GM_getValue("form_flag") === "undefined") {
        GM_setValue("form_flag", true);
      }
      if (typeof GM_getValue("time") === "undefined") {
        GM_setValue("time", "200");
      }
      GM_registerMenuCommand(this.timeSetMsg[userLang], this.timeSet);
    },
    // the function of command menus, make available or unavailable
    featuresChg: function(flagName) {
      this.msgFlag = GM_getValue(flagName) === true ? false : true;
      GM_setValue(flagName, this.msgFlag);
      location.reload();
    },
    timeSet: function() {
      var timeToDelay = prompt("", GM_getValue("time"));
      if (timeToDelay !== null && timeToDelay !== "" && /\d+/g.test(timeToDelay)) {
        GM_setValue("time", timeToDelay);
        location.reload();
      }
    }
  };

  HeaderStruct.prototype.styleSet = function () {
    // change a header's style
    if (pageURL === "https://twitter.com/") {
      this.contentHeader.style.borderStyle = "hidden";
      this.headerInner.style.height = "65px";
      this.headerInner.style.backgroundColor = "transparent";
    }
    // set a button that shows/hides input form
    this.openClose_btn.setAttribute("id", "open_close");
    this.openClose_btn.style.backgroundColor = "#FFD700";
    this.openClose_btn.style.cursor = "pointer";
    this.openClose_btn.style.width = "290px";
    this.openClose_btn.style.textAlign = "center";
    this.openClose_btn.style.marginBottom = "15px";
    this.openClose_btn.appendChild(document.createTextNode(this.openClose_msg[userLang]));
    this.parentFormNode.insertBefore(this.openClose_btn, this.previousNode);
    // construct a container of input form
    this.formContainer = "<form onsubmit='return false;'>" +
          "<input type='text' id='mLtrForm' class='form_btn' value='' placeholder='" +
          this.placeholderAry[userLang][0] + "' style='width: " + this.headerWidth + "px;'>" +
          "<input type='button' id='mLtrAdd' class='form_btn' value='" + this.btnAry[userLang][0] + "'>" +
          "<input type='button' id='mLtrRmv' class='form_btn' value='" + this.btnAry[userLang][1] + "'>" +
          "<input type='button' id='mLtrConf' value='" + this.btnAry[userLang][2] + "' style='color:black;'>" +
          "</form><div style='background-color:white; margin-top:8px; font-size:12px; color:black; height:23px;'>" +
          "<span style='color:green;'>" + this.placeholderAry[userLang][5] + ": </span>" +
          "<label style='margin-right: 17px;'><input type='radio' name='muteLetter' value='mute_words' checked>" +
          this.placeholderAry[userLang][1] + "</label>" +
          "<label style='margin-right: 17px;'><input type='radio' name='muteLetter' value='mute_links'>" +
          this.placeholderAry[userLang][2] + "</label>" +
          "<label style='margin-right: 17px;'><input type='radio' name='muteLetter' value='mute_tags'>" +
          this.placeholderAry[userLang][3] + "</label>" +
          "<label style='margin-right: 17px;'><input type='radio' name='muteLetter' value='mute_ids'>" +
          this.placeholderAry[userLang][4] + "</label></div>";
    if (pageURL === "https://twitter.com/") {
      document.getElementById("content-main-heading").innerHTML = this.formContainer;
    } else {
      this.formNode.style.marginBottom = "10px";
      this.formNode.style.textAlign = "center";
      this.formNode.innerHTML = this.formContainer;
      document.getElementById("timeline").insertBefore(this.formNode, this.contentHeader);
    }
    Array.prototype.slice.call(document.querySelectorAll(".form_btn")).forEach(
      function (targetNode) {
        targetNode.style.marginRight = "10px";
        targetNode.style.color = "black";
      }
    );
    // check the flag of input form
    if (GM_getValue("form_flag") === false) {
      if (pageURL === "https://twitter.com/") {
        this.contentHeader.style.display = "none";
      } else {
        this.formNode.style.display = "none";
      }
    }
  };

  ButtonSet.prototype = {
    // add letters to a mute list
    addMuteLtr: function (btn_flag, theLetter) {
      this.btnFlag = btn_flag;
      this.pluralFlag = 0;
      if (theLetter !== "") {
        if (theLetter.indexOf(splitWord + splitWord) < 0 && theLetter !== splitWord) {
          if (theLetter.indexOf(splitWord) >= 0) {
            this.pluralFlag = 1;
            this.muteListTemp = [];
            theLetter.split(splitWord).forEach(this.addFunc, buttonAction);
          } else {
            this.muteListTemp = "";
            this.addFunc(theLetter);
          }
          if (this.muteListTemp[0] !== "" && this.pluralFlag === 1 || this.muteListTemp !== "" && this.pluralFlag === 0) {
            if (this.pluralFlag === 0) {
              GM_setValue(btn_flag, this.muteListTemp);
            } else {
              if (typeof GM_getValue(btn_flag) === "undefined" || setting.muteNameArray[btn_flag][0] === "") {
                GM_setValue(btn_flag, this.muteListTemp.join(splitWord));
              } else {
                GM_setValue(btn_flag, setting.muteNameArray[btn_flag].join(splitWord) + splitWord + this.muteListTemp.join(splitWord));
              }
            }
            location.reload();
          }
        } else {
          alert(this.altMsgAry[userLang][4]);
        }
      }
    },
    addFunc: function (targetLtr) {
      this.targetText = targetLtr;
      this.muteFlag = 0;
      if (this.targetText !== "") {
        if (typeof GM_getValue(this.btnFlag) === "undefined" || setting.muteNameArray[this.btnFlag][0] === "") {
          if (this.pluralFlag === 1) {
            this.muteListTemp.push(this.targetText);
          } else {
            this.muteListTemp = this.targetText;
          }
        }
        else {
          setting.muteNameArray[this.btnFlag].forEach(this.completeComp, buttonAction);
          if (this.muteFlag === 0) {
            if (this.pluralFlag === 1) {
              this.muteListTemp.push(this.targetText);
            } else {
              this.muteListTemp = setting.muteNameArray[this.btnFlag].join(splitWord) + splitWord + this.targetText;
            }
          } else {
            alert("'" + this.targetText + this.altMsgAry[userLang][0]);
          }
        }
      }
    },
    // delete letters from a mute list
    delMuteLtr: function (btn_flag, theLetter) {
      this.btnFlag = btn_flag;
      this.muteListTemp = setting.muteNameArray[btn_flag];
      if (theLetter !== "") {
        if (theLetter.indexOf(splitWord + splitWord) < 0 && theLetter !== splitWord) {
          if (theLetter.indexOf(splitWord) >= 0) {
            theLetter.split(splitWord).forEach(this.deleteFunc, buttonAction);
          } else {
            this.deleteFunc(theLetter);
          }
          if (this.muteListTemp !== setting.muteNameArray[btn_flag]) {
            GM_setValue(this.btnFlag, this.muteListTemp.join(splitWord));
            location.reload();
          }
        } else {
          alert(this.altMsgAry[userLang][4]);
        }
      }
    },
    deleteFunc: function (targetLtr) {
      this.targetText = targetLtr;
      this.muteFlag = 0;
      if (this.targetText !== "") {
        if (typeof GM_getValue(this.btnFlag) === "undefined" || this.muteListTemp[0] === "") {
          alert(this.altMsgAry[userLang][3]);
        }
        else {
          this.muteListTemp.forEach(this.completeComp, buttonAction);
          if (this.muteFlag === 1) {
            this.muteListTemp = this.muteListTemp.filter(this.filterFunc, buttonAction);
          } else {
            alert("'" + this.targetText + this.altMsgAry[userLang][1]);
          }
        }
      }
    },
    // confirm a mute list
    confMuteLtr: function (btn_flag) {
      if (typeof GM_getValue(btn_flag) !== "undefined" && setting.muteNameArray[btn_flag][0] !== "") {
        alert(this.altMsgAry[userLang][2] + setting.muteNameArray[btn_flag]);
      }
      else {
        alert(this.altMsgAry[userLang][3]);
      }
    },
    completeComp: function (targetLtr) {
      if (this.muteFlag === 0 && this.targetText === targetLtr) {
        this.muteFlag = 1;
      }
    },
    filterFunc: function (targetLtr) {
      return (this.targetText !== targetLtr);
    }
  };

  MuteFeatures.prototype = {
    muteTweet: function (addedTweets) {
      // remove promoted tweet
      if (document.querySelectorAll("[data-promoted='true']") !== null) {
        Array.prototype.slice.call(document.querySelectorAll("[data-promoted='true']")).forEach(
          function (targetNode) {
            targetNode.parentNode.style.display = "none";
          }
        );
      }
      // remove a banner of header
      if (document.querySelector("[class='promptbird promptbird-below-black-bar']") !== null) {
        document.querySelector("[class='promptbird promptbird-below-black-bar']").style.display = "none";
      }

      // when nodes are added
      if (typeof addedTweets !== "undefined") {
        this.homeTweets = Array.prototype.slice.call(addedTweets);
      }
      // when nodes are not added
      else {
        this.homeTweets = Array.prototype.slice.call(document.querySelectorAll("[data-item-type]"));
      }
      this.homeTweets.forEach(this.nodeCheck, muteAction);
    },
    nodeCheck: function (targetNode) {
      var tweetPtag;
      if (targetNode.hasAttribute("data-item-type")) {
        this.tweetPrnt = targetNode;
        if (typeof this.tweetPrnt.childNodes[1].childNodes[3] !== "undefined") {
          tweetPtag = this.tweetPrnt.childNodes[1].childNodes[3].childNodes[3];
        }
        // reply
        if (typeof tweetPtag === "undefined") {
          if (pageURL === "https://twitter.com/") {
            for (this.i = 3; typeof this.tweetPrnt.childNodes[1].childNodes[this.i] !== "undefined"; this.i++) {
              this.replyPrnt = this.tweetPrnt.childNodes[1].childNodes[this.i];
              if (
                typeof this.replyPrnt.childNodes[1] !== "undefined" &&
                this.replyPrnt.childNodes[1].getAttribute("data-you-block")
              ) {
                this.tweetPrnt = this.replyPrnt;
                tweetPtag = this.replyPrnt.childNodes[1].childNodes[3].childNodes[3];
                this.tweetElmCheck(tweetPtag);
                this.tweetPrnt = targetNode;
              }
            }
          }
          else {
            if (
              this.tweetPrnt.childNodes[1].className !== "account-group js-account-group js-user-profile-link" &&
              this.tweetPrnt.childNodes[1].className !== "avatar size32 js-user-profile-link"
            ) {
              tweetPtag = this.tweetPrnt.childNodes[1].childNodes[1].childNodes[1].childNodes[3].childNodes[3];
              this.tweetElmCheck(tweetPtag);
            }
          }
        }
        // not reply
        else {
          // on Search page, timeline
          if (tweetPtag.className === "fullname js-action-profile-name show-popup-with-id") {
            tweetPtag = this.tweetPrnt.childNodes[1].childNodes[5];
          }
          this.tweetElmCheck(tweetPtag);
        }
      }
    },
    tweetElmCheck: function(twtPtag) {
      for (this.j = 0; typeof twtPtag.childNodes[this.j] !== "undefined"; this.j++) {
        this.tweetElement = twtPtag.childNodes[this.j];
        // <A> tag
        if (this.tweetElement.nodeName === "A") {
          // "pic.twitter.com"
          if (this.tweetElement.hasAttribute("data-pre-embedded")) {
            this.tweetElement.setAttribute("href", "http://" + this.tweetElement.childNodes[0].nodeValue);
            this.muteLtrCheck("mute_links");
          }
          // not "pic.twitter.com"
          else if (this.tweetElement.hasAttribute("title")) {
            this.tweetElement.setAttribute("href", this.tweetElement.getAttribute("title"));
            this.muteLtrCheck("mute_links");
          }
          // hashtags
          else if (this.tweetElement.hasAttribute("data-query-source")) {
            this.muteLtrCheck("mute_tags");
          }
          // userIDs
          else if (this.tweetElement.childNodes[0].childNodes[0].nodeValue === "@") {
            this.muteLtrCheck("mute_ids");
          }
        }
        // text or <STRONG> tag
        else if (this.tweetElement.nodeName === "#text" || this.tweetElement.nodeName === "STRONG") {
          this.muteLtrCheck("mute_words");
        }
      }
    },
    muteLtrCheck: function (mute_flag) {
      if (typeof GM_getValue(mute_flag) !== "undefined" && setting.muteNameArray[mute_flag][0] !== "") {
        this.flag = mute_flag;
        setting.muteNameArray[mute_flag].forEach(this.muteFunc, muteAction);
      }
    },
    muteFunc: function (targetLtr) {
      var nodeValTemp = "";
      switch (this.flag) {
        case "mute_words":
          if (GM_getValue("mute_text_flag") === true) {
            // text
            if (this.tweetElement.nodeName === "#text") {
              if (this.tweetElement.nodeValue.indexOf(targetLtr) >= 0) {
                this.tweetPrnt.style.display = "none";
              }
            }
            // <STRONG> tag
            else {
              // add the previous text if it exists
              if (this.tweetElement.previousSibling !== null && this.tweetElement.previousSibling.nodeName === "#text") {
                nodeValTemp = this.tweetElement.previousSibling.nodeValue;
              }
              // text of <STRONG> tag
              nodeValTemp += this.tweetElement.childNodes[0].nodeValue;
              // add the next text if it exists
              if (this.tweetElement.nextSibling !== null && this.tweetElement.nextSibling.nodeName === "#text") {
                nodeValTemp += this.tweetElement.nextSibling.nodeValue;
              }
              // alert(nodeValTemp);
              if (nodeValTemp.indexOf(targetLtr) >= 0) {
                this.tweetPrnt.style.display = "none";
              }
            }
          }
          break;
        case "mute_links":
          if (GM_getValue("mute_link_flag") === true) {
            // not "pic.twitter.com"
            if (this.tweetElement.hasAttribute("title")) {
              if (this.tweetElement.getAttribute("title").indexOf(targetLtr) >= 0) {
                this.tweetPrnt.style.display = "none";
              }
            }
            // "pic.twitter.com"
            else if (this.tweetElement.textContent.indexOf(targetLtr) >= 0) {
              this.tweetPrnt.style.display = "none";
            }
          }
          break;
        case "mute_tags":
          if (
            GM_getValue("mute_tag_flag") === true &&
            this.tweetElement.childNodes[1].textContent.indexOf(targetLtr) >= 0
          ) {
            this.tweetPrnt.style.display = "none";
          }
          break;
        case "mute_ids":
          if (
            GM_getValue("mute_userId_flag") === true &&
            this.tweetElement.childNodes[1].textContent.indexOf(targetLtr) >= 0
          ) {
            this.tweetPrnt.style.display = "none";
          }
          break;
      }
    }
  };

  setting = new Init();
  header = new HeaderStruct();
  buttonAction = new ButtonSet();
  muteAction = new MuteFeatures();

  setting.accessSet();
  header.styleSet();
  muteAction.muteTweet();

  if (GM_getValue("style_flag") === true) {
    tweetStyleChange();
  }

  // events of all buttons------------------------------------------------------------------------------
  document.addEventListener("click", function (e) {
    var tgtNode = e.target; // nodes clicked
    switch (tgtNode.id) {
      // input form
      case "open_close":
        if (GM_getValue("form_flag") === true) {
          if (pageURL === "https://twitter.com/") {
            header.contentHeader.style.display = "none";
          } else {
            header.formNode.style.display = "none";
          }
          GM_setValue("form_flag", false);
        } else {
          if (pageURL === "https://twitter.com/") {
            header.contentHeader.style.display = "block";
          } else {
            header.formNode.style.display = "block";
          }
          GM_setValue("form_flag", true);
        }
        break;
      case "mLtrAdd":
        buttonAction.addMuteLtr(document.querySelector("[checked]").value, document.getElementById("mLtrForm").value);
        break;
      case "mLtrRmv":
        buttonAction.delMuteLtr(document.querySelector("[checked]").value, document.getElementById("mLtrForm").value);
        break;
      case "mLtrConf":
        buttonAction.confMuteLtr(document.querySelector("[checked]").value);
        break;
      default:
        // radio buttons
        if (tgtNode.name === "muteLetter") {
          // remove the attribute "checked", if it already exists
          if (document.querySelector("[checked]")) {
            document.querySelector("[checked]").removeAttribute("checked");
          }
          tgtNode.setAttribute("checked", "checked");
        }
        break;
    }
  }, false);

  // MutationObserver(Timeline)-------------------------------------------------------------------------
  observer = new MutationObserver(function (mutations) {
    mutations.forEach(function (mutation) {
      var nodesWidth = 0, nodesList, i;
      if (mutation.addedNodes.length !== 0) {
        nodesList = mutation.addedNodes;
        muteAction.muteTweet(nodesList);
        // a scroll bar is back
        if (flag_autoRef === 1) {
          setTimeout(function() {
            if (scrHeight !== 0) {
              for (i = 0; i < nodesList.length; i++) {
                nodesWidth += nodesList[i].clientHeight;
              }
              scrHeight = scrHeight + nodesWidth - 38;
            }
            window.scrollTo(0, scrHeight);
          }, parseInt(GM_getValue("time")));
          flag_autoRef = 0;
        }
      }
      if (GM_getValue("style_flag") === true) {
        tweetStyleChange();
      }
    });
  });
  observer.observe(document.getElementById("stream-items-id"), {childList: true } );

  // Auto refresh---------------------------------------------------------------------------------------
  if (GM_getValue("autoRefresh_flag") === true) {
    // init mouse event
    mouse_event = document.createEvent("MouseEvents");
    mouse_event.initMouseEvent("click", true, true, window, 0, 0, 0, 0, 0, false, false, false, false, 0, null);
    // MutationObserver(Auto refresh)
    observerSub = new MutationObserver(function (mutations) {
      mutations.forEach(function (mutation) {
        if (mutation.addedNodes.length !== 0) {
          flag_autoRef = 1;
          scrHeight = window.pageYOffset;
          mutation.addedNodes[0].dispatchEvent(mouse_event);
        }
      });
    });
    observerSub.observe(document.querySelector("[class='stream-item js-new-items-bar-container']"), {childList: true } );
  }
})();