使用jQuery和YQL,以Ajax方式載入外部內容

來源:互聯網
上載者:User

我們來看看怎樣使用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){ // 如果它是個外部URI if(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 { varerrormsg = '<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解決方案應該考慮逾時,以及未找到文檔的情況。查看帶載入指標、異常處理和黃褪技術的完整代碼以獲得靈感。

 摘自 圖靈教育

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.