我正在尝试编写一个简单的javascript来为Google的搜索工具添加更多选项(按“更多搜索工具”时显示的选项。但是,当我尝试将新元素附加到现有元素时,我收到错误。例如:
var yr = document.getElementById('qdr_y');
yr.parent.insertBefore(k,yr);
第二行抛出异常,因为yr
为空。通过检查搜索结果页面的直接源代码,我发现基本结果页面仅包含“所有结果”,“更多搜索工具”和隐藏的“更少搜索工具”。所有其他选项都以其他方式注入。
如何访问这些其他元素,以便将新元素添加到正确的位置?
答案 0 :(得分:1)
你有它:
// ==UserScript==
// @name TESTE
// @namespace TESTE
// @description TESTE
// @include http*://*.google.*
// ==/UserScript==
var k = document.createElement('div');
k.innerHTML = "<center><b> bla bla </b></center>"
var yr = document.getElementById('gbmm');
yr.insertBefore(k,yr.firstChild);
(这只是一个示例。您不应再使用<center>
和<b>
标记。
除非你的意思是这样的
然后代码看起来像这样
// ==UserScript==
// @name TESTE
// @namespace TESTE
// @description TESTE
// @include http*://*.google.*
// ==/UserScript==
var k = document.createElement('li');
k.id = 'myoption'
k.className = 'tbou'
k.innerHTML = "<a href='http://userscripts.org/users/rasg' class='q qs'> Here is my option </a>"
var yr = document.getElementById('clir_1');
yr.parentNode.appendChild(k);
另外,请考虑将JQuery添加到GM脚本中。
// @require http://code.jquery.com/jquery.min.js
编码要容易得多。
*编辑*
根据您的评论
我希望将节点插入“所有搜索工具”中 第二个解决方案。但是,你发布的内容正是如此 我已经在做了,除了使用qdr_y而不是clir_1!
以下(非常简单)代码是解决方案
// ==UserScript==
// @name TESTE 3
// @namespace TESTE 3
// @description TESTE 3
// @require http://code.jquery.com/jquery.min.js
// @include http*://www.google.com/*
// ==/UserScript==
$(window).load(function(){
$('.tbpc').click()
$('.tbt').on('DOMNodeInserted', function() {
if ($('#my_li').length) { $('#my_li').show() }
else { $('#whv_').parent().append("<li id='my_li' class='tbou' style=''><a class='q qs' href='http://userscipts.org'>Now i am inside</a>") }
})
$('.tbpo').on('click', function() { $('#my_li').hide() })
});
它并不像我想的那样漂亮,但谷歌让我们做坏事:)
答案 1 :(得分:0)
请注意,代码段中的parent
应为parentNode
。
无论如何,通常,对于动态元素,您需要检查并等待目标元素。如果需要点击某些内容,您的脚本必须单击它。 (尝试使用Google网站上的JS功能页面通常效果不佳.Google页面对于脚本来说总是非常“有趣”。;))
您需要自由使用轮询来弥补AJAX延迟。 (挂钩到AJAX事件或使用突变事件都有很高的成功率。轮询效果很好。)
最后,因为它是Google,所以仅仅触发一次民意调查是不够的,因为这些搜索选项会不断被覆盖。
以下是适用于美国版Google搜索结果的示例脚本(需要jQuery):
// ==UserScript==
// @name _Google Search options add
// @include http://www.google.com/*
// @require http://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js
// ==/UserScript==
if (window.top != window.self) //-- Don't run on frames or iframes.
return;
/*-- This script:
1) Waits for the "More search tools" control.
2) Clicks that control.
3) Waits for the target element
4) Adds our element before that one.
*/
waitForKeyElements ("#tbpi", clickMoreSearchToolsLink);
function clickMoreSearchToolsLink (jNode) {
var clickEvent = document.createEvent ('MouseEvents');
clickEvent.initEvent ('click', true, true);
jNode[0].dispatchEvent (clickEvent);
waitForKeyElements ("#qdr_y", addOurExtraNodes);
}
function addOurExtraNodes (jNode) {
jNode.before ("<li>Look at me, Ma!</li>");
}
/*--- waitForKeyElements(): A handy, utility function that
does what it says.
*/
function waitForKeyElements (
selectorTxt, /* Required: The jQuery selector string that
specifies the desired element(s).
*/
actionFunction, /* Required: The code to run when elements are
found. It is passed a jNode to the matched
element.
*/
bWaitOnce, /* Optional: If false, will continue to scan for
new elements even after the first match is
found.
*/
iframeSelector /* Optional: If set, identifies the iframe to
search.
*/
) {
var targetNodes, btargetsFound;
if (typeof iframeSelector == "undefined")
targetNodes = $(selectorTxt);
else
targetNodes = $(iframeSelector).contents ()
.find (selectorTxt);
if (targetNodes && targetNodes.length > 0) {
/*--- Found target node(s). Go through each and act if they
are new.
*/
targetNodes.each ( function () {
var jThis = $(this);
var alreadyFound = jThis.data ('alreadyFound') || false;
if (!alreadyFound) {
//--- Call the payload function.
actionFunction (jThis);
jThis.data ('alreadyFound', true);
}
} );
btargetsFound = true;
}
else {
btargetsFound = false;
}
//--- Get the timer-control variable for this selector.
var controlObj = waitForKeyElements.controlObj || {};
var controlKey = selectorTxt.replace (/[^\w]/g, "_");
var timeControl = controlObj [controlKey];
//--- Now set or clear the timer as appropriate.
if (btargetsFound && bWaitOnce && timeControl) {
//--- The only condition where we need to clear the timer.
clearInterval (timeControl);
delete controlObj [controlKey]
}
else {
//--- Set a timer, if needed.
if ( ! timeControl) {
timeControl = setInterval ( function () {
waitForKeyElements ( selectorTxt,
actionFunction,
bWaitOnce,
iframeSelector
);
},
200
);
controlObj [controlKey] = timeControl;
}
}
waitForKeyElements.controlObj = controlObj;
}