SC.Menu dynamic positioning with OpenLayers
In one app I needed to allow the user to CTRL-click on an OpenLayers map to popup a tool menu. Since all the rest of the app is Sproutcore based I also wanted the menu to have the same look&feel.
Sproutcore already has a menu view which is called SC.MenuPane. Unfortunately SC.MenuPane can be positioned only relatively to another SC.View, but what if I want to position the menu exactly where I clicked on the map?
The solution turns out to be pretty simple and requires us to override only one MenuPane method.
The method is positionPane and can be overridden at definition time by adding it to the mixin as done below (gotta love javascript, huh?):
the code for the OpenLayers control that pops-up the menu is the following:
Sproutcore already has a menu view which is called SC.MenuPane. Unfortunately SC.MenuPane can be positioned only relatively to another SC.View, but what if I want to position the menu exactly where I clicked on the map?
The solution turns out to be pretty simple and requires us to override only one MenuPane method.
The method is positionPane and can be overridden at definition time by adding it to the mixin as done below (gotta love javascript, huh?):
Maps.openLayersController.menuPane: SC.MenuPane.create({ layout: {width: 120}, itemHeight: 25, items: [ { title: '_geocode'.loc(), icon: 'http://maps.gstatic.com/favicon.ico', action: "geocode" }, { title: '_streetview'.loc(), icon: 'icon-streetview-16', action: "streetview" } ], /** @private The ideal position for a picker pane is just below the anchor that triggered it + offset of specific preferType. Find that ideal position, then call fitPositionToScreen to get final position. If anchor is missing, fallback to center. */ positionPane: function(useAnchorCached) { useAnchorCached = useAnchorCached && this.get('anchorCached'); var anchor = useAnchorCached ? this.get('anchorCached') : this.get('anchorElement'), layout = this.get('layout'); if ( anchor && anchor.x && anchor.y ) { this.adjust({ width: layout.width, height: layout.height, left: anchor.x, top: anchor.y }); // if no anchor view has been set for some reason, just center. } else { this.adjust({ width: layout.width, height: layout.height, centerX: 0, centerY: 0 }); } this.updateLayout(); return this; } }),
the code for the OpenLayers control that pops-up the menu is the following:
// click control for geocoding and street view var clickControl = new OpenLayers.Control.ModClick( { onClick: function(evt){ // check that CTRL is pressed while clicking if(evt.ctrlKey) { Maps.openLayersController.menuPane.popup({x:evt.x, y:evt.y}); } } } );