VKontakte: имя меню "Группы" вместо "Сообщества"

Возвращает старое название секции групп обратно вместо нового названия "Сообщества". Работает для заголовка вкладки и левой панели ссылок

当前为 2019-12-19 提交的版本,查看 最新版本

// ==UserScript==
// @name         VKontakte: имя меню "Группы" вместо "Сообщества"
// @description  Возвращает старое название секции групп обратно вместо нового названия "Сообщества". Работает для заголовка вкладки и левой панели ссылок
// @version      1.0.0
// @author       https://vk.me/id222792011
// @match        http*://vk.com/*
// @run-at       document-start
// @grant        none
// @noframes
// @namespace https://gf.qytechs.cn/users/424058
// ==/UserScript==

(function() {
  'use strict';

  const soughtFor = 'Сообщества';
  const changeTo  = 'Группы';

  const entities  = {

    1: {
      query: 'title',
      // timeout: {ev: 'DOMContentLoaded', de: 30000},
      cb: titleFix
    },

    2: {
      query: 'span.left_label.inl_bl',
      // timeout: {ev: 'DOMContentLoaded', de: 30000},
      cb: (foundNodes, obs) => {
        for (let node of foundNodes) {
          if (node.innerText.indexOf(soughtFor) != -1) {
            node.innerText = node.innerText.replace(soughtFor, changeTo);
            obs.unsubscribe(2);
            break;
          }
        }
      }
    }

  }

  watching(document, entities);

  function watching(observedNode, entities) {
    const observer = new MutationObserver((mutationsList, observer) => {

      for (const ent in entities) {
        if (!ent.timeout || !ent.timeout.ev) { continue }
        document.addEventListener(ent.timeout.ev, () => {
          setTimeout(() => { observer.disconnect() }, ent.timeout.de || 0);
        });
      }

      for (let mutation of mutationsList) {
        for (let node of mutation.addedNodes) {
          for (const ent in entities) {

            // node.nodeType = 3 equals text changes type
            if (node.nodeType === 3) {

              /* example entities[ent].query: 'span.claSs.name.te-_st.123#i-_d'
              output: {
                classList: ["claSs", "name", "te-_st"]
                id: "i-_d"
                tag: "span"
              }*/
              let queryObj = {
                tag: (entities[ent].query.match(/(?<=^| )[a-z]+/ig) || [])[0],
                id:  (entities[ent].query.match(/(?<=#)([a-z]|_|-)+/i) || [])[0],
                classList: entities[ent].query.match(/(?<=\.)([a-z]|-|_)+/ig) || []
              }

              let
              queryTagCheck = false,
              queryIdCheck = false,
              queryClassesCheck = false;

              if (queryObj.tag ? (mutation.target.localName == queryObj.tag.toLowerCase()) : true) {
                queryTagCheck = true;
              }
              if (queryObj.id ? (mutation.target.id == queryObj.id) : true) {
                queryIdCheck = true;
              }
              if (classListsCompare(queryObj.classList, mutation.target.classList)) {
                queryClassesCheck = true;
              }

              if (queryTagCheck && queryIdCheck && queryClassesCheck) {
                entities[ent].cb([mutation.target], observer);
                continue;
              }

            }

            // node.nodeType = 1 means that the node is Element node, like <p> or <div>
            if (node.nodeType === 1) {
              // the sought-for node can be inside the current, as a child node
              // but also the current node can be the sought-for too,
              // so search should be started from the next level parent
              let nodes = (node.parentNode || document).querySelectorAll(entities[ent].query);
              if (nodes.length) entities[ent].cb(nodes, observer);
            }

          }
        }
      }

    });
    observer.entities = entities;
    observer.unsubscribe = function(entityId) {
      if (entityId || entityId === 0) delete this.entities[entityId];
      if (Object.keys(this.entities).length == 0) this.disconnect();
    }
    observer.observe(observedNode, { childList: true, subtree: true });
  }


  // if the title was generated before observer's init
  // but if title was not yet recieved at all - try-catch
  try { titleFix() } catch(e) {}


  // utils ------------------------------------

  function titleFix() {
    if (
      window.location.href.indexOf('://vk.com/groups') != -1
      &&
      document.title.indexOf(soughtFor) != -1
    ) {
      document.title = document.title.replace(soughtFor, changeTo)
    }
  }

  function classListsCompare(queryArr = [], nodeClassList = []) {
    const classListArr = Array.prototype.slice.call(nodeClassList);

    for (let i = 0; i < classListArr.length; i++) { classListArr[i] = classListArr[i].toLowerCase() }

    for (let i = 0; i < queryArr.length; i++) {
      if (
        queryArr[i].length > 0
        &&
        Array.prototype.indexOf.call(classListArr, queryArr[i].toLowerCase()) == -1
      ) {
        return false;
      }
    }

    return true;
  }

  // ------------------------------------------

})();

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址