PlaceView.js 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219
  1. /*
  2. * PlaceView is used to display the details of single place item
  3. *
  4. * Place view is otherwise straightforward, but reviews are loaded
  5. * not until rest of the page is first rendered
  6. *
  7. */
  8. qype.views.PlaceView = Class.create(View, {
  9. // Define HTML templates
  10. templates: {
  11. details: new Template('<div class="details">'+
  12. ' <div class="image">#{displayimage}</div>'+
  13. ' <div class="info">'+
  14. ' <div class="name">#{title}</div>'+
  15. ' <div class="address">#{displayaddress}</div>'+
  16. ' <div class="button map" onclick="EventManager.publish({name:\'mapLinkClicked\'})">Map</div>'+
  17. ' <div class="distance">#{distance}</div>'+
  18. ' <div class="rating">#{displayrating}</div>'+
  19. ' <div class="functions">'+
  20. ' <div class="button call">#{displaycallto}</div>'+
  21. ' <div class="button url">#{displayurl}</div>'+
  22. ' </div>'+
  23. ' <div class="bar">'+
  24. ' <span class="text">Information</span>'+
  25. ' </div>'+
  26. ' <div class="hours">'+
  27. ' <div class="icon"></div>'+
  28. ' <div class="data">'+
  29. ' <div class="subject">Opening hours</div>'+
  30. ' <div class="text">#{displayopeninghours}</div>'+
  31. ' </div>'+
  32. ' </div>'+
  33. ' <div class="bar">'+
  34. ' <span class="text">Reviews</span>'+
  35. ' </div>'+
  36. ' <div id="placeReviews" class="reviewContainer"></div>'+
  37. ' </div>'+
  38. '</div>'),
  39. review: new Template('<div class="review">'+
  40. ' <div class="icon"></div>'+
  41. ' <div class="data">'+
  42. ' <div class="subject" id="#{idSummary}" onclick="this.toggle(); util.el(\'#{idFullText}\').toggle()">#{summary}</div>'+
  43. ' <div class="fullText" id="#{idFullText}" onclick="this.toggle(); util.el(\'#{idSummary}\').toggle()" style="display: none">#{fullText}</div>'+
  44. ' <div class="rating">#{stars}</div>'+
  45. ' </div>'+
  46. '</div>')
  47. },
  48. // Function to generate HTML from template and the given place data
  49. constructPlaceHtml: function() {
  50. if(this.data.place) {
  51. var place = new qype.models.PlaceModel(this.data.place, this.engine.getContentLang());
  52. var placedata = place.data;
  53. placedata.displayimage = placedata.image ? "<img src='" + place.getImageUrl("large") + "' class='main' />" : "";
  54. if(placedata.address) placedata.displayaddress = '<div class="line">'+placedata.address.housenumber+" "+placedata.address.street+'</div>' +
  55. '<div class="line">'+placedata.address.postcode+" "+placedata.address.city+'</div>';
  56. if(placedata.opening_hours) placedata.displayopeninghours = placedata.opening_hours.gsub("\n","<br />");
  57. if(!placedata.opening_hours) placedata.displayopeninghours = "Not available";
  58. placedata.distance = this.distance || "- " + qype.str.unit_km;
  59. placedata.displayrating = '<div class="stars'+placedata.average_rating+'"></div>' + place.getReviewsStr();
  60. if(placedata.phone) placedata.displaycallto = '<a href="tel:' + placedata.phone + '" onclick="window.widget.openUrl(\'tel:' + placedata.phone + '\')">' + qype.str.place_call + ' (' + placedata.phone + ')</a>';
  61. if(placedata.url) placedata.displayurl = '<a href="" onclick="window.widget.openURL(\'' + placedata.url + '\'); return false; ">' + qype.str.place_open_www + '</a>';
  62. var template = this.templates.details;
  63. return template.evaluate(placedata);
  64. }
  65. return "";
  66. },
  67. // Function to generate review HTML from the review template and the given JSON data
  68. constructReviewsHtml: function() {
  69. if(this.data.placeReviews) {
  70. var arr = [];
  71. var t = this.templates.review;
  72. var review = undefined;
  73. var reviews = this.data.placeReviews;
  74. for(var i = 0, len = reviews.length; i < len; i++) {
  75. review = reviews[i].review;
  76. arr.push(t.evaluate({
  77. summary: "<p>" + review.summary + "</p>",
  78. fullText: review.content_xhtml,
  79. idSummary: review.id + "-summary",
  80. idFullText: review.id + "-fullText",
  81. stars: '<div class="stars' + review.rating + '"></div>'
  82. }));
  83. }
  84. if(reviews.length == 0) {
  85. return "<p>" + qype.str.place_no_reviews + "</p>";
  86. }
  87. else {
  88. return arr.join("");
  89. }
  90. }
  91. return "";
  92. },
  93. initialize: function($super, id) {
  94. // start with super initialize
  95. $super(id);
  96. var content = new Snippet("placeContent");
  97. // Create progress->onData mechanism to display loading while content is rendered
  98. content.onDefault.template.push('<div class="progress"></div>');
  99. content.onData.template.push({
  100. fn: this.constructPlaceHtml,
  101. base: this
  102. });
  103. content.onData.doUse = function() {return content.data.place !== undefined;};
  104. // Same as above
  105. var reviews = new Snippet();
  106. reviews.onDefault.template.push('<div class="progress"></div>');
  107. reviews.onData.template.push({
  108. fn: this.constructReviewsHtml,
  109. base: this
  110. });
  111. reviews.onData.doUse = function() {return reviews.data.placeReviews !== undefined;};
  112. // Register the snippets for the view
  113. this.registerSnippets({
  114. content: content,
  115. reviews: reviews
  116. });
  117. // Register subscribes (button click events)
  118. this.registerSubscribes([
  119. {
  120. eventName: "mapLinkClicked",
  121. callback: this.onMapLinkClick,
  122. context: this
  123. }
  124. ]);
  125. },
  126. // Launch map view when map button is clicked
  127. onMapLinkClick: function() {
  128. this.engine.activateView("mapView",{placedata:this.data.place});
  129. },
  130. build: function($super, params) {
  131. $super(params);
  132. if(!this.data.place) {
  133. this.getPlaceData();
  134. }
  135. },
  136. render: function($super, params) {
  137. if (params.placeid && (params.placeid != this.placeId)) {
  138. this.placeId = params.placeid;
  139. this.distance = params.distance;
  140. this.data.place = undefined;
  141. this.data.placeReviews = undefined;
  142. this.snippets.content.data.place = undefined;
  143. this.snippets.content.data.placeReviews = undefined;
  144. $super(params);
  145. }
  146. else {
  147. $super(params);
  148. // This "child snippet" needs to be redrawn manually here
  149. this.snippets.reviews.setDom("placeReviews");
  150. this.snippets.reviews.rewrite();
  151. }
  152. },
  153. getPlaceData: function() {
  154. qype.API.get("places", {
  155. "onSuccess": this.onGetPlaceData.bind(this),
  156. "onFailure": this.onFailure.bind(this)
  157. }, this.placeId);
  158. },
  159. onGetPlaceData: function(response) {
  160. util.log("{PlaceView.onGetPlaceData} start");
  161. this.data.place = response.responseJSON.place;
  162. this.snippets.content.data.place = this.data.place;
  163. this.snippets.content.rewrite();
  164. // Init a "child" snippet and attach it to the DOM. It can not be done
  165. // earlier since the DOM is surely available only now!
  166. this.snippets.reviews.setDom("placeReviews");
  167. this.snippets.reviews.rewrite();
  168. this.getPlaceReviews();
  169. },
  170. onFailure: function(response) {
  171. util.log("{PlaceView.onFailure}: start, response = ");
  172. util.log(response);
  173. },
  174. // Load reviews from Qype API
  175. getPlaceReviews: function() {
  176. util.log("{PlaceView.getPlaceReview}: start");
  177. qype.API.get("places", {
  178. "onSuccess": this.onGetPlaceReviews.bind(this),
  179. "onFailure": this.onFailure.bind(this)
  180. }, this.placeId + '/reviews/' + this.engine.getContentLang());
  181. },
  182. // Handle successful response (reviews JSON) from Qype API
  183. onGetPlaceReviews: function(response) {
  184. util.log("{PlaceView.onGetPlaceReviews} start");
  185. this.data.placeReviews = response.responseJSON.results;
  186. this.snippets.reviews.data.placeReviews = this.data.placeReviews;
  187. this.snippets.reviews.rewrite();
  188. }
  189. });