GoogleSearchStore.js 23 KB

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