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

編集の要約なし
編集の要約なし
165行目: 165行目:
</details>` : '';
</details>` : '';
                 // =================================================
                 // =================================================
                // ========== 書式ツールバーHTML ==========
                const toolbarHtml = `<div id="f-toolbar" style="margin-bottom:.4em;display:flex;gap:.3em;flex-wrap:wrap;align-items:center;padding:.3em;background:#f8f8f8;border:1px solid #ccc;border-radius:3px;">
<input type="button" class="mw-ui-button f-tb-btn" data-start="'''" data-end="'''" value="B" title="太字" style="font-weight:bold;min-width:2em;padding:0 .5em;">
<input type="button" class="mw-ui-button f-tb-btn" data-start="''" data-end="''" value="I" title="斜体" style="font-style:italic;min-width:2em;padding:0 .5em;">
<span style="font-size:.85em;color:#555;margin-left:.3em;">文字色:</span>
${['#cc0000','#e07000','#007700','#0055cc','#7700aa','#555555'].map(c =>
    `<span class="f-tb-color" data-color="${c}" title="${c}" style="display:inline-block;width:1.2em;height:1.2em;background:${c};border:2px solid #aaa;border-radius:2px;cursor:pointer;vertical-align:middle;"></span>`
).join('')}
</div>`;
                // =========================================


                 const msg = Object.assign({
                 const msg = Object.assign({
                     loading: '<p>読み込み中...</p>',
                     loading: '<p>読み込み中...</p>',
                     postform: `<div id="f-form"><h2>投稿${fedit ? `の編集 (<a href="#post-${fedit}")>#${fedit}</a>)` : ''}</h2>${anonSettingsHtml}<div class="mw-ui-checkbox" style="margin-bottom:.3em;${fedit ? 'display:none;' : ''}"><input type="checkbox" class="mw-ui-checkbox" id="f-reply-cb"><label for="f-reply-cb" style="user-select:none;">返信する</label></div><input type="number" id="f-reply" class="mw-ui-input" style="widht:50%;margin-bottom:.5em;"><textarea accesskey="," id="wpTextbox1" cols="80" rows="25" class="mw-editfont-monospace"></textarea><input type="button" id="f-post" value="投稿" class="mw-ui-button mw-ui-progressive" style="margin-top:.5em;"><input type="button" id="f-preview" value="プレビュー" class="mw-ui-button" style="margin: .5em 0 0 .5em;"><fieldset hidden><legend>プレビュー</legend><div id="f-preview-content"></div></fieldset><style>.mw-ui-checkbox:has(#f-reply-cb:checked)+input{display:block;}#f-reply{display:none;}</style></div>`,
                     postform: `<div id="f-form"><h2>投稿${fedit ? `の編集 (<a href="#post-${fedit}")>#${fedit}</a>)` : ''}</h2>${anonSettingsHtml}<div class="mw-ui-checkbox" style="margin-bottom:.3em;${fedit ? 'display:none;' : ''}"><input type="checkbox" class="mw-ui-checkbox" id="f-reply-cb"><label for="f-reply-cb" style="user-select:none;">返信する</label></div><input type="number" id="f-reply" class="mw-ui-input" style="widht:50%;margin-bottom:.5em;">${toolbarHtml}<textarea accesskey="," id="wpTextbox1" cols="80" rows="25" class="mw-editfont-monospace"></textarea><input type="button" id="f-post" value="投稿" class="mw-ui-button mw-ui-progressive" style="margin-top:.5em;"><input type="button" id="f-preview" value="プレビュー" class="mw-ui-button" style="margin: .5em 0 0 .5em;"><fieldset hidden><legend>プレビュー</legend><div id="f-preview-content"></div></fieldset><style>.mw-ui-checkbox:has(#f-reply-cb:checked)+input{display:block;}#f-reply{display:none;}</style></div>`,
                     postsummary: 'post',
                     postsummary: 'post',
                     replysummary: 'reply to',
                     replysummary: 'reply to',
                     editsummary: 'edit',
                     editsummary: 'edit',
                     deletesummary: 'delete post',
                     deletesummary: 'delete post',
                    deletethreadsummary: 'スレッドの削除',
                     toppage_css: "<style>.f-sticky>td:first-child>a::before{content:'';background-image:url(https://upload.wikimedia.org/wikipedia/commons/a/a5/OOjs_UI_icon_pushPin.svg);width:.8em;height:.8em;margin-right:.2em;display:inline-block;background-size:.8em}#f-loadmore{display:block;margin-left:auto;margin-right:auto;}</style>",
                     toppage_css: "<style>.f-sticky>td:first-child>a::before{content:'';background-image:url(https://upload.wikimedia.org/wikipedia/commons/a/a5/OOjs_UI_icon_pushPin.svg);width:.8em;height:.8em;margin-right:.2em;display:inline-block;background-size:.8em}#f-loadmore{display:block;margin-left:auto;margin-right:auto;}</style>",
                     load_more: '<input type="button" value="もっと読み込む" class="mw-ui-button" id="f-loadmore">',
                     load_more: '<input type="button" value="もっと読み込む" class="mw-ui-button" id="f-loadmore">',
                     create: '<input type="button" class="mw-ui-button mw-ui-progressive" value="スレッドを作成">',
                     create: '<input type="button" class="mw-ui-button mw-ui-progressive" value="スレッドを作成">',
                     createform: '<div id="f-form"><label>スレッド名: <input type="text" id="f-threadname" class="mw-ui-input" style="margin-bottom:.5em;"></label><textarea accesskey="," id="wpTextbox1" cols="80" rows="25" class="mw-editfont-monospace"></textarea><input type="button" value="スレッドを作成" id="f-create" class="mw-ui-button mw-ui-progressive" style="margin-top:.5em;"><input type="button" id="f-preview" value="プレビュー" class="mw-ui-button" style="margin: .5em 0 0 .5em;"><fieldset hidden><legend>プレビュー</legend><div id="f-preview-content"></div></fieldset></div>',
                     createform: `<div id="f-form"><label>スレッド名: <input type="text" id="f-threadname" class="mw-ui-input" style="margin-bottom:.5em;"></label>${toolbarHtml}<textarea accesskey="," id="wpTextbox1" cols="80" rows="25" class="mw-editfont-monospace"></textarea><input type="button" value="スレッドを作成" id="f-create" class="mw-ui-button mw-ui-progressive" style="margin-top:.5em;"><input type="button" id="f-preview" value="プレビュー" class="mw-ui-button" style="margin: .5em 0 0 .5em;"><fieldset hidden><legend>プレビュー</legend><div id="f-preview-content"></div></fieldset></div>`,
                     createthreadsummary: 'スレッドの作成',
                     createthreadsummary: 'スレッドの作成',
                     posterror: 'エラー: 投稿できませんでした',
                     posterror: 'エラー: 投稿できませんでした',
247行目: 259行目:
                         });
                         });
                     },
                     },
                    // ========== スレッド削除(管理者のみ) ==========
                    deleteThread: async () => {
                        const threadName = mw.config.get('wgPageName').replace(mw.forum.toppage + '/', '');
                        if (!confirm(`スレッド「${threadName}」を削除しますか?\nこの操作は取り消せません。`)) return;
                        fetch('/mediawiki/forum-proxy.php', {
                            method: 'POST',
                            headers: { 'Content-Type': 'application/json' },
                            body: JSON.stringify({
                                action: 'delete',
                                title:  mw.config.get('wgPageName'),
                                reason: msg.deletethreadsummary
                            })
                        }).then(r => r.json()).then(data => {
                            if (data.result === 'Success') {
                                location.href = mw.config.get('wgArticlePath').replace('$1', mw.forum.toppage);
                            } else {
                                mw.notify(msg.deleteerror);
                            }
                        }).catch(() => mw.notify(msg.deleteerror));
                    },
                    // =================================================
                    // ========== 書式ツールバーの初期化 ==========
                    initToolbar: () => {
                        const toolbar = document.querySelector('#f-toolbar');
                        if (!toolbar) return;
                        const ta = document.querySelector('#wpTextbox1');
                        // 選択範囲をマークアップで囲むヘルパー
                        const wrapText = (start, end) => {
                            const s = ta.selectionStart, e = ta.selectionEnd;
                            const selected = ta.value.substring(s, e);
                            ta.value = ta.value.substring(0, s) + start + selected + end + ta.value.substring(e);
                            ta.selectionStart = s + start.length;
                            ta.selectionEnd  = s + start.length + selected.length;
                            ta.focus();
                        };
                        // 太字・斜体ボタン
                        toolbar.querySelectorAll('.f-tb-btn').forEach(btn => {
                            btn.onclick = () => wrapText(btn.dataset.start, btn.dataset.end);
                        });
                        // 文字色ボタン
                        toolbar.querySelectorAll('.f-tb-color').forEach(btn => {
                            btn.onclick = () => wrapText(`<span style="color:${btn.dataset.color}">`, '</span>');
                        });
                    },
                    // =============================================
                     // ========== 名前設定UIの初期化 ==========
                     // ========== 名前設定UIの初期化 ==========
                     initAnonSettings: () => {
                     initAnonSettings: () => {
302行目: 364行目:
                         mc.innerHTML = msg.createform;
                         mc.innerHTML = msg.createform;
                         document.querySelector("#f-preview").onclick = func.preview;
                         document.querySelector("#f-preview").onclick = func.preview;
                        func.initToolbar();
                         mw.loader.using('ext.wikiEditor');
                         mw.loader.using('ext.wikiEditor');
                         document.querySelector('#f-create').onclick = function () {
                         document.querySelector('#f-create').onclick = function () {
367行目: 430行目:
                     // 名前設定UIを初期化(匿名ユーザーのみ)
                     // 名前設定UIを初期化(匿名ユーザーのみ)
                     func.initAnonSettings();
                     func.initAnonSettings();
                    // 書式ツールバーを初期化
                    func.initToolbar();
                    // 管理者にスレッド削除ボタンを表示
                    if (isAdmin) {
                        const delThreadBtn = document.createElement('input');
                        delThreadBtn.type = 'button';
                        delThreadBtn.value = 'スレッドを削除';
                        delThreadBtn.className = 'mw-ui-button mw-ui-destructive';
                        delThreadBtn.style.cssText = 'margin-left:.5em;';
                        delThreadBtn.onclick = func.deleteThread;
                        const ind = document.querySelector('.mw-indicators');
                        if (ind) ind.appendChild(delThreadBtn);
                    }


                     document.querySelector('#f-post').onclick = (async () => {
                     document.querySelector('#f-post').onclick = (async () => {