|
|
| (同じ利用者による、間の1版が非表示) |
| 1行目: |
1行目: |
| /** | | /* JSなし */ |
| * トラwiki (tora22.com) - Custom JavaScript
| |
| */
| |
| (function() {
| |
| 'use strict';
| |
| | |
| function initCopyIp() {
| |
| var copyBtn = document.getElementById('tw-copy-ip-btn');
| |
| if (!copyBtn) return;
| |
| | |
| copyBtn.addEventListener('click', function(e) {
| |
| e.preventDefault();
| |
| var ip = 'tora22.com';
| |
| if (navigator.clipboard && navigator.clipboard.writeText) {
| |
| navigator.clipboard.writeText(ip).then(function() {
| |
| var origText = copyBtn.innerHTML;
| |
| copyBtn.innerHTML = '✅ コピー完了!';
| |
| copyBtn.style.backgroundColor = '#10b981';
| |
| setTimeout(function() {
| |
| copyBtn.innerHTML = origText;
| |
| copyBtn.style.backgroundColor = '';
| |
| }, 2000);
| |
| });
| |
| } else {
| |
| var input = document.createElement('input');
| |
| input.value = ip;
| |
| document.body.appendChild(input);
| |
| input.select();
| |
| document.execCommand('copy');
| |
| document.body.removeChild(input);
| |
| alert('サーバーアドレス (tora22.com) をコピーしました!');
| |
| }
| |
| });
| |
| }
| |
| | |
| function loadRecentUpdates() {
| |
| var container = document.getElementById('tw-live-recent-updates');
| |
| if (!container) return;
| |
| | |
| fetch('/api.php?action=query&list=recentchanges&rcnamespace=0&rclimit=6&rcprop=title|timestamp|user|comment&format=json')
| |
| .then(function(res) { return res.json(); })
| |
| .then(function(data) {
| |
| if (!data || !data.query || !data.query.recentchanges) return;
| |
| var rcs = data.query.recentchanges;
| |
| if (rcs.length === 0) return;
| |
| | |
| var html = '<ul class="tw-updates-list">';
| |
| for (var i = 0; i < rcs.length; i++) {
| |
| var item = rcs[i];
| |
| var titleEnc = encodeURIComponent(item.title);
| |
| var dateObj = new Date(item.timestamp);
| |
| var timeStr = formatRelativeTime(dateObj);
| |
| | |
| html += '<li class="tw-update-item">';
| |
| html += ' <div class="tw-update-main">';
| |
| html += ' <div class="tw-update-title"><a href="/index.php/' + titleEnc + '">' + escapeHtml(item.title) + '</a></div>';
| |
| html += ' <div class="tw-update-meta">';
| |
| html += ' <span class="tw-update-user">👤 ' + escapeHtml(item.user) + '</span>';
| |
| if (item.comment) {
| |
| html += ' <span class="tw-update-comment" style="max-width:180px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;">' + escapeHtml(item.comment) + '</span>';
| |
| }
| |
| html += ' </div>';
| |
| html += ' </div>';
| |
| html += ' <div class="tw-update-time">' + timeStr + '</div>';
| |
| html += '</li>';
| |
| }
| |
| html += '</ul>';
| |
| container.innerHTML = html;
| |
| })
| |
| .catch(function(err) {
| |
| console.warn('Recent updates live fetch failed:', err);
| |
| });
| |
| }
| |
| | |
| function formatRelativeTime(date) {
| |
| var now = new Date();
| |
| var diffMs = now - date;
| |
| var diffSec = Math.floor(diffMs / 1000);
| |
| var diffMin = Math.floor(diffSec / 60);
| |
| var diffHr = Math.floor(diffMin / 60);
| |
| var diffDay = Math.floor(diffHr / 24);
| |
| | |
| if (diffMin < 1) return 'たった今';
| |
| if (diffMin < 60) return diffMin + '分前';
| |
| if (diffHr < 24) return diffHr + '時間前';
| |
| if (diffDay < 7) return diffDay + '日前';
| |
| return (date.getMonth() + 1) + '月' + date.getDate() + '日';
| |
| }
| |
| | |
| function escapeHtml(str) {
| |
| if (!str) return '';
| |
| return str.replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>').replace(/"/g, '"');
| |
| }
| |
| | |
| function addSidebarCreateButton() {
| |
| var navPortlet = document.querySelector('#p-ナビゲーション .mw-portlet-body');
| |
| if (navPortlet && !document.getElementById('n-create-custom-btn')) {
| |
| var btn = document.createElement('a');
| |
| btn.id = 'n-create-custom-btn';
| |
| btn.href = '#tw-article-creator';
| |
| btn.className = 'tw-sidebar-create-btn';
| |
| btn.innerHTML = '✏️ 新規記事を作成';
| |
| btn.addEventListener('click', function(e) {
| |
| var createInput = document.querySelector('.createboxInput');
| |
| if (createInput) {
| |
| createInput.focus();
| |
| createInput.scrollIntoView({ behavior: 'smooth', block: 'center' });
| |
| } else {
| |
| window.location.href = '/index.php/メインページ#tw-article-creator';
| |
| }
| |
| });
| |
| navPortlet.insertBefore(btn, navPortlet.firstChild);
| |
| }
| |
| }
| |
| | |
| if (document.readyState === 'loading') {
| |
| document.addEventListener('DOMContentLoaded', function() {
| |
| initCopyIp();
| |
| loadRecentUpdates();
| |
| addSidebarCreateButton();
| |
| });
| |
| } else {
| |
| initCopyIp();
| |
| loadRecentUpdates();
| |
| addSidebarCreateButton();
| |
| }
| |
| })();
| |