前言
del.icio.us 提供了多种可重用的数据格式。而它提供了通用API 访问和类似PHP的输出格式,使这些数据也可以被JavaScript 开发者将其作为JSON 格式所使用。
Google AJAX Search API 提供一些简单的web 对象:它们执行建立在各种Google服务(页面搜索、本地搜索、视频搜索、Blog 搜索、新闻搜索)之上的内嵌(inline)搜索。
如何把这两项技术结合在一起呢?Google AJAX Search API+TAG=美味的站点?
什么是Google AJAX Search API ?
图-1 这就是Google AJAX Search API?
Google AJAX Search API 是提供在页面和web 应用中嵌入Google Search 的JavaScript 代码库。当然像其它Google 开发API 相同,在使用它之前,你首先需要注册一个API key。
Google AJAX Search API 提供一些简单的web 对象:它们执行建立在各种Google服务(页面搜索、本地搜索、视频搜索、Blog 搜索、新闻搜索)之上的内嵌(inline)搜索。如果你设计页面是为了帮助用户建立内容(比如信息板、blog 等),而这个API 可以设计成:通过允许它们直接把搜索结果复制到它们的信息中的方式来支持前面的这些活动。
Google AJAX Search API 是最新发布的,它的特性被广泛地用户使用,你可以通过加入Google AJAX Search API 讨论组来进行反馈和技术讨论。
用户群
最好具有JavaScript 编程和面向对象编程概念。
介绍
“Hello,World”开场白
这是学习API 的最简单方式。下面的web 页面代码显示了对关键词“VW GTI”的内嵌搜索结果集合。之所以称之为集合,因为它包括了本地搜索、页面搜索、视频和Blog 搜索结果。
<!DOCTYPE html PUBLIC "-//W 3C //DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta http-equiv="content-type" content="text/html; charset=utf-8"/> <title>Hello World - Google AJAX Search API Sample</title> <link href="http://www.google.com/uds/css/gsearch.css" type="text/css" rel="stylesheet"/> <script src="http://www.google.com/uds/api?file=uds.js&v=1.0" type="text/javascript"></script> <script language="Javascript" type="text/javascript"> //<![CDATA[ function OnLoad() { // Create a search control var searchControl = new GSearchControl(); // Add in a full set of searchers var localSearch = new GlocalSearch(); searchControl.addSearcher(localSearch); searchControl.addSearcher(new GwebSearch()); searchControl.addSearcher(new GvideoSearch()); searchControl.addSearcher(new GblogSearch()); searchControl.addSearcher(new GnewsSearch()); // Set the Local Search center point localSearch.setCenterPoint(" New York , NY "); // tell the searcher to draw itself and tell it where to attach searchControl.draw(document.getElementById("searchcontrol")); // execute an inital search searchControl.execute("VW GTI"); } //]]> </script> </head> <body onload="OnLoad()"> <div id="searchcontrol"/> </body> </html>
|
你可以下载本例代码,并进行相应修改,但要注意的一点:你必须使用你自己的API key 替换掉原代码中的API key。
上面代码中包含的Google AJAX Search API javascript 库:
http://www.google.com/uds/api?file=uds.js&v=1.0&key=ABCDEFG,此库囊括了Google Search API 所用到的对象和符号。
代码中的主角是GSearchControl 对象,它控制了一个跨越多种搜索服务的搜索。
可以看到,GlocalSearch、GwebSearch、GvideoSearch、GblogSearch 和GnewsSearch 类型的对象(后称搜索者对象)通过GSearchControl 对象的addSearcher 方法被添加到了搜索控制(search control)中,这些搜索者对象(searcher objects)决定了那些搜索服务在搜索控制的操控之下。
通过调用GSearchControl 的draw()方法,使搜索控制显示在页面中。此方法也可把搜索控制绑定到页面的DOM 中。默认情况下,搜索控制以线性布局(linear layout)显示,你也可以选择标签布局(tabbed layout)。关于布局的选将在下面讲解。
为了使用标签布局选项,搜索控制允许开发者轻松地把 “search form”从搜索结果集合中脱离出来。这种做法的用处之一:在页面的sidebar 中显示search form,而搜索结果罗列在页面中央。
用户通过在搜索控制的文本框中输入搜索单词后按下回车按钮或者点击搜索按钮的方式启动一次搜索。搜索控制将自动进行一次对所要求的各种Google 搜索服务的并行搜索。你也可以通过把搜索单词作为参数传递给搜索控制的execute()方法来以编程的方式启动搜索。
浏览器兼容性
图-2 租用哪种浏览器去冲浪?
Google AJAX Search API 目前支持 Firefox 1.5 以上,IE 6,Safari,Opera 9 以上。
API 升级问题
通过在URL:http://www.google.com/uds/api?file=uds.js&v=1.0 中的参数v 来声明所使用的API 版本(这里的参数v 声明的是1.0 版本)。当Google 进行API升级时,版本号将被升高,并在Google AJAX Search API 讨论组中发布通知。请注意在版本升级时的任何必需的代码变化,如果新版本和你的代码兼容的话,请更新你的URL到新的版本。
当然,在新版本发布后,Google 仍然会在一段时间内同时支持新、旧版本,这段时间可能长达一个月。而这段时间过后,使用旧版本API 的client 将不再被接受,所以请尽量保持使用新版本。
在某个版本的使用期间,Google AJAX Search API 开发团队会周期性的更新API以达到修正bug、提高性能的目的,而这是不会产生新版本的。大多数情况,这些修正对用户来讲是保持透明的,但也存在一些对client 产生无意识的破坏,请访问Google AJAX Search API 讨论组报告这些问题。
示例
注意:这里的示例仅提供了相关的Javascript 代码而并非全部的HTML 文件。你可以将这些代码插入到HTML 文件或者通过点击下载链接下载完整的HTML 文件。
基本功能
下面的代码建立了一个搜索控制,并配置它用以完成跨越本地搜索、页面搜索、视频搜索、blog 搜索的搜索,然后将搜索控制放置在页面中。
// create a search control var searchControl = new GSearchControl(null); // add in a full set of searchers searchControl.addSearcher(new GlocalSearch()); searchControl.addSearcher(new GwebSearch()); searchControl.addSearcher(new GvideoSearch()); searchControl.addSearcher(new GblogSearch()); searchControl.addSearcher(new GnewsSearch()); // tell the searcher to draw itself and tell it where to attach // Note that an element must exist within the HTML document with id "search_control" searchControl.draw(document.getElementById("search_control")); |
GSearcherControl 绘制(Draw)模式
搜索控制可以通过编程选择不同的绘制模式:线性(linear)、标签(tabbed)。GdrawOptions 对象通过它的setDrawMode()方法控制了这种行为。此方法可选择的参数:
GSearchControl.DRAW_MODE_LINEAR
GSearchControl.DRAW_MODE_TABBED
为了实际设置搜索控制对象的绘制模式,需要把GdrawOptions 对象作为参数传送给搜索控制对象的draw 方法。
// create a drawOptions object var drawOptions = new GdrawOptions(); // tell the searcher to draw itself in linear mode drawOptions.setDrawMode(GSearchControl.DRAW_MODE_LINEAR); searchControl.draw(element, drawOptions); // tell the searcher to draw itself in tabbed mode drawOptions.setDrawMode(GSearchControl.DRAW_MODE_TABBED); searchControl.draw(element, drawOptions); |
此方法的另一种常见的选项能将“search form”从搜索结果集合中脱离出来。GdrawOptions 对象通过setSearchFormRoot()方法控制这种行为。此方法接受将作为search form 容器的DOM 元素作为参数。
// create a drawOptions object var drawOptions = new GdrawOptions(); drawOptions.setSearchFormRoot(document.getElementById("searchForm")); searchControl.draw(element, drawOptions); |
搜索者对象(Searcher Objects)
搜索控制对象的addSearcher()方法决定了搜索控制对象操控哪些搜索服务。此方法需要2 个参数:一个参数提供服务对象,另一个提供该服务的选项。下面是当前所支持的搜索者对象:
GlocalSearch
GwebSearch
GvideoSearch
GblogSearch
GnewsSearch
随着Google AJAX Search API 的进化,将会有更多支持的服务被加进来。
搜索者选项(GsearcherOptions)
在单独添加搜索者给搜索控制时,addSearcher()方法的第二个可选参数:
GsearcherOptions 对象,它控制每个服务的默认展开模式,后者影响到搜索结果如何显示在页面中。展开模式有以下几种:
GsearchControl.EXPAND_MODE_OPEN:尽可能地显示全部的搜索结果。
GSearchControl.EXPAND_MODE_CLOSED:隐藏搜索结果,除非通过UI 元素(比如一个箭头)被打开。
GSearchControl.EXPAND_MODE_PARTIAL:部分地显示搜索结果。
// create a searcher options object // set up for open expansion mode // load a searcher with these options var options = new GsearcherOptions(); options.setExpandMode(GSearchControl.EXPAND_MODE_OPEN); searchControl.addSearcher(new GwebSearch(), options); |
控制展开模式
下面的示例演示了如何使用这样的搜索控制其中的每个搜索者都采用不同的展开模式。
注意:当搜索者被绘制为标签模式时,展开模式将被忽略。
// local search, partial options = new GsearcherOptions(); options.setExpandMode(GSearchControl.EXPAND_MODE_PARTIAL); searchControl.addSearcher(new GlocalSearch(), options); // web search, open options = new GsearcherOptions(); options.setExpandMode(GSearchControl.EXPAND_MODE_OPEN); searchControl.addSearcher(new GwebSearch(), options); |
控制搜索者结果定位
在一些应用中,需要把某个指定服务的搜索结果投影到页面的任何位置。这种操作的模式通过服务相应的搜索对象的setRoot()方法实现。
// web search, open, alternate root var options = new GsearcherOptions(); options.setExpandMode(GSearchControl.EXPAND_MODE_OPEN); options.setRoot(document.getElementById("somewhere_else")); searchControl.addSearcher(new GwebSearch(), options); |
保持搜索结果
在迄今为止的示例中,页面中的搜索结果只能用于显示,而不能存储到另一个应用中。然而,这正是Google AJAX Search API 优良适用性。Google AJAX Search API允许用户分发搜索结果给内容创建式的应用,比如blog 发布、信息板等。
GSearchControl 对象通过它的setOnKeepCallback()方法提供此功能。通过使用此方法,在用户希望通过点击在结果下面的“Copy”链接来保存某个搜索结果时,应用需要指定一个对象和被调用的方法。
这个链接只在应用已经调用setOnKeepCallback()方法后才被提供。当用户点击链接时,已经注册的回调方法接收一个代表搜索结果的GResult 对象。这个搜索结果对象包括了搜索者对象的一些特定属性,还有包含着代表整个搜索结果的HTML 元素的统一html属性。用于处理回调的最简单方式就是克隆html 代码,将它贴到应用的DOM 某个节点上。
// establish a keep callback searchControl.setOnKeepCallback(this, MyKeepHandler); function MyKeepHandler(result) { // clone the result html node var node = result.html.cloneNode(true); // attach it var savedResults = document.getElementById("saved_results"); savedResults.appendChild(node); } |
设置站点限制
图-3 有限度的限制是为用户提供了便利
一些情况下,你可能需要限制页面搜索、新闻搜索或者blog 搜索在某个指定的站点或者blog 中进行。当应用这些限制后,你可能还想的搜索结果相关的段落(section)设置你自己的标签(label),或是想对搜索结果相关的段落进行风格化(style)。
所有这些都通过使用搜索者选项的多种方法组合来实现。下面的示例演示了如何使用setUserDefinedLabel()、setUserDefinedClassSuffix()、setSiteRestriction()方法。示例中建立了这样一个搜索控制:对其中一个搜索者(GwebSearch 对象)进行了站点限制,仅允许返回来自amazon.com 的搜索结果,并使用“Amazon.com”作为搜索段落标签,对这个段落(粗体标题、橘色keeper 按钮等)应用一些自定义的CSS 样式表。而对于GblogSearch、GnewsSearch 的站点限制也在下面进行演示:
<style type="text/css"> /* customize checkbox for -siteSearch section and * set section title and keep label to bold */ .gsc-resultsRoot-siteSearch .gsc-keeper { background-image : url('../../css/orange_check.gif'); font-weight : bold; } .gsc-resultsRoot-siteSearch .gsc-title { font-weight : bold; } ... // site restricted web search with custom label // and class suffix var siteSearch = new GwebSearch(); siteSearch.setUserDefinedLabel("Amazon.com"); siteSearch.setUserDefinedClassSuffix("siteSearch"); siteSearch.setSiteRestriction("amazon.com"); searchControl.addSearcher(siteSearch); // site restricted web search using a custom search engine siteSearch = new GwebSearch(); siteSearch.setUserDefinedLabel("Product Reviews"); siteSearch.setSiteRestriction("000455696194071821846:reviews"); searchControl.addSearcher(siteSearch); |
搜索控制回调方法
某些条件下,你需要使用搜索控制,因为它提供了你所需要的一切UI,但是你还需要部分地处理搜索控制接收到的搜索结果。这时就需要使用搜索控制提供的一对回调方法。你可以使用它们在搜索执行之前、搜索执行之后进行提示。请注意:这里并不能指望每个被给定的搜索执行都导致完成状态的产生,这种完成状态可以从不产生,所以不要编写导致死锁的代码:一个典型的例子就是当你想在一个邻近的地图上划分本地搜索结果时,完成状态将不会产生。
下面的代码片段展示了如何使用这两种回调方法。
searchControl.setSearchCompleteCallback(this, App.prototype.OnSearchComplete); searchControl.setSearchStartingCallback(this, App.prototype.OnSearchStarting); App.prototype.OnSearchComplete = function(sc, searcher) { // if we have local search results, put them on the map if ( searcher.results && searcher.results.length > 0) { for (var i = 0; i < searcher.results.length; i++) { var result = searcher.results[i]; // if this is a local search result, then proceed... if (result.GsearchResultClass == GlocalSearch.RESULT_CLASS ) { ... App.prototype.OnSearchStarting = function(sc, searcher, query) { alert(The Query is: " + query); ...
|
自定义Search Form
当使用GSearchControl 时,你的应用可以利用集成的“search form”。这个form提供了一个文本输入框、一个搜索按钮、一个清除按钮,还有“google 商标”。如果你的应用不希望使用搜索控制(search control),取而代之的是使用原始的GSearch 层,那么GSearchForm 对象就派上用场了。使用这个对象,可以使你获得实足的自由度优势和集成在搜索控制的search form 商标,但是它作为独立的对象,你需要自己控制它的行为和被放置的位置。
下面的代码片段展示了如何使用这种能力。
// create a search form without a clear button // bind form submission to my custom code var container = document.getElementById("searchFormContainer"); this.searchForm = new GSearchForm(false, container); this.searchForm.setOnSubmitCallback(this, App.prototype.newSearch); // called on form submit App.prototype.newSearch = function(form) { if (form.input.value) { this.searchControl.execute(form.input.value); } return false; } |
高级的商标用法
使用GSearchControl 或者GSearchForm 时,你的用户会自然地使用到“powered by Google”商标。它们能使你的站点所使用的搜索服务与Google 相结合在一起。而当你的应用不使用这些形式,仍然为用户保留Google 商标也是很重要的。GSearch.getBranding()方法帮助你做到这一点。此方法接受一个HTML DOM 元素,然后将“powered by Google”商标贴到这个元素中。作为选择,获得包含“powered by Google”商标的HTML DOM,使你能够直接贴到上面。
下面的代码片段展示了如何使用这种能力。
// attach "powered by Google" branding GSearch.getBranding(document.getElementById("branding")); ... <div id="branding">Loading...</div> |
附加示例
另外,使用示例对上面的概念进行更详细地演示。
Troubleshooting
如果你在编写代码时遇到问题,请参考下面的步骤找出、修正问题:
确认你的API key 是有效的。
查看输入的代码。请记住JavaScript 是一种大小写敏感的语言。
使用JavaScript 调试器。在Firefox 中,你可以使用JavaScript console
或是Venkman Debugger。在IE 中,你可以使用Microsoft Script Debugger。
搜索AJAX Search API 讨论组。如果你找不到问题的答案,请将你的问题和能
重现问题的页面链接发表在讨论组。
查看来自第三方开发者的其它资源。
API 回顾
Google AJAX Search API 由下面的类组成:
GSearchControl:提供用户接口和对搜索者对象的控制,每个搜索者对象被设计用来执行指定类型的搜索并返回相应类型的结果(网页搜索、本地搜索等)。
GSearch:所有搜索者类的基类,它定义了所有搜索者服务必须实现的接口。
GResult:用来封装搜索者对象产生的搜索结果的基类。
GsearchOptions:用于在将搜索者对象添加到搜索控制时,配置搜索者对象的行为。
下面是使用这些类的推荐模板:
// create a searcher object var sc = new GSearchControl(); // add one or more searchers, specifying options as needed var options = new GsearcherOptions(); options.setExpandMode(GSearchControl.EXPAND_MODE_OPEN); sc.addSearcher(new GwebSearch(), options); ... // activate the search control by calling it's .draw() method sc.draw(document.getElementById("myDiv")); |
一旦上面的基本步骤完成之后,搜索控制将被激活。这时,附加的搜索者将不能添加,只要搜索控制被绘制,搜索者选项也不能修改。如果你需要修改搜索控制的行为,你必须构造、激活一个新的搜索控制。
更多信息请看 Search API class 手册。
不足之处
此API 没有提供Search More 的功能,搜索结果最多为8 个,因此无法作分页搜索。
风格化搜索控制
Coming Soon...
风格化搜索结果
Coming Soon...
使用JSON 和Dishy 轻松集成美味书签
什么是Dishy?
图-4 马赛克的魅力(Dishy)
Dishy 是一种对del.icio.us JSON REST API 的JavaScript 封装。在使用时你所需做的事首先是将它包含到你的HTML 文档中:
<script type="text/javascript" src="dishy.js"></script> |
然后,你可以使用一些方法和属性去编写你的代码。
Dishy 能做什么?
社会书签网站:del.icio.us,提供了多种可重用的数据格式。而它提供了通用API
访问和类似PHP 的输出格式,使这些数据也可以被JavaScript 开发者将其作为JSON 格
式所使用。
Dishy:使用del.icio.us 提供的JSON REST API 来获得关于Tag 的JSON 格式
的工具。
Dishy 与tag 一起协力是用户获得以下益处:
1.你可以接收你的链接或者tag 数据,而不是用服务器端代理。
2.获得的数据被自动缓存。
3.在页面被装载后根据需要摘取数据,并且没有增加页面的负担。
4.由于搜索引擎不愿索引那些显示你的页面的相关性的del.icio.us 链接这类的事情不再发生,你的pagerank 将会提高。
这里使用JSON 输出而不是JavaScript 对象,这正是Dishy 走向标准化、易于接收和显示链接和tag 数据的好处。
Dishy 初始化属性
owner:你的del.icio.us ID。默认值是作者的ID,所以最好用自己的ID 覆盖默认值。
fontMin:在tagcloud 中的tag 的最小文字尺寸,单位为像素。
fontMax:在tagcloud 中的tag 的最大文字尺寸,单位为像素。
amountOfTags:用来获取tagcloud 的tag 数量。
showAmount:boolean 值,表示每个tag 是否括号中显示连接数量。
callback:当方法成功接收到数据时的回调方法。每次回调方法被初始化后,它都被赋值为null。
Dishy 其它属性和方法
dishy 方法都没有返回值,取而代之的是它们会生成dishy 对象的属性,你可以在dishy.callback 属性中定义一个在数据被接收后被调用的回调方法。而且这非常易用:比如,你可以简单地在页面被装载后调用它们,并且当某个访问者点击链接时马上使用数据。
dishy.getTags():接收tags。如果你设置amountOfTags 为null,那么你将获得所有的tag。
dishy.tags:包含tag 和使用它们的链接数量的对象。比如:
{" ajax ":3,"CSS":9,"design":43,"fun":4,"geek":2,"humor":4,"JavaScr ipt":6} |
dishy.tagsHTML:使用由空格分离的rel 链接和定义字体尺寸的嵌入风格构成的tag 的HTML 字符串。其中字体的尺寸是由使用tag 的链接数量决定的。默认值为fontMin和fontMax。
<a rel="tag" style="font-size: 30px;" href="http://del.icio.us/codepo8/ajax">ajax</a> <a rel="tag" style="font-size: 13px;" href="http://del.icio.us/codepo8/art">art</a> <a rel="tag" style="font-size: 14px;" href="http://del.icio.us/codepo8/beginningjavascript">beginningjavasc ript</a> <a rel="tag" style="font-size: 24px;" href="http://del.icio.us/codepo8/CSS">CSS</a> <a rel="tag" style="font-size: 30px;" href="http://del.icio.us/codepo8/design">design</a> |
dishy.getLatest():接收最新的链接。
dishy.latest:最新的链接作为成员的对象数组。
[ {"u":"http://www.openjacob.org/draw2d.html", "d":"Open-jACOB Draw2D", "t":["ajax","graph","graphics","visualization","tools"]}, {"u":"http://www.huhcorp.com/","d":"We do stuff.", "t":["humor","funny","business","satire","marketing","design "]}, {"u":"http://www.virtualnes.com/","d":"virtual super nes - play games classics","t":["Games","Nintendo","Emulator","NES","game"]} ... ] |
dishy.latestHTML:使用xFolk microformat 组装在一起的内嵌链接列表的HTML 字符串。注意:这里没有outer 元素,你必须建立一个UL 来内套它们。
<li class="xfolkentry"> <a class="taggedlink" href="http://www.openjacob.org/draw2d.html">Open-jACOB Draw2D</a> <ul class="meta"> <li> <a rel="tag" href="http://www.del.icio.us/codepo8/ajax">ajax</a> </li> <li> <a rel="tag" href="http://www.del.icio.us/codepo8/graph">graph</a> </li> ... </ul> </li> <li class="xfolkentry"> <a class="taggedlink" href="http://www.huhcorp.com/">We do stuff.</a> <ul class="meta"> <li> <a rel="tag" href="http://www.del.icio.us/codepo8/humor">humor</a> </li> <li> <a rel="tag" href="http://www.del.icio.us/codepo8/funny">funny</a> </li> ... </ul> </li> |
dishy.getByTag(sTag):接收与某个指定的tag 相关的链接。
dishy.tagFeed[sTag]:与dishy.latest 格式相同。
dishy.tagHTML[sTag]:与dishy.latestHTML 相同。
Dishy 示例
Display Latest Links
Display Links and Tag Cloud
Clickable Tag Cloud
Display Links By Tag
改进Dishy 的engage 方法
图-5 “进化”才刚开始
Dishy的核心方法engage:使用提供的参数访问使用del.icio.us JSON REST API的URL,然后执行返回的字符串。
比如访问下面的URL:
http://del.icio.us/feeds/json/cleverpig?raw&callback=dishy
.getFeedTagsByDesFilter
其返回字符串为:
dishy.getFeedTagsByDesFilter([{"u":"http://blog.matrix.org.cn//clever pig/entry/20061214","d":"如何定制Roller blog","t":["定制","自定义","主题 ","Roller","blog","feed","美味书签","flickr","badge"]},… {"u":"http://blog.matrix.org.cn//cleverpig/entry/%E8%B0%81%E5%81%B7%E 8%B5%B0%E4%BA%86%E6%88%91%E4%BB%AC%E7% 9A %84%E5%B9%B8%E7%A6% 8F %E6%84%9 F","d":"谁偷走了我们的幸福感?!","t":["AJAX","广告","adsense","ad"]}]) |
请注意:返回字符串代表了一段JavaScript 代码,而这个方法的名字就是URL 中callback 的参数值(dishy.getFeedTagsByDesFilter)。这表明Dishy 希望使用engage 方法运行这段代码。
而Dishy 源代码中的engage 方法并不兼容IE6。为了实现其跨浏览器的特性,所以必须作一定程度的修改:区分IE 和Mozzila 分别编写不同的实现方法(engageForIE、engageForMozzila),并将engage 方法修改为具有识别浏览器、委托不同实现的方法。
/** * 组合方法:访问url,并执行其返回内容 * @param url */ engage:function(url){ if (window.navigator.appName.indexOf('Microsoft')>=0){ dishy.engageForIE(url); } else if (window.navigator.appName.indexOf('Netscape')>=0){ dishy.engageForMozzila(url); } else{ alert('can/'t get browser version:'+window.navigator.appName); } } //不兼容IE engageForMozzila:function(url){ var s = document.createElement('script'); s.setAttribute('src', url); s.setAttribute('type','text/javascript'); document.getElementsByTagName('head')[0].appendChild(s); }, //不兼容FireFox,因为FireFox的XMLHTTPRequest在open时,对跨域访问抛出“权限 不足的错误” //这里使用prototype.js的AjaxRequest没有回应 engageForIE:function(url){ var parameters=''; dishy.http_request = false; if (window.XMLHttpRequest) { // Mozilla, Safari,... dishy.http_request = new XMLHttpRequest(); if (dishy.http_request.overrideMimeType) { dishy.http_request.overrideMimeType('text/html'); } } else if (window.ActiveXObject) { // IE try { dishy.http_request = new ActiveXObject("Msxml2.XMLHTTP"); } catch (e) { alert(e.description); try { dishy.http_request = new ActiveXObject("Microsoft.XMLHTTP"); } catch (e) { alert(e.description); } } } if (!dishy.http_request) { alert('Cannot create XMLHTTP instance'); return false; } dishy.http_request.onreadystatechange = dishy.requestCallback; try{ dishy.http_request.open('GET', url + parameters, true); dishy.http_request.send(null); } catch (e) { alert(e+":"+e.description); } }, //engageForIE中使用的http_request的回调方法 requestCallback:function () { if (dishy.http_request.readyState == 4) { if (dishy.http_request.status == 200) { //alert(http_request.responseText); eval(dishy.http_request.responseText); } else { alert('There was a problem with the request.'); } } }
|
使用Tags+Search 模式丰富页面的相关性
图-6 内容的关联性是提高UE 的重要元素
Tags+Search 模式
Tags+Search 模式是指利用页面中的Tags,对与Tags 相关的资源进行搜索、罗列。
使用Dishy+AJAX Search API 实现Tags+Search 模式
前提条件:为了方便后面的tag 搜索工作,首先要将文章的标题作为书签的description 值提交到del.icoi.us。
如何添加书签:我在《如何定制Roller blog》介绍了如何在blog 中添加美味书签的方法,在页面上添加美味书签的过程应该与之类似。当然,你也可以使用程序在文章发布时自动将其信息提交到美味书签,此方法就留给大家思考吧。
实现过程:我使用Dishy 根据文章标题找到此文章在del.icoi.us 中相应的Tags,并对Tags 中的多个tag 进行随机抽取组成search 关键字,然后使用Google AJAX Search API 对search 关键字进行搜索,并将搜索结果放到页面适合的位置(比如网站的sidebar)。这将大大增加页面的信息相关性。
具体实现第一步:增加Dishy 对tag 的过滤能力
这里简要说一下如何结合Tags 和Google Search 两项技术。请注意:这里的代码
使用到了prototype.js(1.4 版),而JavaScript 类使用了prototype(也被称为
原型)的风格。
1.首先,把文章的标题作为美味书签的description 值提交到del.icoi.us:在添加书签时需要填写页面URL、描述(description)和tag,而这时最好把文章的title 作为description 值,因为这有利于后面Dishy 对tag 的过滤。
2.进一步改进Dishy 类,为其增加必要的descriptionFilter 属性:
//用于过滤tag的description字符串 descriptionFilter:'', |
3.为Dishy 类增加具有过滤能力的一些方法:
/** * 根据des参数过滤接收tag链接,并在处理后调用回调方法 */ getTagsByDesFilter:function(){ var url = 'http://del.icio.us/feeds/json/'+dishy.owner+'?raw&callback=dishy.get FeedTagsByDesFilter'; dishy.engage(url); }, /** * 处理tag链接,调用回调方法 * @param 调用del.icio.us JSON REST API返回的字符串 */ getFeedTagsByDesFilter:function(o){ dishy.latest=o; dishy.tags = dishy.findTagsByJSONResponse(o); if(dishy.callback !== null){ eval(dishy.callback)(dishy.tags); dishy.callback = null; } }, /** * 使用descriptionFilter对del.icio.us JSON REST API返回的字符串进行过滤, 取出d为descriptionFilter的tag数组 * @param 调用del.icio.us JSON REST API返回的字符串 * @return d为descriptionFilter的tag数组 */ findTagsByJSONResponse:function(o){ for (var k in o) { if (o[k].d==dishy.descriptionFilter){ return o[k].t; } } return null; }, |
具体实现第二步:封装Google AJAX Search API 和页面request 类
1. 封装Google AJAX Search API:
提供两种封装选择:gWebSearchControl 类和gCustomizeWebSearchControl类,前者使用GSearchControl 类实现默认风格的搜索,而后者使用GSearchForm 类实现自定义风格的搜索。大家可以自由选择。具体代码见后面的源代码下载。
2. 封装页面request 类(requestWrapper 类):
对页面的URL 参数进行分析提取出所需要的参数名和参数值。
具体实现第三步:完成测试页面
Dishy.html 页面使用了gWebSearchControl 类来完成search 功能。而dishy_customize.html 页面使用了gCustomizeWebSearchControl 类。这两个页面都提供了“使用搜索控制”按钮和“测试传送参数”按钮,分别演示了手动触发搜索操作和基于页面请求参数触发的搜索操作。
Dishy.html 页面代码片断如下:
<input type="button" name="b1" id="b1" value="使用默认的搜索控制" onclick="javascript:fetchTagsAndSearch('cleverpig','如何定制Roller blog')"/> <input type="button" name="b2" id="b2" value="测试传送参数" onclick="javascript:window.open('./dishy.html?u=cleverpig&d='+escape( '如何定制Roller blog'))"/> <div id="searchcontrol"/> <script> var searchControl = new GSearchControl(); var gW = new gWebSearchControl(searchControl,'matrix.org.cn',$('searchcontrol')); /** * 获取tag,并进行搜索 * @param userName del.icoi.us的ID * @param desFilter description过滤字符串 */ function fetchTagsAndSearch(userName,desFilter){ // change properties dishy.owner = userName; dishy.descriptionFilter=desFilter; dishy.callback=gW.executeSearch; // get tags dishy.getTagsByDesFilter(); } //根据request参数判断是非执行fetchTagsAndSearch var reqW=new requestWrapper(window.location.href); if (reqW.getParamValue('u')!=null && reqW.getParamValue('d')!=null){ fetchTagsAndSearch(reqW.getParamValue('u'),reqW.getParamValue('d' )); } </script> |
上面代码的核心方法是fetchTagsAndSearch(userName,desFilter),它接收del.icoi.us 帐号ID 和描述过滤字。
fetchTagsAndSearch 方法工作流程:
此方法首先设置了owner 和descriptionFilter 属性;
将 callback 方法赋值为gWebSearchControl 类对象的executeSearch 方法,以便在Dishy 获取到tag 后,调用executeSearch 方法进行相应的search;
最后,调用Dishy 的getTagsByDesFilter 方法来获取与descriptionFilter相应的tag 数组。
具体实现第四步:与网站集成
1. 部署页面:
有选择地去掉用于测试的按钮等相关内容后,将页面文件(Dishy.html 或者dishy_customize.html)以及相应的JavaScript 文件(dishy.js、gsearch.js、requestWrapper.js、prototype.js)放到web 服务器的相应目录中;
2. 修改网站页面模板:
编辑网站页面模板使其包含Dishy.html 或者dishy_customize.html,并在网站页面装载时传递两个参数d 和u 给Dishy.html 或者dishy_customize.html 页面:这两个参数分别代表文章的标题和del.icoi.us 帐号ID。
参考资源
Google AJAX Search API
Google AJAX Search API 讨论组
Dishy 开发文档
如何定制Roller blog
Prototype 官方网站
Prototype 开发手册
高级JavaScript 开发快速向导
下载资源