使用“stringByEvaluatingJavaScriptFromString”单击UIWebView中的链接

时间:2011-12-03 19:35:19

标签: javascript iphone objective-c ios xcode

如何在UIWebView中使用stringByEvaluatingJavaScriptFromString方法单击链接?实际的超链接本身每次都不同,但测试代码中的措辞(“测试”)总是相同的。

我该怎么做呢?我有一个建议要做以下事情(这不起作用,也没有做任何事情):

var fonts = document.getElementsByTagName('font');
for(i=0;i<fonts.length;i++) {
  if (fonts[i].innerHTML == 'Test') {
  fonts[i].parentNode.childNodes[0].click();
  break;
 }
} 

2 个答案:

答案 0 :(得分:4)

看起来你有一个答案,包括你需要的Objective-C代码,但我想,对于javascript你可以简单地触发链接onclick的内容或导航到相应的url而不是经历模拟的麻烦鼠标单击。当然,我没有在iOS应用程序中对此进行过测试,但可以随意尝试:

var links = document.getElementsByTagName('a');
for(i=0;i<links.length;i++) {
  if (links[i].innerHTML.indexOf('Test') != -1) {
  clickLink(links[i]);
  break;
 }
} 

function clickLink(linkobj) {
 var onclickHandler = linkobj.getAttribute('onclick');
 if (onclickHandler == null) window.location = linkobj.getAttribute('href').replace(/^\s\s*/, '').replace(/\s\s*$/, '');
 else eval(onclickHandler(linkobj));
}

顺便说一句,这段代码中有一个eval将运行onclick处理程序的内容。这可能不安全。如果您只需要导航到链接指定的位置,那么您可能想要删除处理onclick的部分。

下面打印了一个更简单的版本(因为您的示例代码似乎不需要处理onclick),这可能更容易使用。在这种情况下,我在延迟1秒后调用它,但实际上,因为看起来这个代码是为响应iOS端的触发而运行的(按钮点击?),所以你不应该使用延迟而只是等待启用触发器直到加载完成 - webViewDidFinishLoad

function clickLink() {
    var links = document.getElementsByTagName('a');
    for (i = 0; i < links.length; i++) {
        if (links[i].innerHTML.indexOf('Prev') != -1) {
            window.location = links[i].getAttribute('href').replace(/^\s\s*/, '').replace(/\s\s*$/, '');
            break;
        }
    }
}

setTimeout(clickLink, 1000);

jsFiddle使用您的示例代码演示了这一点:http://jsfiddle.net/fzKL7/5/

答案 1 :(得分:1)

我创建了一个示例应用程序,其中包含hooleyhoop在评论中提到的另一个SO问题。

这就是我最终的结果:

- (void)webViewDidFinishLoad:(UIWebView *)wv {
    // Called when the website has finished loading and triggers the JS code
    NSString *javascript = @"function simulate(element, eventName) \
    { \
        var options = extend(defaultOptions, arguments[2] || {}); \
        var oEvent, eventType = null; \
        for (var name in eventMatchers) \
        { \
            if (eventMatchers[name].test(eventName)) { \
                eventType = name; break; \
            } \
        } \
        if (!eventType) { \
            alert('Only HTMLEvents and MouseEvents interfaces are supported'); \
        } \
        if (document.createEvent) \
        { \
            oEvent = document.createEvent(eventType); \
            if (eventType == 'HTMLEvents') \
            { \
                oEvent.initEvent(eventName, options.bubbles, options.cancelable); \
            } \
            else \
            { \
            oEvent.initMouseEvent(eventName, options.bubbles, options.cancelable, document.defaultView, options.button, options.pointerX, options.pointerY, options.pointerX, options.pointerY, options.ctrlKey, options.altKey, options.shiftKey, options.metaKey, options.button, element); \
            } \
            element.dispatchEvent(oEvent); \
        } \
        else \
        { \
            options.clientX = options.pointerX; \
            options.clientY = options.pointerY; \
            var evt = document.createEventObject(); \
            oEvent = extend(evt, options); \
            element.fireEvent('on' + eventName, oEvent); \
        } \
        return element; \
    } \
    function extend(destination, source) { \
        for (var property in source) \
            destination[property] = source[property]; \
        \
        return destination; \
    } \
    var eventMatchers = { \
        'HTMLEvents': /^(?:load|unload|abort|error|select|change|submit|reset|focus|blur|resize|scroll)$/, \
        'MouseEvents': /^(?:click|dblclick|mouse(?:down|up|over|move|out))$/ \
    }; \
    var defaultOptions = { \
        pointerX: 0, \
        pointerY: 0, \
        button: 0, \
        ctrlKey: false, \
        altKey: false, \
        shiftKey: false, \
        metaKey: false, \
        bubbles: true, \
        cancelable: true \
    }; \
    window.setTimeout(function() { \
        var links = document.getElementsByTagName('a'); \
        for(var i in links) { \
            if(links[i].innerHTML == 'Test') { \
                simulate(links[i], 'click'); \
            } \
        } \
    },1);";
    // Execute JS
    [webView stringByEvaluatingJavaScriptFromString:javascript];
}

测试HTML

<html>
    <head>
        <title>Testpage</title>
    </head>
    <body>
        <a href="http://www.google.com">I'm linking to google.com</a><br />
        <a href="http://www.stackoverflow.com">Test</a>
    </body>
</html>

- (void)webViewDidFinishLoad:(UIWebView *)wv

这是UIWebView的委托函数,只要Web视图加载完网站就会调用它。

NSString * javascript = @“...”

这就是我构建JS代码的重点,在开始时,来自触发点击的其他SO问题的函数。最后,我放置了一个超时,执行查找所有“a”标记的部分,循环遍历它们,检查它的innerHTML文本是否为“Test”,如果是这种情况,它会调用simulate函数一个元素作为第一个参数,eventtype作为第二个参数。轰隆隆,点击链接。

我使用了超时,因为它导致直接执行JS的问题,似乎UIWebView需要一些时间,直到函数模拟可用。

干杯, 的Björn