使用“stringByEvaluatingJavaScriptFromString”单击 UIWebView 中的链接
Posted
技术标签:
【中文标题】使用“stringByEvaluatingJavaScriptFromString”单击 UIWebView 中的链接【英文标题】:Click on a link in UIWebView using "stringByEvaluatingJavaScriptFromString" 【发布时间】:2011-12-03 19:35:18 【问题描述】:如何在 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;
【问题讨论】:
您要点击链接还是要在链接的 URL 处加载页面? 看到这个***.com/questions/6157929/… 问题是,我无权编辑页面,也没有任何 ID 或任何东西。我需要在网页中找到文本,然后点击与该文本关联的链接... SO 链接向您展示了如何单击链接。无需编辑页面 - 所有代码都进入您传递给 stringByEvaluatingJavaScriptFromString 的字符串中。如果您的问题还在于找到链接..这本身就是一个不同的问题。它将涉及迭代页面上的所有链接,就像您在问题中所做的那样。 好吧,它说'getElementById',但我的链接没有ID......这就是问题所在。如何在页面上搜索文本,例如“测试”,然后点击与之关联的超链接? 【参考方案1】:看起来你有一个答案,包括你需要的 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/
【讨论】:
不幸的是,您的代码对我不起作用。它只是停留在同一页面上? @pixelbitlabs 您能否发布一些包含您尝试单击的链接之一的 HTML 源代码?我发布的代码应该可以工作,但是如果没有看到任何代码,很难确切地知道你的情况。 只是要注意(我知道这听起来很明显)我不想同时单击它们。我刚在“前一天”尝试过,最初进行了测试,但没有成功。 @pixelbitlabs 你有错误吗?有什么吗?如果将 js 替换为alert('Hello World!');
会起作用吗? alert(links.length);
怎么样? alert(links[i]);
?无关,代码中的最后一个 stringWithFormat 是不必要的。
@pixelbitlabs 我很乐意为您提供进一步的帮助,但我不知所措 - 根据您提供的示例数据,我的 Javascript 工作正常。我们还从另一个用户那里得到验证,它可以在 iOS 应用程序的上下文中运行,并且通过设置警报,您可以自己看到 Javascript 正在您的应用程序中执行。如果没有坐在你的代码前,我不确定我还能为你做什么。如果您只是执行window.location = 'http://apple.com/';
和/或window.location =
您的URL 之一怎么办?可能有助于缩小范围。【参考方案2】:
我创建了一个示例应用程序,其中包含 hooleyhoop 在 cmets 中提到的另一个 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.***.com">Test</a>
</body>
</html>
- (void)webViewDidFinishLoad:(UIWebView *)wv
这是 UIWebView 的委托函数,它会在 Web 视图完成加载网站后立即调用。
NSString *javascript = @"..."
这就是我构建 JS 代码的地方,一开始,触发点击的另一个 SO 问题的函数。最后,我设置了一个超时,执行查找所有“a”标签的部分,循环遍历它们,检查它的 innerHTML 文本是否为“Test”,如果是这种情况,它使用 a 元素调用 simulate
函数作为第一个参数,事件类型作为第二个参数。砰,链接被点击了。
我使用了超时,因为它导致直接执行 JS 出现问题,似乎 UIWebView 需要一些时间才能模拟功能可用。
干杯, 比约恩
【讨论】:
感谢您的回答!如果链接文本没有 ID 或任何内容,只有纯文本,这会起作用吗? :-) 是的,我将用于测试的 HTML 代码添加到我的答案中。 你也可以用 David 的 JS 代码代替我的,它更小而且做同样的事情 ;-)以上是关于使用“stringByEvaluatingJavaScriptFromString”单击 UIWebView 中的链接的主要内容,如果未能解决你的问题,请参考以下文章
在使用加载数据流步骤的猪中,使用(使用 PigStorage)和不使用它有啥区别?
Qt静态编译时使用OpenSSL有三种方式(不使用,动态使用,静态使用,默认是动态使用)