FlickrStore.js 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295
  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.FlickrStore"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
  7. dojo._hasResource["dojox.data.FlickrStore"] = true;
  8. dojo.provide("dojox.data.FlickrStore");
  9. dojo.require("dojo.data.util.simpleFetch");
  10. dojo.require("dojo.io.script");
  11. dojo.require("dojo.date.stamp");
  12. dojo.require("dojo.AdapterRegistry");
  13. dojo.declare("dojox.data.FlickrStore", null, {
  14. constructor: function(/*Object*/args){
  15. // summary:
  16. // Initializer for the FlickrStore store.
  17. // description:
  18. // The FlickrStore is a Datastore interface to one of the basic services
  19. // of the Flickr service, the public photo feed. This does not provide
  20. // access to all the services of Flickr.
  21. // This store cannot do * and ? filtering as the flickr service
  22. // provides no interface for wildcards.
  23. if(args && args.label){
  24. this.label = args.label;
  25. }
  26. if(args && "urlPreventCache" in args){
  27. this.urlPreventCache = args.urlPreventCache?true:false;
  28. }
  29. },
  30. _storeRef: "_S",
  31. label: "title",
  32. //Flag to allor control of if cache prevention is enabled or not.
  33. urlPreventCache: true,
  34. _assertIsItem: function(/* item */ item){
  35. // summary:
  36. // This function tests whether the item passed in is indeed an item in the store.
  37. // item:
  38. // The item to test for being contained by the store.
  39. if(!this.isItem(item)){
  40. throw new Error("dojox.data.FlickrStore: a function was passed an item argument that was not an item");
  41. }
  42. },
  43. _assertIsAttribute: function(/* attribute-name-string */ attribute){
  44. // summary:
  45. // This function tests whether the item passed in is indeed a valid 'attribute' like type for the store.
  46. // attribute:
  47. // The attribute to test for being contained by the store.
  48. if(typeof attribute !== "string"){
  49. throw new Error("dojox.data.FlickrStore: a function was passed an attribute argument that was not an attribute name string");
  50. }
  51. },
  52. getFeatures: function(){
  53. // summary:
  54. // See dojo.data.api.Read.getFeatures()
  55. return {
  56. 'dojo.data.api.Read': true
  57. };
  58. },
  59. getValue: function(item, attribute, defaultValue){
  60. // summary:
  61. // See dojo.data.api.Read.getValue()
  62. var values = this.getValues(item, attribute);
  63. if(values && values.length > 0){
  64. return values[0];
  65. }
  66. return defaultValue;
  67. },
  68. getAttributes: function(item){
  69. // summary:
  70. // See dojo.data.api.Read.getAttributes()
  71. return [
  72. "title", "description", "author", "datePublished", "dateTaken",
  73. "imageUrl", "imageUrlSmall", "imageUrlMedium", "tags", "link"
  74. ];
  75. },
  76. hasAttribute: function(item, attribute){
  77. // summary:
  78. // See dojo.data.api.Read.hasAttributes()
  79. var v = this.getValue(item,attribute);
  80. if(v || v === "" || v === false){
  81. return true;
  82. }
  83. return false;
  84. },
  85. isItemLoaded: function(item){
  86. // summary:
  87. // See dojo.data.api.Read.isItemLoaded()
  88. return this.isItem(item);
  89. },
  90. loadItem: function(keywordArgs){
  91. // summary:
  92. // See dojo.data.api.Read.loadItem()
  93. },
  94. getLabel: function(item){
  95. // summary:
  96. // See dojo.data.api.Read.getLabel()
  97. return this.getValue(item,this.label);
  98. },
  99. getLabelAttributes: function(item){
  100. // summary:
  101. // See dojo.data.api.Read.getLabelAttributes()
  102. return [this.label];
  103. },
  104. containsValue: function(item, attribute, value){
  105. // summary:
  106. // See dojo.data.api.Read.containsValue()
  107. var values = this.getValues(item,attribute);
  108. for(var i = 0; i < values.length; i++){
  109. if(values[i] === value){
  110. return true;
  111. }
  112. }
  113. return false;
  114. },
  115. getValues: function(item, attribute){
  116. // summary:
  117. // See dojo.data.api.Read.getValue()
  118. this._assertIsItem(item);
  119. this._assertIsAttribute(attribute);
  120. var u = dojo.hitch(this, "_unescapeHtml");
  121. var s = dojo.hitch(dojo.date.stamp, "fromISOString");
  122. switch(attribute){
  123. case "title":
  124. return [ u(item.title) ];
  125. case "author":
  126. return [ u(item.author) ];
  127. case "datePublished":
  128. return [ s(item.published) ];
  129. case "dateTaken":
  130. return [ s(item.date_taken) ];
  131. case "imageUrlSmall":
  132. return [ item.media.m.replace(/_m\./, "_s.") ];
  133. case "imageUrl":
  134. return [ item.media.m.replace(/_m\./, ".") ];
  135. case "imageUrlMedium":
  136. return [ item.media.m ];
  137. case "link":
  138. return [ item.link ];
  139. case "tags":
  140. return item.tags.split(" ");
  141. case "description":
  142. return [ u(item.description) ];
  143. default:
  144. return [];
  145. }
  146. },
  147. isItem: function(item){
  148. // summary:
  149. // See dojo.data.api.Read.isItem()
  150. if(item && item[this._storeRef] === this){
  151. return true;
  152. }
  153. return false;
  154. },
  155. close: function(request){
  156. // summary:
  157. // See dojo.data.api.Read.close()
  158. },
  159. _fetchItems: function(request, fetchHandler, errorHandler){
  160. // summary:
  161. // Fetch flickr items that match to a query
  162. // request:
  163. // A request object
  164. // fetchHandler:
  165. // A function to call for fetched items
  166. // errorHandler:
  167. // A function to call on error
  168. var rq = request.query = request.query || {};
  169. //Build up the content to send the request for.
  170. var content = {
  171. format: "json",
  172. tagmode:"any"
  173. };
  174. dojo.forEach(
  175. [ "tags", "tagmode", "lang", "id", "ids" ],
  176. function(i){
  177. if(rq[i]){ content[i] = rq[i]; }
  178. }
  179. );
  180. content.id = rq.id || rq.userid || rq.groupid;
  181. if(rq.userids){
  182. content.ids = rq.userids;
  183. }
  184. //Linking this up to Flickr is a PAIN!
  185. var handle = null;
  186. var getArgs = {
  187. url: dojox.data.FlickrStore.urlRegistry.match(request),
  188. preventCache: this.urlPreventCache,
  189. content: content
  190. };
  191. var myHandler = dojo.hitch(this, function(data){
  192. if(!!handle){
  193. dojo.disconnect(handle);
  194. }
  195. //Process the items...
  196. fetchHandler(this._processFlickrData(data), request);
  197. });
  198. handle = dojo.connect("jsonFlickrFeed", myHandler);
  199. var deferred = dojo.io.script.get(getArgs);
  200. //We only set up the errback, because the callback isn't ever really used because we have
  201. //to link to the jsonFlickrFeed function....
  202. deferred.addErrback(function(error){
  203. dojo.disconnect(handle);
  204. errorHandler(error, request);
  205. });
  206. },
  207. _processFlickrData: function(data){
  208. var items = [];
  209. if(data.items){
  210. items = data.items;
  211. //Add on the store ref so that isItem can work.
  212. for(var i = 0; i < data.items.length; i++){
  213. var item = data.items[i];
  214. item[this._storeRef] = this;
  215. }
  216. }
  217. return items;
  218. },
  219. _unescapeHtml: function(/*String*/ str){
  220. // summary:
  221. // Utility function to un-escape XML special characters in an
  222. // HTML string.
  223. // str: String.
  224. // The string to un-escape
  225. // returns:
  226. // HTML String converted back to the normal text (unescaped)
  227. // characters (<,>,&, ", etc,).
  228. //TODO:
  229. // Check to see if theres already compatible escape() in
  230. // dojo.string or dojo.html
  231. return str.replace(/&amp;/gm, "&").
  232. replace(/&lt;/gm, "<").
  233. replace(/&gt;/gm, ">").
  234. replace(/&quot;/gm, "\"").
  235. replace(/&#39;/gm, "'");
  236. }
  237. });
  238. dojo.extend(dojox.data.FlickrStore, dojo.data.util.simpleFetch);
  239. var feedsUrl = "http://api.flickr.com/services/feeds/";
  240. var reg = dojox.data.FlickrStore.urlRegistry = new dojo.AdapterRegistry(true);
  241. reg.register("group pool",
  242. function(request){ return !!request.query["groupid"]; },
  243. feedsUrl+"groups_pool.gne"
  244. );
  245. reg.register("default",
  246. function(request){ return true; },
  247. feedsUrl+"photos_public.gne"
  248. );
  249. //We have to define this because of how the Flickr API works.
  250. //This somewhat stinks, but what can you do?
  251. if(!jsonFlickrFeed){
  252. var jsonFlickrFeed = function(data){};
  253. }
  254. }