GoogleSearchStore.js 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663
  1. /*
  2. Copyright (c) 2004-2012, The Dojo Foundation All Rights Reserved.
  3. Available via Academic Free License >= 2.1 OR the modified BSD license.
  4. see: http://dojotoolkit.org/license for details
  5. */
  6. if(!dojo._hasResource["dojox.data.GoogleSearchStore"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
  7. dojo._hasResource["dojox.data.GoogleSearchStore"] = true;
  8. dojo.provide("dojox.data.GoogleSearchStore");
  9. dojo.require("dojo.io.script");
  10. dojo.provide("dojox.data.GoogleWebSearchStore");
  11. dojo.provide("dojox.data.GoogleBlogSearchStore");
  12. dojo.provide("dojox.data.GoogleLocalSearchStore");
  13. dojo.provide("dojox.data.GoogleVideoSearchStore");
  14. dojo.provide("dojox.data.GoogleNewsSearchStore");
  15. dojo.provide("dojox.data.GoogleBookSearchStore");
  16. dojo.provide("dojox.data.GoogleImageSearchStore");
  17. dojo.experimental("dojox.data.GoogleSearchStore");
  18. dojo.declare("dojox.data.GoogleSearchStore",null,{
  19. // summary:
  20. // A data store for retrieving search results from Google.
  21. // This data store acts as a base class for Google searches,
  22. // and has a number of child data stores that implement different
  23. // searches. This store defaults to searching the web, and is functionally
  24. // identical to the dojox.data.GoogleWebSearchStore object.
  25. // The following attributes are supported on each item:
  26. // <ul>
  27. // <li>url - The URL for the item</li>
  28. // <li>unescapedUrl - The URL for the item, with URL escaping. This is often more readable</li>
  29. // <li>visibleUrl - The URL with no protocol specified.
  30. // <li>cacheUrl - The URL to the copy of the document cached by Google
  31. // <li>title - The page title in HTML format.</li>
  32. // <li>titleNoFormatting - The page title in plain text</li>
  33. // <li>content - A snippet of information about the page</li>
  34. // </ul>
  35. // The query accepts one parameter: text - The string to search for
  36. constructor: function(/*Object*/args){
  37. // summary:
  38. // Initializer for the GoogleSearchStore store.
  39. // description:
  40. // The GoogleSearchStore is a Datastore interface to
  41. // the Google search service. The constructor accepts the following arguments:
  42. // <ul>
  43. // <li>label - the label attribute to use. Defaults to titleNoFormatting</li>
  44. // <li>key - The API key to use. This is optional</li>
  45. // <li>lang - The language locale to use. Defaults to the browser locale</li>
  46. // </ul>
  47. if(args){
  48. if(args.label){
  49. this.label = args.label;
  50. }
  51. if(args.key){
  52. this._key = args.key;
  53. }
  54. if(args.lang){
  55. this._lang = args.lang;
  56. }
  57. if("urlPreventCache" in args){
  58. this.urlPreventCache = args.urlPreventCache?true:false;
  59. }
  60. }
  61. this._id = dojox.data.GoogleSearchStore.prototype._id++;
  62. },
  63. // _id: Integer
  64. // A unique identifier for this store.
  65. _id: 0,
  66. // _requestCount: Integer
  67. // A counter for the number of requests made. This is used to define
  68. // the callback function that GoogleSearchStore will use.
  69. _requestCount: 0,
  70. // _googleUrl: String
  71. // The URL to Googles search web service.
  72. _googleUrl: "http://ajax.googleapis.com/ajax/services/search/",
  73. // _storeRef: String
  74. // The internal reference added to each item pointing at the store which owns it.
  75. _storeRef: "_S",
  76. // _attributes: Array
  77. // The list of attributes that this store supports
  78. _attributes: [ "unescapedUrl", "url", "visibleUrl", "cacheUrl", "title",
  79. "titleNoFormatting", "content", "estimatedResultCount"],
  80. // _aggregtedAttributes: Hash
  81. // Maps per-query aggregated attributes that this store supports to the result keys that they come from.
  82. _aggregatedAttributes: {
  83. estimatedResultCount: "cursor.estimatedResultCount"
  84. },
  85. // label: String
  86. // The default attribute which acts as a label for each item.
  87. label: "titleNoFormatting",
  88. // type: String
  89. // The type of search. Valid values are "web", "local", "video", "blogs", "news", "books", "images".
  90. // This should not be set directly. Instead use one of the child classes.
  91. _type: "web",
  92. // urlPreventCache: boolean
  93. // Sets whether or not to pass preventCache to dojo.io.script.
  94. urlPreventCache: true,
  95. // _queryAttrs: Hash
  96. // Maps query hash keys to Google query parameters.
  97. _queryAttrs: {
  98. text: 'q'
  99. },
  100. _assertIsItem: function(/* item */ item){
  101. // summary:
  102. // This function tests whether the item passed in is indeed an item in the store.
  103. // item:
  104. // The item to test for being contained by the store.
  105. if(!this.isItem(item)){
  106. throw new Error("dojox.data.GoogleSearchStore: a function was passed an item argument that was not an item");
  107. }
  108. },
  109. _assertIsAttribute: function(/* attribute-name-string */ attribute){
  110. // summary:
  111. // This function tests whether the item passed in is indeed a valid 'attribute' like type for the store.
  112. // attribute:
  113. // The attribute to test for being contained by the store.
  114. if(typeof attribute !== "string"){
  115. throw new Error("dojox.data.GoogleSearchStore: a function was passed an attribute argument that was not an attribute name string");
  116. }
  117. },
  118. getFeatures: function(){
  119. // summary:
  120. // See dojo.data.api.Read.getFeatures()
  121. return {
  122. 'dojo.data.api.Read': true
  123. };
  124. },
  125. getValue: function(item, attribute, defaultValue){
  126. // summary:
  127. // See dojo.data.api.Read.getValue()
  128. var values = this.getValues(item, attribute);
  129. if(values && values.length > 0){
  130. return values[0];
  131. }
  132. return defaultValue;
  133. },
  134. getAttributes: function(item){
  135. // summary:
  136. // See dojo.data.api.Read.getAttributes()
  137. return this._attributes;
  138. },
  139. hasAttribute: function(item, attribute){
  140. // summary:
  141. // See dojo.data.api.Read.hasAttributes()
  142. if(this.getValue(item,attribute)){
  143. return true;
  144. }
  145. return false;
  146. },
  147. isItemLoaded: function(item){
  148. // summary:
  149. // See dojo.data.api.Read.isItemLoaded()
  150. return this.isItem(item);
  151. },
  152. loadItem: function(keywordArgs){
  153. // summary:
  154. // See dojo.data.api.Read.loadItem()
  155. },
  156. getLabel: function(item){
  157. // summary:
  158. // See dojo.data.api.Read.getLabel()
  159. return this.getValue(item,this.label);
  160. },
  161. getLabelAttributes: function(item){
  162. // summary:
  163. // See dojo.data.api.Read.getLabelAttributes()
  164. return [this.label];
  165. },
  166. containsValue: function(item, attribute, value){
  167. // summary:
  168. // See dojo.data.api.Read.containsValue()
  169. var values = this.getValues(item,attribute);
  170. for(var i = 0; i < values.length; i++){
  171. if(values[i] === value){
  172. return true;
  173. }
  174. }
  175. return false;
  176. },
  177. getValues: function(item, attribute){
  178. // summary:
  179. // See dojo.data.api.Read.getValue()
  180. this._assertIsItem(item);
  181. this._assertIsAttribute(attribute);
  182. var val = item[attribute];
  183. if(dojo.isArray(val)) {
  184. return val;
  185. }else if(val !== undefined){
  186. return [val];
  187. }else{
  188. return [];
  189. }
  190. },
  191. isItem: function(item){
  192. // summary:
  193. // See dojo.data.api.Read.isItem()
  194. if(item && item[this._storeRef] === this){
  195. return true;
  196. }
  197. return false;
  198. },
  199. close: function(request){
  200. // summary:
  201. // See dojo.data.api.Read.close()
  202. },
  203. _format: function(item, name){
  204. return item;//base implementation does not format any items
  205. },
  206. fetch: function(request){
  207. // summary:
  208. // Fetch Google search items that match to a query
  209. // request:
  210. // A request object
  211. // fetchHandler:
  212. // A function to call for fetched items
  213. // errorHandler:
  214. // A function to call on error
  215. request = request || {};
  216. var scope = request.scope || dojo.global;
  217. if(!request.query){
  218. if(request.onError){
  219. request.onError.call(scope, new Error(this.declaredClass +
  220. ": A query must be specified."));
  221. return;
  222. }
  223. }
  224. //Make a copy of the request object, in case it is
  225. //modified outside the store in the middle of a request
  226. var query = {};
  227. for(var attr in this._queryAttrs) {
  228. query[attr] = request.query[attr];
  229. }
  230. request = {
  231. query: query,
  232. onComplete: request.onComplete,
  233. onError: request.onError,
  234. onItem: request.onItem,
  235. onBegin: request.onBegin,
  236. start: request.start,
  237. count: request.count
  238. };
  239. //Google's web api will only return a max of 8 results per page.
  240. var pageSize = 8;
  241. //Generate a unique function to be called back
  242. var callbackFn = "GoogleSearchStoreCallback_" + this._id + "_" + (++this._requestCount);
  243. //Build up the content to send the request for.
  244. //rsz is the result size, "large" gives 8 results each time
  245. var content = this._createContent(query, callbackFn, request);
  246. var firstRequest;
  247. if(typeof(request.start) === "undefined" || request.start === null){
  248. request.start = 0;
  249. }
  250. if(!request.count){
  251. request.count = pageSize;
  252. }
  253. firstRequest = {start: request.start - request.start % pageSize};
  254. var _this = this;
  255. var searchUrl = this._googleUrl + this._type;
  256. var getArgs = {
  257. url: searchUrl,
  258. preventCache: this.urlPreventCache,
  259. content: content
  260. };
  261. var items = [];
  262. var successfulReq = 0;
  263. var finished = false;
  264. var lastOnItem = request.start -1;
  265. var numRequests = 0;
  266. var scriptIds = [];
  267. // Performs the remote request.
  268. function doRequest(req){
  269. //Record how many requests have been made.
  270. numRequests ++;
  271. getArgs.content.context = getArgs.content.start = req.start;
  272. var deferred = dojo.io.script.get(getArgs);
  273. scriptIds.push(deferred.ioArgs.id);
  274. //We only set up the errback, because the callback isn't ever really used because we have
  275. //to link to the jsonp callback function....
  276. deferred.addErrback(function(error){
  277. if(request.onError){
  278. request.onError.call(scope, error, request);
  279. }
  280. });
  281. }
  282. // Function to handle returned data.
  283. var myHandler = function(start, data){
  284. if (scriptIds.length > 0) {
  285. // Delete the script node that was created.
  286. dojo.query("#" + scriptIds.splice(0,1)).forEach(dojo.destroy);
  287. }
  288. if(finished){return;}
  289. var results = _this._getItems(data);
  290. var cursor = data ? data['cursor']: null;
  291. if(results){
  292. //Process the results, adding the store reference to them
  293. for(var i = 0; i < results.length && i + start < request.count + request.start; i++) {
  294. _this._processItem(results[i], data);
  295. items[i + start] = results[i];
  296. }
  297. successfulReq ++;
  298. if(successfulReq == 1){
  299. // After the first request, we know how many results exist.
  300. // So perform any follow up requests to retrieve more data.
  301. var pages = cursor ? cursor.pages : null;
  302. var firstStart = pages ? Number(pages[pages.length - 1].start) : 0;
  303. //Call the onBegin method if it exists
  304. if (request.onBegin){
  305. var est = cursor ? cursor.estimatedResultCount : results.length;
  306. var total = est ? Math.min(est, firstStart + results.length) : firstStart + results.length;
  307. request.onBegin.call(scope, total, request);
  308. }
  309. // Request the next pages.
  310. var nextPage = (request.start - request.start % pageSize) + pageSize;
  311. var page = 1;
  312. while(pages){
  313. if(!pages[page] || Number(pages[page].start) >= request.start + request.count){
  314. break;
  315. }
  316. if(Number(pages[page].start) >= nextPage) {
  317. doRequest({start: pages[page].start});
  318. }
  319. page++;
  320. }
  321. }
  322. // Call the onItem function on all retrieved items.
  323. if(request.onItem && items[lastOnItem + 1]){
  324. do{
  325. lastOnItem++;
  326. request.onItem.call(scope, items[lastOnItem], request);
  327. }while(items[lastOnItem + 1] && lastOnItem < request.start + request.count);
  328. }
  329. //If this is the last request, call final fetch handler.
  330. if(successfulReq == numRequests){
  331. //Process the items...
  332. finished = true;
  333. //Clean up the function, it should never be called again
  334. dojo.global[callbackFn] = null;
  335. if(request.onItem){
  336. request.onComplete.call(scope, null, request);
  337. }else{
  338. items = items.slice(request.start, request.start + request.count);
  339. request.onComplete.call(scope, items, request);
  340. }
  341. }
  342. }
  343. };
  344. var callbacks = [];
  345. var lastCallback = firstRequest.start - 1;
  346. // Attach a callback function to the global namespace, where Google can call it.
  347. dojo.global[callbackFn] = function(start, data, responseCode, errorMsg){
  348. try {
  349. if(responseCode != 200){
  350. if(request.onError){
  351. request.onError.call(scope, new Error("Response from Google was: " + responseCode), request);
  352. }
  353. dojo.global[callbackFn] = function(){};//an error occurred, do not return anything else.
  354. return;
  355. }
  356. if(start == lastCallback + 1){
  357. myHandler(Number(start), data);
  358. lastCallback += pageSize;
  359. //make sure that the callbacks happen in the correct sequence
  360. if(callbacks.length > 0){
  361. callbacks.sort(_this._getSort());
  362. //In case the requsts do not come back in order, sort the returned results.
  363. while(callbacks.length > 0 && callbacks[0].start == lastCallback + 1){
  364. myHandler(Number(callbacks[0].start), callbacks[0].data);
  365. callbacks.splice(0,1);
  366. lastCallback += pageSize;
  367. }
  368. }
  369. }else{
  370. callbacks.push({start:start, data: data});
  371. }
  372. } catch (e) {
  373. request.onError.call(scope, e, request);
  374. }
  375. };
  376. // Perform the first request. When this has finished
  377. // we will have a list of pages, which can then be
  378. // gone through
  379. doRequest(firstRequest);
  380. },
  381. _getSort: function() {
  382. return function(a,b){
  383. if(a.start < b.start){return -1;}
  384. if(b.start < a.start){return 1;}
  385. return 0;
  386. };
  387. },
  388. _processItem: function(item, data) {
  389. item[this._storeRef] = this;
  390. // Copy aggregated attributes from query results to the item.
  391. for(var attribute in this._aggregatedAttributes) {
  392. item[attribute] = dojo.getObject(this._aggregatedAttributes[attribute], false, data);
  393. }
  394. },
  395. _getItems: function(data){
  396. return data['results'] || data;
  397. },
  398. _createContent: function(query, callback, request){
  399. var content = {
  400. v: "1.0",
  401. rsz: "large",
  402. callback: callback,
  403. key: this._key,
  404. hl: this._lang
  405. };
  406. for(var attr in this._queryAttrs) {
  407. content[this._queryAttrs[attr]] = query[attr];
  408. }
  409. return content;
  410. }
  411. });
  412. dojo.declare("dojox.data.GoogleWebSearchStore", dojox.data.GoogleSearchStore,{
  413. // Summary:
  414. // A data store for retrieving search results from Google.
  415. // The following attributes are supported on each item:
  416. // <ul>
  417. // <li>title - The page title in HTML format.</li>
  418. // <li>titleNoFormatting - The page title in plain text</li>
  419. // <li>content - A snippet of information about the page</li>
  420. // <li>url - The URL for the item</li>
  421. // <li>unescapedUrl - The URL for the item, with URL escaping. This is often more readable</li>
  422. // <li>visibleUrl - The URL with no protocol specified.</li>
  423. // <li>cacheUrl - The URL to the copy of the document cached by Google</li>
  424. // <li>estimatedResultCount - (aggregated per-query) estimated number of results</li>
  425. // </ul>
  426. // The query accepts one parameter: text - The string to search for
  427. });
  428. dojo.declare("dojox.data.GoogleBlogSearchStore", dojox.data.GoogleSearchStore,{
  429. // Summary:
  430. // A data store for retrieving search results from Google.
  431. // The following attributes are supported on each item:
  432. // <ul>
  433. // <li>title - The blog post title in HTML format.</li>
  434. // <li>titleNoFormatting - The blog post title in plain text</li>
  435. // <li>content - A snippet of information about the blog post</li>
  436. // <li>blogUrl - The URL for the blog</li>
  437. // <li>postUrl - The URL for the a single blog post</li>
  438. // <li>visibleUrl - The URL with no protocol specified.
  439. // <li>cacheUrl - The URL to the copy of the document cached by Google
  440. // <li>author - The author of the blog post</li>
  441. // <li>publishedDate - The published date, in RFC-822 format</li>
  442. // </ul>
  443. // The query accepts one parameter: text - The string to search for
  444. _type: "blogs",
  445. _attributes: ["blogUrl", "postUrl", "title", "titleNoFormatting", "content",
  446. "author", "publishedDate"],
  447. _aggregatedAttributes: { }
  448. });
  449. dojo.declare("dojox.data.GoogleLocalSearchStore", dojox.data.GoogleSearchStore,{
  450. // summary:
  451. // A data store for retrieving search results from Google.
  452. // The following attributes are supported on each item:
  453. // <ul>
  454. // <li>title - The blog post title in HTML format.</li>
  455. // <li>titleNoFormatting - The blog post title in plain text</li>
  456. // <li>content - A snippet of information about the blog post</li>
  457. // <li>url - The URL for the item</li>
  458. // <li>lat - The latitude.</li>
  459. // <li>lng - The longtitude.</li>
  460. // <li>streetAddress - The street address</li>
  461. // <li>city - The city</li>
  462. // <li>region - The region</li>
  463. // <li>country - The country</li>
  464. // <li>phoneNumbers - Phone numbers associated with this address. Can be one or more.</li>
  465. // <li>ddUrl - A URL that can be used to provide driving directions from the center of the search results to this search results</li>
  466. // <li>ddUrlToHere - A URL that can be used to provide driving directions from this search result to a user specified location</li>
  467. // <li>staticMapUrl - The published date, in RFC-822 format</li>
  468. // <li>viewport - Recommended viewport for the query results (same for all results in a query)
  469. // <ul>
  470. // <li>center - contains lat, lng properties</li>
  471. // <li>span - lat, lng properties for the viewport span</li>
  472. // <li>ne, sw - lat, lng properties for the viewport corners<li>
  473. // </ul>
  474. // </li>
  475. // </ul>
  476. // The query accepts the following parameters:
  477. // <ul>
  478. // <li>text - The string to search for</li>
  479. // <li>centerLatLong - Comma-separated lat & long for the center of the search (e.g. "48.8565,2.3509")</li>
  480. // <li>searchSpan - Comma-separated lat & long degrees indicating the size of the desired search area (e.g. "0.065165,0.194149")</li>
  481. // </ul>
  482. _type: "local",
  483. _attributes: ["title", "titleNoFormatting", "url", "lat", "lng", "streetAddress",
  484. "city", "region", "country", "phoneNumbers", "ddUrl", "ddUrlToHere",
  485. "ddUrlFromHere", "staticMapUrl", "viewport"],
  486. _aggregatedAttributes: {
  487. viewport: "viewport"
  488. },
  489. _queryAttrs: {
  490. text: 'q',
  491. centerLatLong: 'sll',
  492. searchSpan: 'sspn'
  493. }
  494. });
  495. dojo.declare("dojox.data.GoogleVideoSearchStore", dojox.data.GoogleSearchStore,{
  496. // summary:
  497. // A data store for retrieving search results from Google.
  498. // The following attributes are supported on each item:
  499. // <ul>
  500. // <li>title - The blog post title in HTML format.</li>
  501. // <li>titleNoFormatting - The blog post title in plain text</li>
  502. // <li>content - A snippet of information about the blog post</li>
  503. // <li>url - The URL for the item</li>
  504. // <li>published - The published date, in RFC-822 format.</li>
  505. // <li>publisher - The name of the publisher.</li>
  506. // <li>duration - The approximate duration, in seconds, of the video.</li>
  507. // <li>tbWidth - The width in pixels of the video.</li>
  508. // <li>tbHeight - The height in pixels of the video</li>
  509. // <li>tbUrl - The URL to a thumbnail representation of the video.</li>
  510. // <li>playUrl - If present, supplies the url of the flash version of the video that can be played inline on your page. To play this video simply create and <embed> element on your page using this value as the src attribute and using application/x-shockwave-flash as the type attribute. If you want the video to play right away, make sure to append &autoPlay=true to the url..</li>
  511. // </ul>
  512. // The query accepts one parameter: text - The string to search for
  513. _type: "video",
  514. _attributes: ["title", "titleNoFormatting", "content", "url", "published", "publisher",
  515. "duration", "tbWidth", "tbHeight", "tbUrl", "playUrl"],
  516. _aggregatedAttributes: { }
  517. });
  518. dojo.declare("dojox.data.GoogleNewsSearchStore", dojox.data.GoogleSearchStore,{
  519. // summary:
  520. // A data store for retrieving search results from Google.
  521. // The following attributes are supported on each item:
  522. // <ul>
  523. // <li>title - The news story title in HTML format.</li>
  524. // <li>titleNoFormatting - The news story title in plain text</li>
  525. // <li>content - A snippet of information about the news story</li>
  526. // <li>url - The URL for the item</li>
  527. // <li>unescapedUrl - The URL for the item, with URL escaping. This is often more readable</li>
  528. // <li>publisher - The name of the publisher</li>
  529. // <li>clusterUrl - A URL pointing to a page listing related storied.</li>
  530. // <li>location - The location of the news story.</li>
  531. // <li>publishedDate - The date of publication, in RFC-822 format.</li>
  532. // <li>relatedStories - An optional array of objects specifying related stories.
  533. // Each object has the following subset of properties:
  534. // "title", "titleNoFormatting", "url", "unescapedUrl", "publisher", "location", "publishedDate".
  535. // </li>
  536. // </ul>
  537. // The query accepts one parameter: text - The string to search for
  538. _type: "news",
  539. _attributes: ["title", "titleNoFormatting", "content", "url", "unescapedUrl", "publisher",
  540. "clusterUrl", "location", "publishedDate", "relatedStories" ],
  541. _aggregatedAttributes: { }
  542. });
  543. dojo.declare("dojox.data.GoogleBookSearchStore", dojox.data.GoogleSearchStore,{
  544. // summary:
  545. // A data store for retrieving search results from Google.
  546. // The following attributes are supported on each item:
  547. // <ul>
  548. // <li>title - The book title in HTML format.</li>
  549. // <li>titleNoFormatting - The book title in plain text</li>
  550. // <li>authors - An array of authors</li>
  551. // <li>url - The URL for the item</li>
  552. // <li>unescapedUrl - The URL for the item, with URL escaping. This is often more readable</li>
  553. // <li>bookId - An identifier for the book, usually an ISBN.</li>
  554. // <li>pageCount - The number of pages in the book.</li>
  555. // <li>publishedYear - The year of publication.</li>
  556. // </ul>
  557. // The query accepts one parameter: text - The string to search for
  558. _type: "books",
  559. _attributes: ["title", "titleNoFormatting", "authors", "url", "unescapedUrl", "bookId",
  560. "pageCount", "publishedYear"],
  561. _aggregatedAttributes: { }
  562. });
  563. dojo.declare("dojox.data.GoogleImageSearchStore", dojox.data.GoogleSearchStore,{
  564. // summary:
  565. // A data store for retrieving search results from Google.
  566. // The following attributes are supported on each item:
  567. // <ul>
  568. // <li>title - The image title in HTML format.</li>
  569. // <li>titleNoFormatting - The image title in plain text</li>
  570. // <li>url - The URL for the image</li>
  571. // <li>unescapedUrl - The URL for the image, with URL escaping. This is often more readable</li>
  572. // <li>tbUrl - The URL for the image thumbnail</li>
  573. // <li>visibleUrl - A shortened version of the URL associated with the result, stripped of a protocol and path</li>
  574. // <li>originalContextUrl - The URL of the page containing the image.</li>
  575. // <li>width - The width of the image in pixels.</li>
  576. // <li>height - The height of the image in pixels.</li>
  577. // <li>tbWidth - The width of the image thumbnail in pixels.</li>
  578. // <li>tbHeight - The height of the image thumbnail in pixels.</li>
  579. // <li>content - A snippet of information about the image, in HTML format</li>
  580. // <li>contentNoFormatting - A snippet of information about the image, in plain text</li>
  581. // </ul>
  582. // The query accepts one parameter: text - The string to search for
  583. _type: "images",
  584. _attributes: ["title", "titleNoFormatting", "visibleUrl", "url", "unescapedUrl",
  585. "originalContextUrl", "width", "height", "tbWidth", "tbHeight",
  586. "tbUrl", "content", "contentNoFormatting"],
  587. _aggregatedAttributes: { }
  588. });
  589. }