Widget:C.Background

De Wiki Gla
Revisão de 14h17min de 22 de janeiro de 2026 por Gurren1 (discussão | contribs)
Ir para navegação Ir para pesquisar

<script>

 /**
  * @typedef {Object} MediaWiki
  * @property {Object} util
  * @property {Function} util.wikiScript
  * @property {Function} util.wikiUrlencode
  * @property {Object} config
  * @property {Function} config.get
  */
 // @ts-ignore - MediaWiki global
 var mw = window.mw || {};
 (function () {
   /**
    * Builds a MediaWiki file URL from a filename
    * @param {string} fileName - The filename (with or without "Arquivo:" prefix)
    * @returns {string} The full URL to the file
    */
   function buildBgURL(fileName) {
     if (!fileName) return "";
     var base =
       window.mw && mw.util && typeof mw.util.wikiScript === "function"
         ? mw.util.wikiScript()
         : window.mw && mw.config
           ? mw.config.get("wgScript") || "/index.php"
           : "/index.php";
     var path =
       "Especial:FilePath/" + fileName.replace(/^Arquivo:|^File:/, "");
     if (window.mw && mw.util && typeof mw.util.wikiUrlencode === "function") {
       return base + "?title=" + mw.util.wikiUrlencode(path);
     } else {
       return base + "?title=" + encodeURIComponent(path).replace(/%2F/g, "/");
     }
   }
   /**
    * Sistema de cache persistente usando IndexedDB
    */
   var BgCache = (function () {
     var DB_NAME = "character-bg-cache";
     var DB_VERSION = 1;
     var STORE_NAME = "backgrounds";
     var db = null;
     /**
      * Inicializa o banco de dados IndexedDB
      */
     function initDB() {
       return new Promise(function (resolve, reject) {
         if (db) {
           resolve(db);
           return;
         }
         if (!window.indexedDB) {
           reject(new Error("IndexedDB não disponível"));
           return;
         }
         var request = indexedDB.open(DB_NAME, DB_VERSION);
         request.onerror = function () {
           reject(request.error);
         };
         request.onsuccess = function () {
           db = request.result;
           resolve(db);
         };
         request.onupgradeneeded = function (event) {
           var database = event.target.result;
           if (!database.objectStoreNames.contains(STORE_NAME)) {
             database.createObjectStore(STORE_NAME);
           }
         };
       });
     }
     /**
      * Obtém imagem do cache
      * @param {string} url - URL da imagem
      * @returns {Promise<string|null>} URL do blob ou null se não estiver em cache
      */
     function get(url) {
       return initDB()
         .then(function (database) {
           return new Promise(function (resolve, reject) {
             var transaction = database.transaction([STORE_NAME], "readonly");
             var store = transaction.objectStore(STORE_NAME);
             var request = store.get(url);
             request.onsuccess = function () {
               var blob = request.result;
               if (blob && blob instanceof Blob) {
                 var blobUrl = URL.createObjectURL(blob);
                 resolve(blobUrl);
               } else {
                 resolve(null);
               }
             };
             request.onerror = function () {
               reject(request.error);
             };
           });
         })
         .catch(function () {
           return Promise.resolve(null);
         });
     }
     /**
      * Salva imagem no cache
      * @param {string} url - URL da imagem
      * @param {Blob} blob - Blob da imagem
      */
     function set(url, blob) {
       initDB()
         .then(function (database) {
           var transaction = database.transaction([STORE_NAME], "readwrite");
           var store = transaction.objectStore(STORE_NAME);
           store.put(blob, url);
         })
         .catch(function () {
           // Falha silenciosa - cache opcional
         });
     }
     /**
      * Carrega imagem e aplica cache
      * @param {string} url - URL da imagem
      * @returns {Promise<string>} URL do blob (do cache ou recém-carregada)
      */
     function loadImage(url) {
       return get(url)
         .then(function (cachedUrl) {
           if (cachedUrl) {
             return Promise.resolve(cachedUrl);
           }
           // Carrega a imagem e salva no cache
           return fetch(url, { mode: "cors" })
             .then(function (response) {
               if (!response.ok) {
                 throw new Error(
                   "Falha ao carregar imagem: " + response.status
                 );
               }
               return response.blob();
             })
             .then(function (blob) {
               set(url, blob);
               return URL.createObjectURL(blob);
             });
         })
         .catch(function () {
           // Em caso de erro, retorna a URL original
           return Promise.resolve(url);
         });
     }
     return {
       loadImage: loadImage,
     };
   })();
   /**
    * Applies background image to an element (com cache persistente)
    * @param {HTMLElement} el - The element to apply background to
    */
   function applyBg(el) {
     try {
       var url = el.getAttribute("data-bg-url");
       if (!url) {
         var f = el.getAttribute("data-bg-file");
         if (f) {
           url = buildBgURL(f);
           el.setAttribute("data-bg-url", url);
         }
       }
       if (url) {
         // Tenta carregar do cache primeiro
         BgCache.loadImage(url)
           .then(function (blobUrl) {
             el.style.backgroundImage = 'url("' + blobUrl + '")';
             // Remove o atributo temporário se existir
             el.removeAttribute("data-bg-loading");
           })
           .catch(function () {
             // Fallback para URL original em caso de erro
             el.style.backgroundImage = 'url("' + url + '")';
           });
         // Aplica URL original imediatamente enquanto carrega do cache (progressive enhancement)
         if (!el.hasAttribute("data-bg-loading")) {
           el.setAttribute("data-bg-loading", "1");
           el.style.backgroundImage = 'url("' + url + '")';
         }
       }
     } catch (e) {
       /* no-op */
     }
   }
   // Aplicar backgrounds imediatamente
   document.querySelectorAll("[data-bg-url], [data-bg-file]").forEach(applyBg);
   // Apply to future elements (AJAX)
   new MutationObserver(function (mutations) {
     mutations.forEach(function (m) {
       if (m.type === "childList") {
         m.addedNodes.forEach(function (n) {
           if (n.nodeType === 1) {
             if (
               n.hasAttribute &&
               (n.hasAttribute("data-bg-file") ||
                 n.hasAttribute("data-bg-url"))
             ) {
               applyBg(n);
             }
             if (n.querySelectorAll) {
               n.querySelectorAll("[data-bg-file], [data-bg-url]").forEach(
                 applyBg
               );
             }
           }
         });
       } else if (m.type === "attributes" && m.target) {
         applyBg(m.target);
       }
     });
   }).observe(document.body, {
     attributes: true,
     attributeFilter: ["data-bg-file", "data-bg-url"],
     childList: true,
     subtree: true,
   });
 })();

</script>