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

3,729 バイト追加 、 2019年6月25日 (火) 00:32
編集の要約なし
編集の要約なし
タグ: モバイル編集 モバイルウェブ編集
編集の要約なし
タグ: モバイル編集 モバイルウェブ編集
2行目: 2行目:


/**
/**
  * @typedef MobileUIMenuItem
  * @typedef {import("jquery")} _JQueryStatic
  * @prop {string} title
*/
  * @prop {string} page
 
/**
* @typedef MenuDataItemComponent
  * @prop {string} [text]
* @prop {string} [title]
* @prop {string} [href]
* @prop {string} [id]
* @prop {string | string[]} [class]
* @prop {string} [dataEventName]
*/
 
/**
* @typedef MenuDataItem
  * @prop {string} [id]
  * @prop {string | string[]} [class]
  * @prop {string | string[]} [class]
* @prop {MenuDataItemComponent[]} components
  */
  */


/**
/**
  * @typedef MobileUI
  * @typedef MenuDataGroup
  * @prop {MobileUIMenuItem[]} menu
  * @prop {string} [id]
* @prop {string | string[]} [class]
* @prop {MenuDataItem[]} items
  */
  */


/**
/**
  * @param {import("jquery")} $
  * @typedef MobileUI
  * @param {any} mw
* @prop {MenuDataGroup[]} leftGroups
  * @param {MobileUI} mobileUI
  * @prop {MenuDataGroup} leftShortURLGroup
  * @prop {MenuDataGroup[]} rightGroups
  */
  */
function applyMobileUI($, mw, mobileUI) {
    const config = {
        wgArticleId: Number(),
        wgServer: "",
        wgScriptPath: String(),
    };


     Object.assign(config, mw.config.get(Object.keys(config)));
class MobileUIBuilder {
     /**
    * @param {any} mw
    * @param {JQueryStatic} $
    */
    constructor(mw, $) {
        this.mw = mw;
        this.$ = $;


    const wikiURL = `${config.wgServer}${config.wgScriptPath}`;
        /**
        * @type {string}
        */
        this.wgServer = mw.config.get("wgServer");
 
        /**
        * @type {string}
        */
        this.wgScriptPath = mw.config.get("wgScriptPath");
 
        /**
        * @type {number}
        */
        this.wgArticleId = mw.config.get("wgArticleId");
    }


     /**
     /**
     * @type {JQuery<HTMLElement>[]}
     * @param {MenuDataItemComponent} component
    * @returns {string}
     */
     */
     const groups = [];
     hrefForMenuDataItemComponent(component) {
        switch (component.id) {
            case "page-short-url":
                return (
                    this.wgServer
                    + this.wgScriptPath
                    + "?curid="
                    + String(this.wgArticleId)
                );


    const ul = $("<ul>");
            default:
                return component.title
                    ? (this.wgScriptPath + "/" + component.title)
                    : component.href;
        }
    }


     groups.push(ul);
     /**
    * @param {MenuDataItemComponent} component
    * @returns {JQuery<HTMLElement>}
    */
    menuDataItemComponent(component) {
        const href = this.hrefForMenuDataItemComponent(component);


    for (const menuItem of mobileUI.menu) {
        return this
        const li = $("<li>").appendTo(ul);
            .$("<a>")
            .text(component.text || href)
            .attr("href", href)
            .attr("id", component.id)
            .addClass(component.class)
            .attr("data-event-name", component.dataEventName);
    }


         $("<a>")
    /**
             .text(menuItem.title)
    * @param {MenuDataItem} item
             .addClass(["mw-ui-icon", "mw-ui-icon-before"])
    * @returns {JQuery<HTMLElement>}
             .attr("href", menuItem.page)
    */
             .appendTo(li);
    menuDataItem(item) {
         /**
        * @type {JQuery<HTMLElement>[]}
        */
        const children = [];
 
        for (const component of item.components) {
             children.push(this.menuDataItemComponent(component));
        }
 
        return this
             .$("<li>")
             .attr("id", item.id)
            .addClass(item.class)
             .append(children);
     }
     }


     if (config.wgArticleId > 1) {
     /**
         const hlist = $("<ul>")
    * @param {MenuDataGroup} group
            .addClass("hlist")
    * @returns {JQuery<HTMLElement>}
            .css("word-break", "break-all");
    */
    menuDataGroup(group) {
         /**
        * @type {JQuery<HTMLElement>[]}
        */
        const children = [];


         const li = $("<li>").appendTo(hlist);
         for (const item of group.items) {
        const dl = $("<dl>").appendTo(li);
            children.push(this.menuDataItem(item));
        }


         $("<dt>")
         return this
             .text("ページの短縮URL")
            .$("<ul>")
             .css("display", "block")
             .attr("id", group.id)
            .css("padding-left", "1em")
             .addClass(group.class)
             .appendTo(dl);
             .append(children);
    }


         const dd = $("<dd>")
    /**
             .css("display", "block")
    * @param {MenuDataGroup[]} groups
            .appendTo(dl);
    * @returns {JQuery<HTMLElement>[]}
    */
    menuDataGroups(groups) {
        /**
        * @type {JQuery<HTMLElement>[]}
        */
         const children = [];
 
        for (const group of groups) {
             children.push(this.menuDataGroup(group));
        }
 
        return children;
    }
 
    /**
    * @param {Node} node
    * @returns {HTMLElement | null}
    */
    elementIfTarget(node) {
        const element = /** @type {HTMLElement} */ (node);
        const { classList } = element;
 
        if (!classList) return null;
        if (!classList.contains("menu")) return null;
        if (classList.contains("menu-right")) return null;
 
        return element;
    }
 
    /**
    * @returns {HTMLElement}
    */
    get navElement() {
        return window.document.getElementById("mw-mf-page-left");
    }


         const shortURL = `${wikiURL}/?curid=${config.wgArticleId}`;
    /**
    * @returns {HTMLElement | null}
    */
    get menuElement() {
         return /** @type {HTMLElement} */ (
            this.navElement.getElementsByClassName("menu").item(0)
        );
    }


        $("<a>")
    /**
            .text(shortURL)
    * @param {MobileUI} mobileUI
            .attr("href", shortURL)
    * @param {HTMLElement} menuElement
            .appendTo(dd);
    */
    modify(mobileUI, menuElement) {
        const leftGroups = this.menuDataGroups(mobileUI.leftGroups);
        const rightGroups = [];


         groups.push(hlist);
         const jqMenu = this.$(menuElement);
        jqMenu.find("ul").first().remove();
        jqMenu.prepend(leftGroups);
 
        this
            .$("<div>")
            .addClass(["menu", "menu-right"])
            .append(rightGroups)
            .insertAfter(jqMenu);
     }
     }


     $(".menu").ready($ => {
     /**
        const menu = $(".menu");
    * @param {MobileUI} mobileUI
        menu.find("ul").first().remove();
    */
         menu.prepend(groups);
    build(mobileUI) {
     });
        const element = this.menuElement;
 
        if (element) {
            this.modify(mobileUI, element);
            return;
        }
 
        const observer = new MutationObserver((mutations, observer) => {
            for (const record of mutations) {
                for (const node of record.addedNodes) {
                    const element = this.elementIfTarget(node);
                    if (element) {
                        observer.disconnect();
                        this.modify(mobileUI, element);
                        return;
                    }
                }
            }
        });
 
         observer.observe(this.navElement, { childList: true });
     }
}
}