Jump to content

User:PerryPerson/WikiFonts.js

From Wikipedia, the free encyclopedia
Note: After saving, you have to bypass your browser's cache to see the changes. Google Chrome, Firefox, Microsoft Edge and Safari: Hold down the ⇧ Shift key and click the Reload toolbar button. For details and instructions about other browsers, see Wikipedia:Bypass your cache.
(function() {
  if (typeof mw === 'undefined' || !mw.util) {
    console.warn('WikiFonts: MediaWiki mw.util not found.');
    return;
  }

  function applyCssImportant(prop, val) {
    document.body.style.setProperty(prop, val, 'important');
  }

  function applyFontFace(fontName, fontDataUrl) {
    let styleTag = document.getElementById('customFontFace');
    if (!styleTag) {
      styleTag = document.createElement('style');
      styleTag.id = 'customFontFace';
      document.head.appendChild(styleTag);
    }
    styleTag.textContent = `
      @font-face {
        font-family: '${fontName}';
        src: url('${fontDataUrl}');
      }
    `;
  }

  function removeFontFace() {
    const tag = document.getElementById('customFontFace');
    if (tag) tag.remove();
  }

  function loadAndApplySettings() {
    const saved = JSON.parse(localStorage.getItem('wikiFontSettings') || '{}');
    if (!saved) return;

    if (saved.fontName && saved.fontDataUrl) {
      applyFontFace(saved.fontName, saved.fontDataUrl);
      applyCssImportant('font-family', saved.fontName);
    } else {
      removeFontFace();
    }

    if (saved.fontCssUrl) {
      let linkTag = document.getElementById('externalFontCss');
      if (!linkTag) {
        linkTag = document.createElement('link');
        linkTag.id = 'externalFontCss';
        linkTag.rel = 'stylesheet';
        document.head.appendChild(linkTag);
      }
      linkTag.href = saved.fontCssUrl;
      if (saved.fontFamily) {
        applyCssImportant('font-family', saved.fontFamily);
      }
    } else {
      const linkTag = document.getElementById('externalFontCss');
      if (linkTag) linkTag.remove();

      if (saved.fontFamily && !saved.fontName) {
        applyCssImportant('font-family', saved.fontFamily);
      }
    }

    applyCssImportant('font-weight', saved.bold ? 'bold' : 'normal');
    applyCssImportant('font-style', saved.italic ? 'italic' : 'normal');
  }

  loadAndApplySettings();

  function openWikiFontsModal() {
    if ($('#wikiFontsModal').length === 0) {
      $('body').append(`
        <div id="wikiFontsModal" style="display:none;position:fixed;top:30px;left:50%;transform:translateX(-50%);
          z-index:9999;background:#001f3f;color:white;border:2px solid #001f3f;padding:15px 15px 60px;width:90%;
          max-width:700px;border-radius:6px;font-family:sans-serif;max-height:85vh;overflow-y:auto;">
          <h3>WikiFonts</h3>
          <div style="background:#e1eaff;color:#001f3f;padding:10px;border-radius:6px;">
            <label>Font Family:<br><input type="text" id="fontFamilyInput" style="width:100%;padding:4px;margin-bottom:8px;"></label><br>
            <label>Font CSS URL:<br><input type="text" id="fontCssUrlInput" style="width:100%;padding:4px;margin-bottom:4px;">
              <button id="loadFontCssBtn" style="padding:4px 8px;background:#0074D9;color:white;border:none;border-radius:4px;margin-left:5px;cursor:pointer;">Load</button>
            </label><br>
            <label>Upload Font:<br><input type="file" id="fontFileInput" accept=".ttf,.woff,.woff2" style="margin-bottom:8px;cursor:pointer;"></label><br>
            <label>Font Name:<br><input type="text" id="fontNameInput" style="width:100%;padding:4px;"></label><br>
            <label><input type="checkbox" id="fontBold"> Bold</label>
            <label style="margin-left:10px;"><input type="checkbox" id="fontItalic"> Italic</label><br>
            <button id="resetFontBtn" style="background:#ff4136;color:white;border:none;padding:6px 12px;border-radius:4px;margin-top:10px;cursor:pointer;">Reset Font</button>
          </div>
          <br>
          <button id="saveWikiFonts" style="background:#0074D9;color:white;border:none;padding:6px 12px;margin-top:10px;cursor:pointer;">Save</button>
          <button id="closeWikiFonts" style="padding:6px 12px;margin-left:5px;cursor:pointer;">Close</button>
        </div>
      `);

      const saved = JSON.parse(localStorage.getItem('wikiFontSettings') || '{}');
      $('#fontFamilyInput').val(saved.fontFamily || '');
      $('#fontCssUrlInput').val(saved.fontCssUrl || '');
      $('#fontNameInput').val(saved.fontName || '');
      $('#fontBold').prop('checked', saved.bold || false);
      $('#fontItalic').prop('checked', saved.italic || false);

      let uploadedFontDataURL = saved.fontDataUrl || null;

      $('#loadFontCssBtn').on('click', () => {
        const url = $('#fontCssUrlInput').val().trim();
        if (url) {
          $('#externalFontCss').remove();
          $('head').append(`<link id="externalFontCss" rel="stylesheet" href="${url}">`);
          alert('Font CSS loaded.');
        }
      });

      $('#fontFileInput').on('change', function() {
        const file = this.files[0];
        if (file) {
          const reader = new FileReader();
          reader.onload = e => {
            uploadedFontDataURL = e.target.result;
            alert('Font loaded! Now enter a font name and save.');
          };
          reader.readAsDataURL(file);
        }
      });

      $('#resetFontBtn').on('click', () => {
        $('#fontFamilyInput,#fontCssUrlInput,#fontNameInput').val('');
        $('#fontBold,#fontItalic').prop('checked', false);
        uploadedFontDataURL = null;
        $('#externalFontCss,#customFontFace').remove();
        $('body').css({'font-family': '', 'font-weight': '', 'font-style': ''});
        localStorage.removeItem('wikiFontSettings');
      });

      $('#saveWikiFonts').on('click', () => {
        const fontFamily = $('#fontFamilyInput').val().trim();
        const fontCssUrl = $('#fontCssUrlInput').val().trim();
        const fontName = $('#fontNameInput').val().trim();
        const bold = $('#fontBold').is(':checked');
        const italic = $('#fontItalic').is(':checked');

        if (fontCssUrl) {
          $('#externalFontCss').remove();
          $('head').append(`<link id="externalFontCss" rel="stylesheet" href="${fontCssUrl}">`);
        }

        if (uploadedFontDataURL && fontName) {
          applyFontFace(fontName, uploadedFontDataURL);
          applyCssImportant('font-family', fontName);
        } else if (fontFamily) {
          removeFontFace();
          applyCssImportant('font-family', fontFamily);
        } else {
          removeFontFace();
          $('body').css('font-family', '');
        }

        applyCssImportant('font-weight', bold ? 'bold' : 'normal');
        applyCssImportant('font-style', italic ? 'italic' : 'normal');

        const settings = {
          fontFamily,
          fontCssUrl,
          fontName,
          fontDataUrl: uploadedFontDataURL,
          bold,
          italic
        };
        localStorage.setItem('wikiFontSettings', JSON.stringify(settings));

        $('#wikiFontsModal').hide();
      });

      $('#closeWikiFonts').on('click', () => $('#wikiFontsModal').hide());
    } else {
      $('#wikiFontsModal').show();
    }
  }

  mw.util.addPortletLink('p-personal', 'javascript:void(0);', 'WikiFonts', 'pt-wikifonts', 'Open WikiFonts font settings');

  // Delegated event handler to fix double-click bug and ensure click always works
  $(document).on('click', '#pt-wikifonts a', function(e) {
    e.preventDefault();
    openWikiFontsModal();
  });

})();