Mudanças entre as edições de "Widget:C.Background"

De Wiki Gla
Ir para navegação Ir para pesquisar
m
m
 
(2 revisões intermediárias pelo mesmo usuário não estão sendo mostradas)
Linha 3: Linha 3:
     =========================== -->
     =========================== -->
<script>
<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 () {
     /**
     /**
     * @typedef {Object} MediaWiki
     * Builds a MediaWiki file URL from a filename
     * @property {Object} util
     * @param {string} fileName - The filename (with or without "Arquivo:" prefix)
    * @property {Function} util.wikiScript
     * @returns {string} The full URL to the file
    * @property {Function} util.wikiUrlencode
    * @property {Object} config
     * @property {Function} config.get
     */
     */
     // @ts-ignore - MediaWiki global
     function buildBgURL(fileName) {
    var mw = window.mw || {};
      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, "/");
      }
    }


     (function () {
     /**
        /**
    * Sistema de cache persistente usando IndexedDB
        * Builds a MediaWiki file URL from a filename
    */
        * @param {string} fileName - The filename (with or without "Arquivo:" prefix)
    var BgCache = (function () {
        * @returns {string} The full URL to the file
      var DB_NAME = "character-bg-cache";
        */
      var DB_VERSION = 1;
        function buildBgURL(fileName) {
      var STORE_NAME = "backgrounds";
            if (!fileName) return '';
      var db = null;
            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');
      * Inicializa o banco de dados IndexedDB
            var path = 'Especial:FilePath/' + fileName.replace(/^Arquivo:|^File:/, '');
      */
            if (window.mw && mw.util && typeof mw.util.wikiUrlencode === 'function') {
      function initDB() {
                return base + '?title=' + mw.util.wikiUrlencode(path);
        return new Promise(function (resolve, reject) {
             } else {
          if (db) {
                return base + '?title=' + encodeURIComponent(path).replace(/%2F/g, '/');
            resolve(db);
            }
             return;
        }
          }


        /**
          if (!window.indexedDB) {
        * Sistema de cache persistente usando IndexedDB
             reject(new Error("IndexedDB não disponível"));
        */
             return;
        var BgCache = (function () {
          }
             var DB_NAME = 'character-bg-cache';
             var DB_VERSION = 1;
            var STORE_NAME = 'backgrounds';
            var db = null;


            /**
          var request = indexedDB.open(DB_NAME, DB_VERSION);
            * Inicializa o banco de dados IndexedDB
            */
            function initDB() {
                return new Promise(function (resolve, reject) {
                    if (db) {
                        resolve(db);
                        return;
                    }


                    if (!window.indexedDB) {
          request.onerror = function () {
                        reject(new Error('IndexedDB não disponível'));
            reject(request.error);
                        return;
          };
                    }


                    var request = indexedDB.open(DB_NAME, DB_VERSION);
          request.onsuccess = function () {
            db = request.result;
            resolve(db);
          };


                    request.onerror = function () {
          request.onupgradeneeded = function (event) {
                        reject(request.error);
            var database = event.target.result;
                    };
            if (!database.objectStoreNames.contains(STORE_NAME)) {
              database.createObjectStore(STORE_NAME);
            }
          };
        });
      }


                    request.onsuccess = function () {
      /**
                        db = request.result;
      * Obtém imagem do cache
                        resolve(db);
      * @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.onupgradeneeded = function (event) {
              request.onsuccess = function () {
                        var database = event.target.result;
                var entry = request.result;
                        if (!database.objectStoreNames.contains(STORE_NAME)) {
                if (entry && entry.blob instanceof Blob) {
                            database.createObjectStore(STORE_NAME);
                  resolve(entry);
                        }
                } else if (entry && entry instanceof Blob) {
                    };
                  resolve({ blob: entry, meta: {}, cachedAt: 0 });
                 });
                 } else {
            }
                  resolve(null);
                }
              };


            /**
              request.onerror = function () {
            * Obtém imagem do cache
                reject(request.error);
            * @param {string} url - URL da imagem
              };
            * @returns {Promise<string|null>} URL do blob ou null se não estiver em cache
            });
            */
          })
            function get(url) {
          .catch(function () {
                return initDB().then(function (database) {
            return Promise.resolve(null);
                    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;
      * Salva imagem no cache
                            if (blob && blob instanceof Blob) {
      * @param {string} url - URL da imagem
                                var blobUrl = URL.createObjectURL(blob);
      * @param {Blob} blob - Blob da imagem
                                resolve(blobUrl);
      */
                            } else {
      function set(url, blob, meta) {
                                resolve(null);
        initDB()
                            }
          .then(function (database) {
                        };
            var transaction = database.transaction([STORE_NAME], "readwrite");
            var store = transaction.objectStore(STORE_NAME);
            store.put(
              {
                blob: blob,
                meta: meta || {},
                cachedAt: Date.now(),
              },
              url
            );
          })
          .catch(function () {
            // Falha silenciosa - cache opcional
          });
      }


                        request.onerror = function () {
      function extractMeta(response) {
                            reject(request.error);
        return {
                        };
          etag:
                    });
            response.headers.get("ETag") ||
                }).catch(function () {
            response.headers.get("Etag") ||
                    return Promise.resolve(null);
            "",
                });
          lastModified: response.headers.get("Last-Modified") || "",
            }
        };
      }


            /**
      function metaMatches(a, b) {
            * Salva imagem no cache
        if (!a || !b) return false;
            * @param {string} url - URL da imagem
        if (a.etag && b.etag) return a.etag === b.etag;
            * @param {Blob} blob - Blob da imagem
        if (a.lastModified && b.lastModified)
            */
          return a.lastModified === b.lastModified;
            function set(url, blob) {
        return false;
                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
                });
            }


            /**
      function headMeta(url) {
            * Carrega imagem e aplica cache
        return fetch(url, { method: "HEAD", cache: "no-store" }).then(function (
            * @param {string} url - URL da imagem
          response
            * @returns {Promise<string>} URL do blob (do cache ou recém-carregada)
        ) {
            */
          if (!response.ok) {
            function loadImage(url) {
            throw new Error("HEAD falhou: " + response.status);
                return get(url).then(function (cachedUrl) {
          }
                    if (cachedUrl) {
          return extractMeta(response);
                        return Promise.resolve(cachedUrl);
        });
                    }
      }


                    // Carrega a imagem e salva no cache
      function fetchBlob(url) {
                    return fetch(url, { mode: 'cors' }).then(function (response) {
        return fetch(url, { mode: "cors", cache: "no-store" }).then(function (
                        if (!response.ok) {
          response
                            throw new Error('Falha ao carregar imagem: ' + response.status);
        ) {
                        }
          if (!response.ok) {
                        return response.blob();
            throw new Error(
                     }).then(function (blob) {
              "Falha ao carregar imagem: " + response.status
                        set(url, blob);
            );
                        return URL.createObjectURL(blob);
          }
                    });
          var meta = extractMeta(response);
                 }).catch(function () {
          return response.blob().then(function (blob) {
                    // Em caso de erro, retorna a URL original
            return { blob: blob, meta: meta };
                    return Promise.resolve(url);
          });
        });
      }
 
      /**
      * 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 (cachedEntry) {
            if (cachedEntry && cachedEntry.blob instanceof Blob) {
              return headMeta(url)
                .then(function (remoteMeta) {
                  var hasRemoteMeta =
                    remoteMeta &&
                     (remoteMeta.etag || remoteMeta.lastModified);
                  if (hasRemoteMeta && metaMatches(cachedEntry.meta, remoteMeta)) {
                    return URL.createObjectURL(cachedEntry.blob);
                  }
                  return fetchBlob(url).then(function (fresh) {
                    set(url, fresh.blob, fresh.meta);
                    return URL.createObjectURL(fresh.blob);
                  });
                 })
                .catch(function () {
                  return URL.createObjectURL(cachedEntry.blob);
                 });
                 });
             }
             }


             return {
            // Carrega a imagem e salva no cache
                loadImage: loadImage
             return fetchBlob(url).then(function (fresh) {
             };
              set(url, fresh.blob, fresh.meta);
        })();
              return URL.createObjectURL(fresh.blob);
             });
          })
          .catch(function () {
            // Em caso de erro, retorna a URL original
            return Promise.resolve(url);
          });
      }


         /**
      return {
        * Applies background image to an element (com cache persistente)
         loadImage: loadImage,
        * @param {HTMLElement} el - The element to apply background to
      };
        */
    })();
        function applyBg(el) {
 
            try {
    /**
                var url = el.getAttribute('data-bg-url');
    * Applies background image to an element (com cache persistente)
                if (!url) {
    * @param {HTMLElement} el - The element to apply background to
                    var f = el.getAttribute('data-bg-file');
    */
                    if (f) {
    function applyBg(el) {
                        url = buildBgURL(f);
      try {
                        el.setAttribute('data-bg-url', url);
        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) {
        if (url) {
                    // Tenta carregar do cache primeiro
          var setBgImage = function (primary, fallback) {
                    BgCache.loadImage(url).then(function (blobUrl) {
            if (!primary) return;
                        el.style.backgroundImage = 'url("' + blobUrl + '")';
            if (fallback) {
                        // Remove o atributo temporário se existir
              el.style.backgroundImage =
                        el.removeAttribute('data-bg-loading');
                 'url("' + primary + '"), url("' + fallback + '")';
                    }).catch(function () {
            } else {
                        // Fallback para URL original em caso de erro
              el.style.backgroundImage = 'url("' + primary + '")';
                        el.style.backgroundImage = 'url("' + url + '")';
            }
                    });
          };
          var currentBg = el.style.backgroundImage || "";
          // Tenta carregar do cache primeiro
          BgCache.loadImage(url)
            .then(function (blobUrl) {
              if (blobUrl && blobUrl !== url) {
                setBgImage(blobUrl, url);
              } else {
                setBgImage(url);
              }
              // Remove o atributo temporário se existir
              el.removeAttribute("data-bg-loading");
            })
            .catch(function () {
              // Fallback para URL original em caso de erro
              setBgImage(url);
              el.removeAttribute("data-bg-loading");
            });


                    // Aplica URL original imediatamente enquanto carrega do cache (progressive enhancement)
          // Aplica URL original imediatamente enquanto carrega do cache (progressive enhancement)
                    if (!el.hasAttribute('data-bg-loading')) {
          if (!el.hasAttribute("data-bg-loading")) {
                        el.setAttribute('data-bg-loading', '1');
            el.setAttribute("data-bg-loading", "1");
                        el.style.backgroundImage = 'url("' + url + '")';
            if (!currentBg || currentBg === "none") {
                    }
              setBgImage(url);
                }
            } catch (e) {
                /* no-op */
             }
             }
          }
         }
         }
      } catch (e) {
        /* no-op */
      }
    }


        // Aplicar backgrounds imediatamente
    // Aplicar backgrounds imediatamente
        document.querySelectorAll('[data-bg-url], [data-bg-file]').forEach(applyBg);
    document.querySelectorAll("[data-bg-url], [data-bg-file]").forEach(applyBg);


        // Apply to future elements (AJAX)
    // Apply to future elements (AJAX)
        new MutationObserver(function (mutations) {
    new MutationObserver(function (mutations) {
            mutations.forEach(function (m) {
      mutations.forEach(function (m) {
                if (m.type === 'childList') {
        if (m.type === "childList") {
                    m.addedNodes.forEach(function (n) {
          m.addedNodes.forEach(function (n) {
                        if (n.nodeType === 1) {
            if (n.nodeType === 1) {
                            if (n.hasAttribute && (n.hasAttribute('data-bg-file') || n.hasAttribute('data-bg-url'))) {
              if (
                                applyBg(n);
                n.hasAttribute &&
                            }
                (n.hasAttribute("data-bg-file") ||
                            if (n.querySelectorAll) {
                  n.hasAttribute("data-bg-url"))
                                n.querySelectorAll('[data-bg-file], [data-bg-url]').forEach(applyBg);
              ) {
                            }
                applyBg(n);
                        }
              }
                    });
              if (n.querySelectorAll) {
                } else if (m.type === 'attributes' && m.target) {
                n.querySelectorAll("[data-bg-file], [data-bg-url]").forEach(
                    applyBg(m.target);
                  applyBg
                }
                );
            });
              }
        }).observe(document.body, {
            }
            attributes: true,
          });
            attributeFilter: ['data-bg-file', 'data-bg-url'],
        } else if (m.type === "attributes" && m.target) {
            childList: true,
          applyBg(m.target);
            subtree: true,
        }
        });
      });
    })();
    }).observe(document.body, {
      attributes: true,
      attributeFilter: ["data-bg-file", "data-bg-url"],
      childList: true,
      subtree: true,
    });
  })();
</script>
</script>

Edição atual tal como às 05h20min de 24 de janeiro de 2026

<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 entry = request.result;
               if (entry && entry.blob instanceof Blob) {
                 resolve(entry);
               } else if (entry && entry instanceof Blob) {
                 resolve({ blob: entry, meta: {}, cachedAt: 0 });
               } 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, meta) {
       initDB()
         .then(function (database) {
           var transaction = database.transaction([STORE_NAME], "readwrite");
           var store = transaction.objectStore(STORE_NAME);
           store.put(
             {
               blob: blob,
               meta: meta || {},
               cachedAt: Date.now(),
             },
             url
           );
         })
         .catch(function () {
           // Falha silenciosa - cache opcional
         });
     }
     function extractMeta(response) {
       return {
         etag:
           response.headers.get("ETag") ||
           response.headers.get("Etag") ||
           "",
         lastModified: response.headers.get("Last-Modified") || "",
       };
     }
     function metaMatches(a, b) {
       if (!a || !b) return false;
       if (a.etag && b.etag) return a.etag === b.etag;
       if (a.lastModified && b.lastModified)
         return a.lastModified === b.lastModified;
       return false;
     }
     function headMeta(url) {
       return fetch(url, { method: "HEAD", cache: "no-store" }).then(function (
         response
       ) {
         if (!response.ok) {
           throw new Error("HEAD falhou: " + response.status);
         }
         return extractMeta(response);
       });
     }
     function fetchBlob(url) {
       return fetch(url, { mode: "cors", cache: "no-store" }).then(function (
         response
       ) {
         if (!response.ok) {
           throw new Error(
             "Falha ao carregar imagem: " + response.status
           );
         }
         var meta = extractMeta(response);
         return response.blob().then(function (blob) {
           return { blob: blob, meta: meta };
         });
       });
     }
     /**
      * 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 (cachedEntry) {
           if (cachedEntry && cachedEntry.blob instanceof Blob) {
             return headMeta(url)
               .then(function (remoteMeta) {
                 var hasRemoteMeta =
                   remoteMeta &&
                   (remoteMeta.etag || remoteMeta.lastModified);
                 if (hasRemoteMeta && metaMatches(cachedEntry.meta, remoteMeta)) {
                   return URL.createObjectURL(cachedEntry.blob);
                 }
                 return fetchBlob(url).then(function (fresh) {
                   set(url, fresh.blob, fresh.meta);
                   return URL.createObjectURL(fresh.blob);
                 });
               })
               .catch(function () {
                 return URL.createObjectURL(cachedEntry.blob);
               });
           }
           // Carrega a imagem e salva no cache
           return fetchBlob(url).then(function (fresh) {
             set(url, fresh.blob, fresh.meta);
             return URL.createObjectURL(fresh.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) {
         var setBgImage = function (primary, fallback) {
           if (!primary) return;
           if (fallback) {
             el.style.backgroundImage =
               'url("' + primary + '"), url("' + fallback + '")';
           } else {
             el.style.backgroundImage = 'url("' + primary + '")';
           }
         };
         var currentBg = el.style.backgroundImage || "";
         // Tenta carregar do cache primeiro
         BgCache.loadImage(url)
           .then(function (blobUrl) {
             if (blobUrl && blobUrl !== url) {
               setBgImage(blobUrl, url);
             } else {
               setBgImage(url);
             }
             // Remove o atributo temporário se existir
             el.removeAttribute("data-bg-loading");
           })
           .catch(function () {
             // Fallback para URL original em caso de erro
             setBgImage(url);
             el.removeAttribute("data-bg-loading");
           });
         // Aplica URL original imediatamente enquanto carrega do cache (progressive enhancement)
         if (!el.hasAttribute("data-bg-loading")) {
           el.setAttribute("data-bg-loading", "1");
           if (!currentBg || currentBg === "none") {
             setBgImage(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>