Updates to EveryMarathon for WebOS - TouchPad


[NOTE: 7/5/2011 - changed enyo.hitch() in source code to enyo.bind(), which is documented. They’re the same function in Enyo 0.1]

Now that I actually have a device to run the app on, I’ve found a few things I’d needed to fix with version 1.0.0 of EveryMarathon:

  1. The scrollers for individual states weren’t moving back into place when I refreshed their contents - you have to do that manually with the $.scroller.scrollIntoView() method

  2. In Portrait mode, the app looked terrible - what I thought would fix that would be to set a minimum width on the details pane, but that doesn’t seem to work. I need to go back to this, but for now, I hard-coded the app to only work in “right” landscape orientation - what’s annoying about this is that if you are holding it upside down but in landscape, the app will launch upside down…this is on the must fix list.

  3. The month displayed in the details view was off by one - totally my bug, nothing to do with WebOS - easy fix.

  4. I got my map working, with clickable infoboxes! This was way more trouble than I thought it would be, because I was overthinking things. Microsoft supplies the Bing Maps V7 AJAX map control with a Pushpin object and an Infobox object, but the two aren’t connected. I took advantage of the fact that everything is a Javascript object, so I can just define new properties on my Pushpin objects and Infobox objects to maintain the state I need to. Obviously I’d prefer it if Microsoft provided the solution, or if HP had a nice wrapper for this for Enyo, but until then, I’ll use my custom Enyo MapView kind. Here’s the source code:

enyo.kind({
  name: "EveryMarathon.MapView",
  kind: "VFlexBox",
  events: {
      onBack: "",
      onPinOnclick: "",
      onInfoboxOnclick: "",
      onSelectItem: ""

  },
  published: {
      url: "",
      visibleInfobox: "",
      selectedItemIndex: ""
  },
  components: [
      {kind: "Map", name:"mapContainer", zoom: 6, flex:1, credentials: BING\_API\_CREDENTIALS},
	  {kind: "Toolbar", components: [
		{kind: enyo.GrabButton},
		{flex: 1},				  
			{caption: "Done with Map", onclick: "dismiss"},
			{flex: 1},				  

	  ]}	      
	],
  showRacesOnMap: function(races) {
	
	this.$.mapContainer.clearAll();
	
  	var inOptions = null;
  	var locations = \[\];
  	for (var i = 0; i< races.length; i++)
  	{
  		var latitude = races\[i\].latitude;
  		var longitude = races\[i\].longitude;
		var location = new Microsoft.Maps.Location(latitude, longitude);
		locations.push(location)
		var pushpin = new Microsoft.Maps.Pushpin(location, inOptions);
		var infobox = new Microsoft.Maps.Infobox(location, {htmlContent: "

" + races\[i\].title + "

",visible:false, offset:new Microsoft.Maps.Point(0,35)});
		infobox.raceIndex = i;
		pushpin.infobox = infobox;
		this.$.mapContainer.map.entities.push(infobox);
		this.$.mapContainer.map.entities.push(pushpin);
    	Microsoft.Maps.Events.addHandler(pushpin, 'click', enyo.bind(this, "doPinOnclick"));
    	Microsoft.Maps.Events.addHandler(infobox, 'click', enyo.bind(this, "doInfoboxOnclick"));
	}
	var bestview = Microsoft.Maps.LocationRect.fromLocations(locations);
	this.$.mapContainer.map.setView({bounds:bestview });
	this.$.mapContainer.setZoom(6);
  },
  dismiss: function() {  
      this.doBack();
  },    
  doPinOnclick: function(inSender) {
	var pin = inSender.target;
	if (pin)
	{
		var infobox = pin.infobox;
		if (infobox)
		{
			if (this.getVisibleInfobox() != "")
			{
				this.getVisibleInfobox().setOptions({visible:false});
			}
  			this.setVisibleInfobox(infobox);
  			infobox.setOptions({visible:true});
		}
	}
  },
  doInfoboxOnclick: function(insSender) {
  	this.setSelectedItemIndex(insSender.target.raceIndex);
    	this.doSelectItem(this);
  }
});