-2

我正在尝试编写一个简单的 javascript 来为 Google 的搜索工具添加更多选项(当您按“更多搜索工具”时显示的选项。但是,当我尝试将新元素附加到现有元素时,我收到一个错误。例如:

var yr = document.getElementById('qdr_y'); 
yr.parent.insertBefore(k,yr);

第二行抛出异常,因为yr为空。通过查看搜索结果页面的直接源代码,我发现基本结果页面仅包含“所有结果”、“更多搜索工具”和隐藏的“更少搜索工具”。所有其他选项都以其他方式注入。

如何访问这些其他元素,以便将新元素添加到正确的位置?

4

2 回答 2

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>and<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() })
});

在此处输入图像描述

它不像我想的那么漂亮,但谷歌让我们做坏事:)

于 2012-04-14T06:17:27.937 回答
0

请注意,parent在您的代码片段中应该是parentNode.

无论如何,一般来说,对于动态元素,您需要检查并等待目标元素。如果需要单击某些内容,您的脚本必须单击它。(在 Google 网站上尝试使用页面 JS 功能通常效果不佳。Google 页面总是为编写脚本提供额外的“乐趣”。;))

您需要自由地使用轮询来补偿 AJAX 延迟。(挂钩 AJAX 事件或使用突变事件都具有很高的痛苦与成功率。轮询效果很好。)

最后,因为它是谷歌,仅仅触发一次投票是不够的,因为那些搜索选项不断被覆盖。

这是一个适用于美国版 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;
}
于 2012-04-14T07:51:35.480 回答