我正在开发一个用图片做各种事情的用户脚本。
问题是,有时图像会在初始加载后添加到页面中,并且这些图像不会被我的用户脚本处理。
我需要javascript / jQuery中的一些代码,每次将新图像加载到浏览器中时都会自动运行一个函数。
这就是我的尝试:
$('img').on('load', function() {
handleImgTag();
});
这不起作用。当一个新的图像添加到页面时(我正在使用chat.stackoverflow.com作为测试,并发送一条新消息,意味着我的个人资料图片再次添加到页面中,而我的代码未处理)图像不是处理后没有任何反应。
我试过四处寻找,但我似乎无法找到办法,也许是因为搜索条件不好?
是否有可以在 Tampermonkey用户脚本中使用的事件或其他内容,当用户所在页面上添加新图片时,该用户将运行该功能?
编辑:
我不同意上面提到的重复项,因为这是关于图像的,并且在Tampermonkey用户内部使用。此外,重复项还有5到8年的历史,可能无法反映最佳实践或当前技术。
答案 0 :(得分:1)
$('img').on('load',...
无效,因为它会将匿名事件处理程序发送到所有现有图像上。他们从未接受过未来的AJAX /动态插入图像。
的正确格式为:$('body').on ('load', 'img', handleImgTag);
, EXCEPT load
events do not bubble。
因此,您必须使用以下任一方法:来自链接问题的技巧(主要是MutationObserver
),或waitForKeyElements()
之类的内容。
并且,您必须动态附加加载事件(对于缓慢加载图像)。
以下完整工作脚本说明了该过程。请注意waitForKeyElements
会为每个<img>
触发一次,无论是静态加载还是动态加载。 :
// ==UserScript==
// @name _Process select images on or after load
// @match *://chat.stackoverflow.com/rooms/*
// @match *://chat.stackexchange.com/rooms/*
// @match *://chat.meta.stackexchange.com/rooms/*
// @require https://ajax.googleapis.com/ajax/libs/jquery/2.1.0/jquery.min.js
// @require https://gist.github.com/raw/2625891/waitForKeyElements.js
// @grant GM_addStyle
// @grant GM.getValue
// ==/UserScript==
//- The @grant directives are needed to restore the proper sandbox.
waitForKeyElements ("#chat img", loadHandling);
function loadHandling (jNode) {
if (jNode[0].complete) {
handleImgTag (jNode);
}
else {
jNode.on ('load', handleImgTag);
}
}
function handleImgTag (jNodeOrEvent) {
var newImg; // will be jQuery node
if (jNodeOrEvent instanceof jQuery) {
newImg = jNodeOrEvent;
}
else {
newImg = $(jNodeOrEvent.target);
}
console.log ("Found new image with width ", newImg.width () );
}
注意:建议调整jQuery选择器,传递给waitForKeyElements,以尽可能合理地缩小目标图像。
答案 1 :(得分:-1)
在浏览器范围内,可以使用globalEventHandler或eventListeners。
但是因为用户脚本对window
和document
有一些不同的范围,所以它不能正常工作。使用web extensions(下一代usercipts ..),这个范围问题是相同的,但至少它迫使我们更多地关注DOM。
以下是针对用户脚本的一些解决方法,并进行了自己的实验。 通常我的实验会导致“程序员”的沮丧,所以不用担心,玩得开心!
首先代替加载事件,在用户脚本中,加载脚本有延迟。它很脏但很有帮助,至少对于调试而言。
setTimeout(function(){ }, 3000)
要将事件处理程序加载到主文档中,我们必须创建一个元素并将其附加到主DOM。
在大多数情况下,问题只是因为浏览器加载本地资源的速度要快得多,我们必须指定脚本在目标页面上的位置,或者它可能位于DOM的最顶层。 (意思是没有事件处理程序,我们不能用他们的名字调用id,我们需要使用getElementById等等)
s = document.createElement("script")
s.innerText = "" // The events scripts
document.body.appendChild(s)
这里的好处是,脚本可以是外部的。通过加载外部脚本,浏览器会将其附加到DOM ,实际上如果DOM加载良好。在大多数情况下,东西开始只用这个动作。
另一种方法是直接在目标DOM的每个元素上设置onchange
属性。
如果元素已存在,则此选项有效。 (如果您通过更改src加载图像)。您也可以根据需要设置许多(隐藏)元素并设置其属性。这有点多余,但避免任何事件侦听器。这是扁平的方法。它也可以在服务器端完成。
要在不知道其ID的情况下为所有图片代码设置onchange,我们可以使用querySelectorAll
,这种情况非常有用,因为我们可以使用forEach
。 (与getElementsBytagName
不同)
document.querySelectorAll("img").forEach(function(element){
element.setAttribute("onchange","handleImgTag()")
})
现在一起:
setTimeout(function(){
// the querySelectorAll function encoded in base64
var all = "ZG9jdW1lbnQucXVlcnlTZWxlY3RvckFsbCgnaW1nJykuZm9yRWFjaChmdW5jdGlvbihlbGVtZW50KXsNCiAgZWxlbWVudC5zZXRBdHRyaWJ1dGUoJ29ubG9hZCcsJ2FsZXJ0KCknKQ0KfSk="
s = document.createElement("script")
// The events scripts, base64 decoded
s.innerText = atob(all) + ""
document.body.appendChild(s) // End of DOM, at trigger.
}, 1000) // Onloads sets after 1s.
<img src="http://icons.iconarchive.com/icons/martin-berube/flat-animal/64/pony-icon.png"></img>
<img src="" id="more"></img>
<button onclick="more.src='http://icons.iconarchive.com/icons/martin-berube/flat-animal/64/crab-icon.png'">LOAD MORE</button>
范围界定是良好用户脚本的关键。
尝试将所有脚本放在DOM端。祝你好运!