使用jQuery和YQL,以Ajax方式加载外部内容
来源:互联网 发布:中国网络部队61398 编辑:程序博客网 时间:2024/05/21 15:46
我们来看看怎样使用jQuery,以Ajax方式加载外部(其他域上)的内容。这里的所有代码都可以从GitHub下载,也可以在这个演示页面中获取,因而不用复制粘贴了。
OK,Ajax通过jQuery是很容易做到的,大多数解决方案就几行代码:
$(document).ready(function(){$('.ajaxtrigger').click(function(){$('#target').load('ajaxcontent.html');});});
查看这个简单但有点粗陋的Ajax演示就可以看到结果。
这会将所有带ajaxtrigger
类的元素转换成触发器来加载ajaxcontent.html,并在ID为target
的元素中显示其内容。
这样不好,因为多数时候这意味着人们将使用<a href="#">click me</a>
这种空链接,但这不是我们现在要讨论的问题。我在撰写一篇更长的文章,其中会提到增强Ajax可用性和可访问性的所有技巧。
要使其能够重用可以像下面这样:
$(document).ready(function(){$('.ajaxtrigger').click(function(){$('#target').load($(this).attr('href'));return false;});});
这样,你可以使用<a href="ajaxcontent.html" class="ajaxtrigger">load some content</a>
来加载内容,而所有JavaScript代码都可以重用。
查看这个可重用Ajax演示就能看到结果。
我要解决的问题发生在点击演示页面中的第二个链接时:加载外部内容失败,因为Ajax不允许跨域加载内容。这意味着,<a href="http://icant.co.uk/" class="ajaxtrigger">see my portfolio</a>
加载Ajax内容将失败,而且没有提示。尽管你无数遍地点击这个链接,但是什么都不会发生。避免出现这种情况的一个方法,是简单地让浏览器加载该文档,但前提是用户真的想加载外部链接。
查看这个允许加载外部链接的演示就能看到结果。
$(document).ready(function(){$('.ajaxtrigger').click(function(){var url = $(this).attr('href');if(url.match('^http')){return true;} else {$('#target').load(url);return false;}});});
使用PHP代理
如果浏览Web,你会发现大多数的解决方案是PHP(或其他语言)代理脚本。比如,下面是使用cURL的proxy.php代理脚本:
<?php$url = $_GET['url'];$ch = curl_init();curl_setopt($ch, CURLOPT_URL, $url);curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);$output = curl_exec($ch);curl_close($ch);echo $content;?>
然后可以稍作修改使用这个脚本(使用代理):
$(document).ready(function(){$('.ajaxtrigger').click(function(){var url = $(this).attr('href');if(url.match('^http')){url = 'proxy.php?url=' + url;}$('#target').load(url);return false;});});
用这样的代理脚本依旧是个很蠢的办法,因为不进行过滤,人们就可以使用这个脚本来加载你服务器上的任何文档,并将其内容显示在自己的页面中(用firebug来重命名链接,就能看到你服务器上的任何内容),他们可以使用它将邮件群发脚本插入文档,或者简单地使用它来重定向到任何其他Web资源,并且让你的服务器看上去就是发送请求的那个服务器。垃圾邮件制造者就有了施展才华的地方了。
使用白名单和过滤代理
因而,要想使用代理,就得确保有被认可的URI的白名单。此外,除了另一个HTML文档的主体,其他的都除去比较好。另一个好办法是过滤脚本。这会避免显示错误和执行你本不想在网站上执行的脚本。
就像下面这样:
<?php$url = $_GET['url'];$allowedurls = array('http://developer.yahoo.com','http://icant.co.uk');if(in_array($url,$allowedurls)){$ch = curl_init();curl_setopt($ch, CURLOPT_URL, $url);curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);$output = curl_exec($ch);curl_close($ch);$content = preg_replace('/.*<body[^>]*>/msi','',$output);$content = preg_replace('/</body>.*/msi','',$content);$content = preg_replace('/<?/body[^>]*>/msi','',$content);$content = preg_replace('/[r|n]+/msi','',$content);$content = preg_replace('/<--[Ss]*?-->/msi','',$content);$content = preg_replace('/<noscript[^>]*>[Ss]*?</noscript>/msi','',$content);$content = preg_replace('/<script[^>]*>[Ss]*?</script>/msi','',$content);$content = preg_replace('/<script.*/>/msi','',$content);echo $content;} else {echo 'Error: URL not allowed to load here.';}?>
使用YQL的纯JavaScript解决方案
但是,如果没有权利访问服务器,或者你只想使用JavaScript,怎么办?不用担心,这是可以做到的。借助YQL可以加载任何HTML文档,并以JSON格式返回。jQuery具有加载JSON的好接口,因此与YQL一起使用就可以达到我们的目的。
从YQL获取HTML很容易,使用下面语句即可:
select * from html where url="http://icant.co.uk"
YQL还可以完成下面一些事:
- 加载并清理HTML文档
- 使用HTML Tidy运行HTML文档来删除不好的标记
- 缓存HTML
- 只返回HTML的主体内容,因而除内联样式外不需处理其他样式
数据输出格式可以是XML或JSON。如果为JSON定义了回调参数,就表明要使用JSON-P,所有HTML都会保存在一个JavaScript对象中——这不适合重组。
foo({"query":{<a href=""1" title="">count</a>",<a href=""2010-01-10T07:51:43Z" title="">created</a>",<a href=""en-US" title="">lang</a>",<a href=""2010-01-10T07:51:43Z" title="">updated</a>",<a href=""http://query.yahoo[...whatever...]k%22" title="">uri</a>","results":{"body":{"div":{<a href=""doc2" title="">id</a>",<a href="[{"id":"hd" title="">div</a>",<a href=""icant.co.uk" title="">h1</a> - everything Christian Heilmann"},{<a href=""bd" title="">id</a>","div":[{<a href="[{"h2":"About" title="">div</a> this and me","[... and so on...]}}}}}}}});
当定义了带XML输出的回调时,会得到将HTML数据作为数组中字符串的函数调用,简单多了:
foo({"query":{<a href=""1" title="">count</a>",<a href=""2010-01-10T07:47:40Z" title="">created</a>",<a href=""en-US" title="">lang</a>",<a href=""2010-01-10T07:47:40Z" title="">updated</a>",<a href=""http://query.y[...who" title="">uri</a> cares...]%22"},"results":["<body>n <div id="doc2">n <div id="hd">n<h1>icant.co.uk - everything Christian Heilmann</h1>n... and so on ..."]});
使用jQuery的getJSON()
方法,访问YQL端点,这很容易实现:
$.getJSON("http://query.yahooapis.com/v1/public/yql?"+"q=select%20*%20from%20html%20where%20url%3D%22"+encodeURIComponent(url)+"%22&format=xml'&callback=?",function(data){if(data.results[0]){var data = filterData(data.results[0]);container.html(data);} else {var errormsg = '<p>Error: could not load the page.</p>';container.html(errormsg);}});
组合在一起可以得到使用jQuery和YQL的跨域Ajax解决方案:
$(document).ready(function(){var container = $('#target');$('.ajaxtrigger').click(function(){doAjax($(this).attr('href'));return false;});function doAjax(url){// 如果它是个外部URIif(url.match('^http')){// 调用YQL$.getJSON("http://query.yahooapis.com/v1/public/yql?"+"q=select%20*%20from%20html%20where%20url%3D%22"+encodeURIComponent(url)+"%22&format=xml'&callback=?",// 这个函数得到的数据来自成功的JSON-P调用function(data){// 如果有数据,过滤它并呈现出来if(data.results[0]){var data = filterData(data.results[0]);container.html(data);// 否则提示出错了} else {var errormsg = '<p>Error: could not load the page.</p>';container.html(errormsg);}});// 如果它不是外部URI,使用Ajax的load()方法} else {$('#target').load(url);}}// 过滤掉一些不好的东西function filterData(data){data = data.replace(/<?/body[^>]*>/g,'');data = data.replace(/[r|n]+/g,'');data = data.replace(/<--[Ss]*?-->/g,'');data = data.replace(/<noscript[^>]*>[Ss]*?</noscript>/g,'');data = data.replace(/<script[^>]*>[Ss]*?</script>/g,'');data = data.replace(/<script.*/>/,'');return data;}});
当然,这个例子还很粗糙。实际的Ajax解决方案应该考虑超时,以及未找到文档的情况。查看带加载指示器、异常处理和黄褪技术的完整代码以获得灵感。
- 使用jQuery和YQL,以Ajax方式加载外部内容
- jQuery加载外部文件的方式get、post、ajax、load的区别
- jQuery Form Plugin以ajax方式提交CKEditor编辑的内容丢失
- JQuery加载外部文件的方式get、post、ajax、load的区别及异步加载的实现
- jquery之利用ajax与服务器交谈(加载内容到元素上之利用jquery加载内容,使用load()方法)
- VC++以DLL方式加载和使用SQLite数据库
- .NET中使用Jquery和Ajax(三) - load加载
- ajax以get和post方式请求
- 怎样使AJAX有利于SEO:为使用JS和AJAX动态加载的内容制定href
- YQL
- YQL
- Jquery和Struts2使用Ajax时部分属性以json返回的处理
- 【jQuery】使用ajax()方法加载服务器数据
- jquery使用ajax加载并解析xml
- 动态加载页面-使用jquery ajax
- jQuery加载方法以及ajax的使用
- 分享javascript加载外部内容
- jsp使用jquery通过ajax方式访问
- ContextMenuStrip简单使用
- ExtJs 精典布局
- 常用字符集编码详解:ASCII 、GB2312、GBK、GB18030、UTF-8、unicode
- 端口大全及端口关闭/打开方法(下)
- 网址。
- 使用jQuery和YQL,以Ajax方式加载外部内容
- linux内核支持pppd
- java 创建文件和目录
- unix: Sunos Solaris显示中文乱码,使用SecureCRT连接正确显示中文
- Tapjoy创始人新推移动电商平台Karma
- sysgen环境变量到底怎么产生作用的?
- 什么是XenServer
- Virtual Printer文章
- Jquery ajaxsubmit 上传图片