「MediaWiki:Common.js」の版間の差分

提供:WikiNebula
編集の要約なし
編集の要約なし
 
(同じ利用者による、間の15版が非表示)
1行目: 1行目:
/* ここにあるすべてのJavaScriptは、すべてのページ読み込みですべての利用者に対して読み込まれます */
/* ここにあるすべてのJavaScriptは、すべてのページ読み込みですべての利用者に対して読み込まれます */
function my_switch(){
function my_switch(){
   var uri = new URL(window.location.href);
   var uri = new URL(window.location.href);
31行目: 30行目:
         "nebula_switch: 閲覧モードでないため、入れ替えは行いません"
         "nebula_switch: 閲覧モードでないため、入れ替えは行いません"
       );
       );
  }else{
    var uri = new URL(window.location.href);
    if (is_view_mode(uri)){
      if (document.getElementById("nebula_switch")){
        uri.searchParams.append("nebula_switch", "");
        document.getElementsByClassName("mw-parser-output")[0].innerHTML
        += "<h2>お知らせ:この記事は、「男女逆にして」表示できます</h2>"
        + "<p>WikiNebula では、女性に対して向けられるべきではないような"
        + "差別や冷遇が、男性に対しては現実に起きてしまっていることを、"
        + "記事として取り上げています。</p>"
        + "<p>そのため、 WikiNebula には、男性が経験するこの種の"
        + "差別や女尊男卑を理解しやすくするために、"
        + "男女の立場を入れ替えて表示する「男女入れ替えスイッチ」"
        + "の機能があります。</p>"
        + "<p>現在、男女入れ替えスイッチが無効になっています。"
        + "有効にするには、<a href='" + uri.toString() +"'>こちら</a>を"
        + "クリックしてください</p>";
      }
    }
   }
   }


138行目: 156行目:
     });
     });


     var url = new URL(window.location.href);
     var uri = new URL(window.location.href);
     url.searchParams.delete("nebula_switch");
     uri.searchParams.delete("nebula_switch");
     content_node.innerHTML
     content_node.innerHTML
     += "<h2>お知らせ:この記事は、「男女逆にして」表示されています</h2>"
     += "<h2>お知らせ:この記事は、「男女逆にして」表示されています</h2>"
150行目: 168行目:
     + "の機能があります。</p>"
     + "の機能があります。</p>"
     + "<p>現在、男女入れ替えスイッチが有効になっています。"
     + "<p>現在、男女入れ替えスイッチが有効になっています。"
     + "無効にするには、<a href='" + url.toString() +"'>こちら</a>を"
     + "無効にするには、<a href='" + uri.toString() +"'>こちら</a>を"
     + "クリックしてください</p>";
     + "クリックしてください</p>";


182行目: 200行目:


my_switch();
my_switch();
/* ===== SNSシェアボタン ===== */
mw.loader.using('mediawiki.util').then(function () {
    $(function () {
        if (
            mw.config.get('wgAction') !== 'view' ||
            !mw.config.get('wgIsArticle') ||
            [0, 4].indexOf(mw.config.get('wgNamespaceNumber')) === -1 ||
            new URL(location.href).searchParams.has('veaction') ||
            document.getElementById('wn-share-top')
        ) {
            return;
        }
        var content = document.getElementById('mw-content-text');
        if (!content) {
            return;
        }
        var url = new URL(
            mw.util.getUrl(mw.config.get('wgPageName')),
            location.origin
        ).href;
        var title = mw.config.get('wgTitle') + ' | WikiNebula';
        var u = encodeURIComponent(url);
        var t = encodeURIComponent(title);
        var xText = encodeURIComponent(title + ' @WikiNebulaPR');
        var services = [
            {
                name: 'x',
                label: 'Xでシェア',
                shortLabel: 'X',
                url: 'https://twitter.com/intent/tweet?url=' + u +
                    '&text=' + xText
            },
            {
                name: 'facebook',
                label: 'Facebookでシェア',
                shortLabel: 'Facebook',
                url: 'https://www.facebook.com/sharer/sharer.php?u=' + u
            },
            {
                name: 'line',
                label: 'LINEで送る',
                shortLabel: 'LINE',
                url: 'https://social-plugins.line.me/lineit/share?url=' +
                    u + '&text=' + t
            }
        ];
        function makeBar(position) {
            var bar = document.createElement('nav');
            bar.id = 'wn-share-' + position;
            bar.className = 'wn-share wn-share--' + position;
            bar.setAttribute('aria-label', 'この記事をシェア');
            services.forEach(function (service) {
                var link = document.createElement('a');
                link.className = 'wn-share__button';
                link.textContent = position === 'sidebar' ?
                    service.shortLabel : service.label;
                link.setAttribute('aria-label', service.label);
                link.setAttribute('data-service', service.name);
                link.href = service.url;
                link.target = '_blank';
                link.rel = 'noopener noreferrer';
                bar.appendChild(link);
            });
            return bar;
        }
        content.insertBefore(makeBar('top'), content.firstChild);
        content.appendChild(makeBar('bottom'));
        var sidebar = document.querySelector(
            '.skin-vector-2022 .vector-main-menu-container'
        );
        if (sidebar) {
            sidebar.insertBefore(makeBar('sidebar'), sidebar.firstChild);
        }
    });
});
/* ===== 公式案内:PCは左側、小さい画面はヘッダー直下 ===== */
$(function () {
    if (!document.body.classList.contains('skin-vector-2022')) {
        return;
    }
    var official = document.getElementById('p-公式案内');
    var sidebar = document.querySelector('.vector-main-menu-container');
    var header = document.querySelector('.vector-header-container');
    if (!official || !sidebar || !header) {
        return;
    }
    // リンク先はMediaWiki:Sidebarから読み取り、URLを二重管理しない
    var mobileHost = document.createElement('div');
    mobileHost.className = 'wn-official-mobile-host';
    header.appendChild(mobileHost);
    official.classList.add('wn-official-links');
    official.setAttribute('role', 'navigation');
    official.setAttribute('aria-label', '公式案内');
    var mobileLabels = {
        'x.com': '公式X',
        'twitter.com': '公式X',
        'facebook.com': '公式Facebook',
        'line.me': '公式オプチャ'
    };
    var labels = Array.from(official.querySelectorAll('a')).map(function (link) {
        var label = link.firstElementChild || link;
        var hostname = new URL(link.href, location.href).hostname.replace(/^www\./, '');
        return {
            element: label,
            full: label.textContent,
            compact: mobileLabels[hostname] || label.textContent
        };
    });
    var wideScreen = window.matchMedia('(min-width: 1200px)');
    function placeOfficialLinks() {
        labels.forEach(function (label) {
            label.element.textContent = wideScreen.matches ? label.full : label.compact;
        });
        if (wideScreen.matches) {
            var navigation = document.getElementById('mw-navigation');
            sidebar.insertBefore(
                official,
                navigation && navigation.parentNode === sidebar ? navigation : null
            );
        } else {
            mobileHost.appendChild(official);
        }
    }
    placeOfficialLinks();
    wideScreen.addEventListener('change', placeOfficialLinks);
});

2026年10月19日 (月) 18:00時点における最新版

/* ここにあるすべてのJavaScriptは、すべてのページ読み込みですべての利用者に対して読み込まれます */
function my_switch(){
  var uri = new URL(window.location.href);
  var is_switched = uri.searchParams.get("nebula_switch") != null;
  if (is_switched){
    console.log("nebula_switch: 入れ替え後のページです");

    if (is_view_mode(uri)){
      console.log("nebula_switch: 閲覧モードです");

      var parser = new Switch_parser();
      if (parser.parse(document.getElementById("nebula_switch"))){
        if (parser.tag_exists){
          console.log(
            "nebula_switch: 入れ替えタグの解析に成功しました"
          );

          nebula_run(parser.doc);
        }else{
          console.log("nebula_switch: 入れ替えタグがありません");
        }
      }else{
        console.log("nebula_switch: 入れ替えタグが異常です");
        nebula_write_error(parser.failed_message);
      }
      
      
    }else
      console.log(
        "nebula_switch: 閲覧モードでないため、入れ替えは行いません"
      );
  }else{
    var uri = new URL(window.location.href);
    if (is_view_mode(uri)){
      if (document.getElementById("nebula_switch")){
        uri.searchParams.append("nebula_switch", "");
        document.getElementsByClassName("mw-parser-output")[0].innerHTML
        += "<h2>お知らせ:この記事は、「男女逆にして」表示できます</h2>"
        + "<p>WikiNebula では、女性に対して向けられるべきではないような" 
        + "差別や冷遇が、男性に対しては現実に起きてしまっていることを、"
        + "記事として取り上げています。</p>"
        + "<p>そのため、 WikiNebula には、男性が経験するこの種の" 
        + "差別や女尊男卑を理解しやすくするために、"
        + "男女の立場を入れ替えて表示する「男女入れ替えスイッチ」"
        + "の機能があります。</p>"
        + "<p>現在、男女入れ替えスイッチが無効になっています。"
        + "有効にするには、<a href='" + uri.toString() +"'>こちら</a>を"
        + "クリックしてください</p>";
      }
    }
  }

}

  function is_view_mode(uri){
    var view_tab = document.getElementById("ca-view");
    if (view_tab)
      var is_view_mode_selected
        = view_tab.classList.contains("selected");
    else
      var is_view_mode_selected = false;
    var is_not_ve_edit_mode = uri.searchParams.get("veaction") == null;
    return is_view_mode_selected && is_not_ve_edit_mode;
  }

  // ES5 なので class 構文は使えない・・・
  function Switch_parser(){
    if (this === null) throw new TypeError();
  }
  Switch_parser.prototype = {
    constructor: Switch_parser,
    parse: function(switch_tag){
      // パース成功の真偽値を返却する
      
      if (switch_tag == null){
        this.tag_exists = false;
        return true;
      }
      this.tag_exists = true;
      
      if (!window.DOMParser){
        this.failed_message = "DOMParser が有効ではありません。"
        + "お使いのブラウザで DOMParser を有効にしてください。";
        return false;
      }
      
      var dom_parser = new DOMParser();
      var doc = dom_parser.parseFromString(
        "<root>" + switch_tag.innerText + "</root>", "text/xml"
      );
      var parser_error = doc.querySelector("parsererror");
      if (parser_error){
        this.failed_message = "入れ替えタグに構文エラーがありました\n"
        + parser_error.innerHTML;
        return false;
      }
      this.doc = doc;
      return true;

    }
  };

  function nebula_write_error(message){
    var content_node = 
      document.getElementsByClassName("mw-parser-output")[0];
    content_node.innerHTML = 
      "<h1>エラー: 男女入れ替えスイッチでエラー</h1>" + message
    throw new Error("nebula_switch: " + message);
  }

  function nebula_run(doc){
    var content_node
    = document.getElementsByClassName("mw-parser-output")[0];
    Array.from(doc.children[0].children).forEach(function(tag){
      if (tag.tagName.toLowerCase() == "replace"){
        var is_syntax_error = !(
             tag.childNodes[0].nodeName == "#text"
          && tag.childNodes[1].nodeName.toLowerCase() == "to"
          && tag.childNodes[2].nodeName == "#text"
          && tag.childNodes.length == 3
        );
        if (is_syntax_error){
          nebula_write_error(
            "次のreplace タグが構文エラーです。<br>"
            + "<code>" + code_escape(tag.outerHTML) + "</code>"
          );
        }
        var before = code_unescape(tag.childNodes[0].nodeValue);
        var after  = code_unescape(tag.childNodes[2].nodeValue);
        
        content_node.innerHTML
        = content_node.innerHTML.replaceAll(before, after);

      }

      if (tag.tagName.toLowerCase() == "swap"){
        var is_syntax_error = !(
             tag.childNodes[0].nodeName == "#text"
          && tag.childNodes[1].nodeName.toLowerCase() == "for"
          && tag.childNodes[2].nodeName == "#text"
          && tag.childNodes.length == 3
        );
        if (is_syntax_error){
          nebula_write_error(
            "次のreplace タグが構文エラーです。<br>"
            + "<code>" + code_escape(tag.outerHTML) + "</code>"
          );
        }
        var A = code_unescape(tag.childNodes[0].nodeValue);
        var B = code_unescape(tag.childNodes[2].nodeValue);
        
        content_node.innerHTML
        = swap_string(content_node.innerHTML, A, B);

      }
    });

    var uri = new URL(window.location.href);
    uri.searchParams.delete("nebula_switch");
    content_node.innerHTML
    += "<h2>お知らせ:この記事は、「男女逆にして」表示されています</h2>"
    + "<p>WikiNebula では、女性に対して向けられるべきではないような" 
    + "差別や冷遇が、男性に対しては現実に起きてしまっていることを、"
    + "記事として取り上げています。</p>"
    + "<p>そのため、 WikiNebula には、男性が経験するこの種の" 
    + "差別や女尊男卑を理解しやすくするために、"
    + "男女の立場を入れ替えて表示する「男女入れ替えスイッチ」"
    + "の機能があります。</p>"
    + "<p>現在、男女入れ替えスイッチが有効になっています。"
    + "無効にするには、<a href='" + uri.toString() +"'>こちら</a>を"
    + "クリックしてください</p>";

  }
    function code_escape(code){
      var textarea = document.createElement("textarea");
      textarea.innerText = code;
      return textarea.innerHTML;
    }

    function code_unescape(code){
      var textarea = document.createElement("textarea");
      textarea.innerHTML = code;
      return textarea.innerText;
    }

    function swap_string(input_string, x, y) {
      // xとyを正規表現の特殊文字からエスケープする
      x = x.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
      y = y.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');

      // xとyを入れ替える
      var regex = new RegExp('(' + x + '|' + y + ')', 'g');
      var result = input_string.replace(regex, function(match) {
        return match === x ? y : x;
      });

      return result;
    }


my_switch();


/* ===== SNSシェアボタン ===== */
mw.loader.using('mediawiki.util').then(function () {
    $(function () {
        if (
            mw.config.get('wgAction') !== 'view' ||
            !mw.config.get('wgIsArticle') ||
            [0, 4].indexOf(mw.config.get('wgNamespaceNumber')) === -1 ||
            new URL(location.href).searchParams.has('veaction') ||
            document.getElementById('wn-share-top')
        ) {
            return;
        }

        var content = document.getElementById('mw-content-text');
        if (!content) {
            return;
        }

        var url = new URL(
            mw.util.getUrl(mw.config.get('wgPageName')),
            location.origin
        ).href;
        var title = mw.config.get('wgTitle') + ' | WikiNebula';
        var u = encodeURIComponent(url);
        var t = encodeURIComponent(title);
        var xText = encodeURIComponent(title + ' @WikiNebulaPR');

        var services = [
            {
                name: 'x',
                label: 'Xでシェア',
                shortLabel: 'X',
                url: 'https://twitter.com/intent/tweet?url=' + u +
                    '&text=' + xText
            },
            {
                name: 'facebook',
                label: 'Facebookでシェア',
                shortLabel: 'Facebook',
                url: 'https://www.facebook.com/sharer/sharer.php?u=' + u
            },
            {
                name: 'line',
                label: 'LINEで送る',
                shortLabel: 'LINE',
                url: 'https://social-plugins.line.me/lineit/share?url=' +
                    u + '&text=' + t
            }
        ];

        function makeBar(position) {
            var bar = document.createElement('nav');
            bar.id = 'wn-share-' + position;
            bar.className = 'wn-share wn-share--' + position;
            bar.setAttribute('aria-label', 'この記事をシェア');

            services.forEach(function (service) {
                var link = document.createElement('a');
                link.className = 'wn-share__button';
                link.textContent = position === 'sidebar' ?
                    service.shortLabel : service.label;
                link.setAttribute('aria-label', service.label);
                link.setAttribute('data-service', service.name);
                link.href = service.url;
                link.target = '_blank';
                link.rel = 'noopener noreferrer';
                bar.appendChild(link);
            });

            return bar;
        }

        content.insertBefore(makeBar('top'), content.firstChild);
        content.appendChild(makeBar('bottom'));

        var sidebar = document.querySelector(
            '.skin-vector-2022 .vector-main-menu-container'
        );
        if (sidebar) {
            sidebar.insertBefore(makeBar('sidebar'), sidebar.firstChild);
        }
    });
});

/* ===== 公式案内:PCは左側、小さい画面はヘッダー直下 ===== */
$(function () {
    if (!document.body.classList.contains('skin-vector-2022')) {
        return;
    }

    var official = document.getElementById('p-公式案内');
    var sidebar = document.querySelector('.vector-main-menu-container');
    var header = document.querySelector('.vector-header-container');
    if (!official || !sidebar || !header) {
        return;
    }

    // リンク先はMediaWiki:Sidebarから読み取り、URLを二重管理しない
    var mobileHost = document.createElement('div');
    mobileHost.className = 'wn-official-mobile-host';
    header.appendChild(mobileHost);
    official.classList.add('wn-official-links');
    official.setAttribute('role', 'navigation');
    official.setAttribute('aria-label', '公式案内');

    var mobileLabels = {
        'x.com': '公式X',
        'twitter.com': '公式X',
        'facebook.com': '公式Facebook',
        'line.me': '公式オプチャ'
    };
    var labels = Array.from(official.querySelectorAll('a')).map(function (link) {
        var label = link.firstElementChild || link;
        var hostname = new URL(link.href, location.href).hostname.replace(/^www\./, '');
        return {
            element: label,
            full: label.textContent,
            compact: mobileLabels[hostname] || label.textContent
        };
    });
    var wideScreen = window.matchMedia('(min-width: 1200px)');

    function placeOfficialLinks() {
        labels.forEach(function (label) {
            label.element.textContent = wideScreen.matches ? label.full : label.compact;
        });

        if (wideScreen.matches) {
            var navigation = document.getElementById('mw-navigation');
            sidebar.insertBefore(
                official,
                navigation && navigation.parentNode === sidebar ? navigation : null
            );
        } else {
            mobileHost.appendChild(official);
        }
    }

    placeOfficialLinks();
    wideScreen.addEventListener('change', placeOfficialLinks);
});