MediaWiki:Gadget-freezeAPNG.js: различия между версиями
Материал из Space Station 14 Вики
Pok (обсуждение | вклад) мНет описания правки Метка: ручная отмена |
Pok (обсуждение | вклад) Нет описания правки |
||
| Строка 1: | Строка 1: | ||
(function($, mw){ | (function($, mw){ | ||
function detectAndFreeze(img){ | function detectAndFreeze(img){ | ||
if (img.dataset.freezeProcessed) return; | |||
var xhr = new XMLHttpRequest(); | var xhr = new XMLHttpRequest(); | ||
xhr.open('GET', img.src, true); | xhr.open('GET', img.src, true); | ||
| Строка 14: | Строка 15: | ||
bytes[i+3] === 0x4C | bytes[i+3] === 0x4C | ||
){ | ){ | ||
freezeWithSwap(img); | |||
break; | break; | ||
} | } | ||
} | } | ||
}; | }; | ||
xhr.onerror = function(){ /* ignore */ }; | |||
xhr.send(); | xhr.send(); | ||
} | } | ||
function | function freezeWithSwap(img){ | ||
if (img.dataset.freezeProcessed) return; | |||
img.dataset.freezeProcessed = '1'; | |||
var origW = img.getAttribute('width'), | var origW = img.getAttribute('width'), | ||
origH = img.getAttribute('height'), | origH = img.getAttribute('height'), | ||
ow | originalDisplay = window.getComputedStyle(img).display || 'inline'; | ||
oh | |||
canvas = document.createElement('canvas'); | var animatedClone = img.cloneNode(true); | ||
canvas.width | animatedClone.className = (animatedClone.className ? animatedClone.className + ' ' : '') + 'freezeAPNG-animated'; | ||
animatedClone.style.display = 'none'; | |||
animatedClone.style.visibility = 'visible'; | |||
if (origW) animatedClone.setAttribute('width', origW); | |||
if (origH) animatedClone.setAttribute('height', origH); | |||
var ow = img.naturalWidth || img.width || 0, | |||
oh = img.naturalHeight || img.height || 0; | |||
if (!ow || !oh) { | |||
return; | |||
} | |||
var canvas = document.createElement('canvas'); | |||
canvas.width = ow; | |||
canvas.height = oh; | canvas.height = oh; | ||
canvas.getContext('2d').drawImage(img, 0, 0, ow, oh); | var ctx = canvas.getContext('2d'); | ||
try { | |||
ctx.drawImage(img, 0, 0, ow, oh); | |||
} catch (e) { | |||
return; | |||
} | |||
var frozenData; | |||
try { | |||
frozenData = canvas.toDataURL('image/png'); | |||
} catch (e) { | |||
return; | |||
} | |||
var parent = img.parentNode; | |||
if (!parent) return; | |||
if (img.nextSibling) parent.insertBefore(animatedClone, img.nextSibling); | |||
else parent.appendChild(animatedClone); | |||
try { | try { | ||
img.src = | img.src = frozenData; | ||
if (origW) img.setAttribute('width', origW); | if (origW) img.setAttribute('width', origW); | ||
if (origH) img.setAttribute('height', origH); | if (origH) img.setAttribute('height', origH); | ||
} catch(e){} | } catch (e){ /* ignore */ } | ||
img.style.display = originalDisplay; | |||
animatedClone.style.display = 'none'; | |||
var container = img.closest && img.closest('.freezeAPNG') ? img.closest('.freezeAPNG') : parent; | |||
var showAnimated = function(){ | |||
img.style.display = 'none'; | |||
animatedClone.style.display = originalDisplay; | |||
}; | |||
var showFrozen = function(){ | |||
animatedClone.style.display = 'none'; | |||
img.style.display = originalDisplay; | |||
}; | |||
container.addEventListener('mouseenter', showAnimated); | |||
container.addEventListener('mouseleave', showFrozen); | |||
container.addEventListener('focusin', showAnimated); | |||
container.addEventListener('focusout', showFrozen); | |||
var touchTimeout = null; | |||
container.addEventListener('touchstart', function(e){ | |||
showAnimated(); | |||
if (touchTimeout) clearTimeout(touchTimeout); | |||
touchTimeout = setTimeout(function(){ | |||
showFrozen(); | |||
}, 1200); | |||
}, {passive: true}); | |||
container.addEventListener('touchend', function(){ if (touchTimeout) { clearTimeout(touchTimeout); touchTimeout = null; showFrozen(); } }, {passive: true}); | |||
container.addEventListener('touchcancel', function(){ if (touchTimeout) { clearTimeout(touchTimeout); touchTimeout = null; showFrozen(); } }, {passive: true}); | |||
} | } | ||
$(function(){ | $(function(){ | ||
$('.freezeAPNG img[src$=".png"]').each(function(){ | $('.freezeAPNG img[src$=".png"]').each(function(){ | ||
if ( | var img = this; | ||
detectAndFreeze( | if (img.dataset.freezeProcessed) return; | ||
if (img.complete) { | |||
detectAndFreeze(img); | |||
} else { | } else { | ||
img.addEventListener('load', function(){ | |||
detectAndFreeze( | detectAndFreeze(img); | ||
}); | }); | ||
} | } | ||
Версия от 20:32, 17 марта 2026
(function($, mw){
function detectAndFreeze(img){
if (img.dataset.freezeProcessed) return;
var xhr = new XMLHttpRequest();
xhr.open('GET', img.src, true);
xhr.responseType = 'arraybuffer';
xhr.onload = function(){
if (xhr.status < 200 || xhr.status >= 300) return;
var bytes = new Uint8Array(xhr.response);
for (var i = 0; i < bytes.length - 4; i++){
if (
bytes[i] === 0x61 &&
bytes[i+1] === 0x63 &&
bytes[i+2] === 0x54 &&
bytes[i+3] === 0x4C
){
freezeWithSwap(img);
break;
}
}
};
xhr.onerror = function(){ /* ignore */ };
xhr.send();
}
function freezeWithSwap(img){
if (img.dataset.freezeProcessed) return;
img.dataset.freezeProcessed = '1';
var origW = img.getAttribute('width'),
origH = img.getAttribute('height'),
originalDisplay = window.getComputedStyle(img).display || 'inline';
var animatedClone = img.cloneNode(true);
animatedClone.className = (animatedClone.className ? animatedClone.className + ' ' : '') + 'freezeAPNG-animated';
animatedClone.style.display = 'none';
animatedClone.style.visibility = 'visible';
if (origW) animatedClone.setAttribute('width', origW);
if (origH) animatedClone.setAttribute('height', origH);
var ow = img.naturalWidth || img.width || 0,
oh = img.naturalHeight || img.height || 0;
if (!ow || !oh) {
return;
}
var canvas = document.createElement('canvas');
canvas.width = ow;
canvas.height = oh;
var ctx = canvas.getContext('2d');
try {
ctx.drawImage(img, 0, 0, ow, oh);
} catch (e) {
return;
}
var frozenData;
try {
frozenData = canvas.toDataURL('image/png');
} catch (e) {
return;
}
var parent = img.parentNode;
if (!parent) return;
if (img.nextSibling) parent.insertBefore(animatedClone, img.nextSibling);
else parent.appendChild(animatedClone);
try {
img.src = frozenData;
if (origW) img.setAttribute('width', origW);
if (origH) img.setAttribute('height', origH);
} catch (e){ /* ignore */ }
img.style.display = originalDisplay;
animatedClone.style.display = 'none';
var container = img.closest && img.closest('.freezeAPNG') ? img.closest('.freezeAPNG') : parent;
var showAnimated = function(){
img.style.display = 'none';
animatedClone.style.display = originalDisplay;
};
var showFrozen = function(){
animatedClone.style.display = 'none';
img.style.display = originalDisplay;
};
container.addEventListener('mouseenter', showAnimated);
container.addEventListener('mouseleave', showFrozen);
container.addEventListener('focusin', showAnimated);
container.addEventListener('focusout', showFrozen);
var touchTimeout = null;
container.addEventListener('touchstart', function(e){
showAnimated();
if (touchTimeout) clearTimeout(touchTimeout);
touchTimeout = setTimeout(function(){
showFrozen();
}, 1200);
}, {passive: true});
container.addEventListener('touchend', function(){ if (touchTimeout) { clearTimeout(touchTimeout); touchTimeout = null; showFrozen(); } }, {passive: true});
container.addEventListener('touchcancel', function(){ if (touchTimeout) { clearTimeout(touchTimeout); touchTimeout = null; showFrozen(); } }, {passive: true});
}
$(function(){
$('.freezeAPNG img[src$=".png"]').each(function(){
var img = this;
if (img.dataset.freezeProcessed) return;
if (img.complete) {
detectAndFreeze(img);
} else {
img.addEventListener('load', function(){
detectAndFreeze(img);
});
}
});
});
})(jQuery, mediaWiki);