123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293 |
- /**
- * PlacesView.js defines the view object of the applications main view
- *
- * Places view lists available places nearby
- * Note! We are using this same view also when user has selected
- * some category; when category is selected, the category name is
- * displayed instead of default text 'Nearby places'. Also
- * back button behaviour is different (back goes to categories)
- *
- */
- qype.views.PlacesView = Class.create(View, {
- initialize: function($super, id) {
- $super(id);
- this.currentCategoryName = undefined;
- /* ***************************
- PLACE OF CODE SNIPPET 10.1
- ****************************/
-
- // Create new snippet for the link leading to CategoriesView and bind
- // it to a DOM node.
- var categoriesLink = new Snippet("categoriesLink");
- /* ***************************
- PLACE OF CODE SNIPPET 10.2
- ****************************/
-
- // Add default template
- categoriesLink.onDefault.template.push(qype.str.places_link_to_categories + " >>");
- /* ***************************
- PLACE OF CODE SNIPPET 10.3
- ****************************/
- // Event handlers can be attached directly to the DOM node
- var goToCategories = function() {
- this.engine.activateView("categoriesView");
- }
- categoriesLink.dom.addEventListener("click", goToCategories.bind(this), false);
- // Create new snippet for the header and bind to a DOM node.
- var header = new Snippet("placesHeader");
- // Add default template
- header.onDefault.template.push({
- fn: function() { // Gives the appropriate header string for the view
- return this.currentCategoryName || qype.str.places_header_nearby
- },
- base: this
- });
- /* ***************************
- PLACE OF CODE SNIPPET 11.1
- ****************************/
- // Create new snippet for the actual content and bind to a DOM node.
- var content = new Snippet("placesContent");
- // Add default template
- content.onDefault.template.push("<div class='progress'></div>");
- // Different rendering when there's required data available
- content.onData.template.push({
- fn: this.constructPlacesHtml,
- base: this
- });
- // When to actually use the onData templates?
- content.onData.doUse = function() {
- return content.data.places !== undefined;
- };
- // And finally register all the Snippets to this view
- this.registerSnippets({
- categoriesLink: categoriesLink,
- header: header
- /* ***************************
- PLACE OF CODE SNIPPET 11.2
- ****************************/
- ,
- content: content
- });
- // Register global subscribes
- this.registerSubscribes([
- {
- eventName: "placeClicked",
- callback: this.onItemClick,
- context: this
- },
- {
- eventName: "mapLinkClicked",
- callback: this.onMapLinkClick,
- context: this
- },
- {
- eventName: "locationButtonClicked",
- callback: this.onLocationButtonClick,
- context: this
- }
-
- ]);
- },
- // Templates help separating the JS values and actual HTML content. The templates
- // of Prototype.js are used, even though they can handle only templating of
- // simple data types and not e.g. JS Objects in JSON.
- templates: {
- place: new Template(
- '<div class="item" onclick="EventManager.publish({name:\'#{eventName}\', id:\'#{id}\', distance:\'#{distance}\'})">' +
- ' <div class="image">#{displayImage}</div>' +
- ' <div class="info">' +
- ' <div class="name">#{title}</div>' +
- ' <div class="rating">#{rating}</div>' +
- ' <div class="category">#{categoryName}</div>' +
- ' </div>' +
- ' <div class="distance">#{distance}</div>' +
- '</div>'
- ),
- empty: new Template(
- '<div class="item empty">' +
- ' <div class="name">#{label}</div>' +
- '</div>'
- )
- },
- /**
- * Override the default build to prepare the view as needed.
- */
- build: function($super, params) {
- $super(params);
-
- /* ***************************
- PLACE OF CODE SNIPPET 11.3
- ****************************/
- // Remove the old data and update the snippet. Thus, old content is not shown
- // while retrieving new data, instead the default progress spinner is shown.
- this.snippets.content.data.places = undefined;
- this.snippets.content.rewrite();
- // Params allow showing one single category.
- if(params && params.categoryId && params.categoryName) {
- // If we opened this view via CategoriesView, then do not show the
- // 'Categories' shortcut on the top.
- this.snippets.categoriesLink.dom.hide();
- this.currentCategoryId = params.categoryId;
- this.currentCategoryName = params.categoryName;
- }
- else {
- // By default a shortcut to the CategoriesView is shown.
- this.snippets.categoriesLink.dom.show();
- this.currentCategoryId = undefined;
- this.currentCategoryName = undefined;
- }
- // Start retrieving the data
- this.getPlaces();
- },
- /**
- * @param {Object} evt Holds the event as it was published via the EventManager.
- * See the templates.place from this class.
- */
- onItemClick: function(evt) {
- util.log("{PlacesView.onItemClick} start");
- this.engine.activateView("placeView", {
- placeid: evt.id,
- distance: evt.distance
- });
- },
- // Click handlers take care of click events in the view
- onMapLinkClick: function() {
- console.log("hmm",this.snippets.content.data.places);
- this.engine.activateView("mapView",{placedata:this.snippets.content.data.places});
- },
-
- onLocationButtonClick: function() {
- console.log("Refresh location clicked");
-
- // This launches GPS location request; the functionality is
- // defined in app.js
- qype.refreshLocation();
- },
-
- /**
- * Create the actual content HTML for the retrieved places. Is triggered only
- * if the onData templates are used, see the initialize() method.
- *
- * @return The generated HTML as a string
- */
- constructPlacesHtml: function() {
-
- /* *******************************
- PLACE OF CODE SNIPPET 12.4.1
- ********************************/
-
- var places = undefined;
- if(places = this.snippets.content.data.places) { // Check if there's proper data stored
- places = places.results;
- var t = this.templates.place; // Set the HTML template
- var arr = [];
- var lang = this.engine.getContentLang(); // Get the language set in Engine.js
-
- for(var i = 0; i < places.length; i++) { // loop through the list of places
-
- /* *******************************
- PLACE OF CODE SNIPPET 12.4.2
- ********************************/
-
- var place = new qype.models.PlaceModel(places[i].place, lang); // initialize new PlaceModel object (see PlaceModel.js)
- var data = { // Fill template variables by using the place model
- id: place.getId(),
- title: place.data.title,
- eventName: "placeClicked",
- categoryName: place.getCategoriesStr(),
- distance: place.getDistanceStr(),
- rating: '<div class="stars'+place.data.average_rating+'"></div>' + place.getReviewsStr()
- }
- var placeImage = place.getImageUrl("medium");
- if(placeImage) {
- data.displayImage = '<div style="background-image: url(\''+placeImage+'\');" class="listItem"></div>';
- }
- arr.push(t.evaluate(data)); // Evaluate the template with given data, and add the result HTML into temporary array
- }
- if(places.length === 0) { // Special case: no places availabe
- arr.push(this.templates.empty.evaluate({
- label: qype.str.no_data_available // Use text/HTML string defined in strings.js
- }));
- }
- return arr.join(""); // Return result array (HTML)
- }
- return "";
- },
- /**
- * Start retrieving the needed places via Qype API. Calls the API in
- * asynchronous manner.
- */
- getPlaces: function() {
- var loc = this.engine.getCurrentLocation();
- var params = {};
-
- if(this.currentCategoryId) {
- params.in_category = this.currentCategoryId;
- }
-
- /* *******************************
- PLACE OF CODE SNIPPET 12.3.2
- ********************************/
-
- qype.API.get("positions", {
- "onSuccess": this.onGetPlaces.bind(this),
- "onFailure": this.onFailure
- },
- loc.coords.latitude + "," + loc.coords.longitude + "/places",
- params
- );
- }
-
- /* *******************************
- PLACE OF CODE SNIPPET 12.3.1
- ********************************/
- ,
- /**
- * Gets called if the places were successfully retrieved from the Qype API.
- *
- * @param {Ajax.Response} response Response object as coming from the Prototype.js.
- */
- onGetPlaces: function(response) {
- util.log("{PlacesView.onGetPlaces} start");
- this.snippets.content.data.places = response.responseJSON;
-
- // Handle snippet/DOM updating manually.
- util.depressurizeAll("item");
- this.snippets.header.rewrite();
- this.snippets.content.rewrite();
- util.pressurizeAll("item");
- },
- onFailure: function(response) {
- util.log("{PlacesView.onFailure}: start, response = ");
- util.log(response);
- }
- });
|