Issue using enyo inside of leaflet popup

I'm trying to use enyo in conjunction with leaflet. I am attempting to put a leaflet button inside of a leaflet popup, however the ontap callback never fires. Below I have included the code that instantiates the button. Any ideas on what I might be doing wrong?

As an aside, there had been an issue with click event propagation being stopped by leaflet popups, but it has since be resolved.
var mark = new L.marker([44.974998, -93.269906]).addTo(this.map);
var popDiv = L.DomUtil.create("div");
var pop = new L.popup();
mark.bindPopup(pop);

enyo.kind({
	kind: enyo.Button,
	name: "thefoobutton",
	content: "foo",
	ontap: function(){alert("The foo button was tapped");},
});
var button = new thefoobutton({owner: this});
button.renderInto(popDiv);
pop.setContent(popDiv);

Comments

  • edited June 2013
    The problem here is that ontap is not a function, it accepts a string which Enyo then binds to a function by that name on the owner element.

    What you could, instead, do is:
    var button = new enyo.Button({
    	content: "foo",
    	owner: this,
    	ontap: "myEventHandler"
    });
    button.renderInto(popDiv);
    pop.setContent(popDiv);
    That, for the record, is assuming your above code is being called from inside an Enyo application.

    For example: http://jsfiddle.net/arthurthornton/5xQvn/
  • Ah, I see. I tried making that change, but still no luck. I also made a fiddle demonstrating the issue and with more complete code.

    http://jsfiddle.net/pwnosaurus/YPqpm/
  • Usually you do NOT use renderInto for any controls except the top-level application control. Rendering is something the framework handles, not the application code. I can see why this might be different, due to wanting to integrate with this 3rd-party code.

    I think one of the problems here is that you're rendering into a div that's not on the page, then using the setContent call from the Leaflet library to put it into that object. Enyo doesn't generally put DOM event handlers on the individual object is renders, instead setting up page-wide handlers that get the event when it bubbles up to the document.body. It then interprets the events and pushed them back down to the rendered controls according to its own dispatch scheme. Since you've put the button into the Leaflet widget, it's likely intercepting the mousedown/mouseup events and never letting Enyo see them.
  • It seems that this is the only way to get things into the leaflet popup using their APIs, do you have a suggestion about how to fix this? Is there something in enyo that _would_ be the proper way to do this?

    If not, is there functionality to wrap a ContextualPopup around an arbitrary div?
  • Also, is there any way to test if the enyo dispatcher has received the mouseup/mousedown events?
  • If you use enyo.Popup instead of the Leaflet popup and intercept the click using thier APIs to open the popup, I'd expect things would work, as enyo creates floating popups on a separate top-level layer.
  • To test that, you can put a breakpoint on gesture.js's down method.
  • Thank you for the help guys. I have implemented a workaround that puts a click handler on the leaflet popup which directly bubbles an ontap event on the button.

    Code below, and in action here http://jsfiddle.net/pwnosaurus/uqcJJ/4/
    enyo.kind({
        name: "mapContainer",
        rendered: function(){
            this.inherited(arguments);
            
            //Initialize the map
            this.map = L.map(this.id).setView([44.981313, -93.266569],13);
    		L.tileLayer("http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png",
                {attribution: "Map data © OpenStreetMap contributors"}
            ).addTo(this.map);
            
            //Initilize the marker and popup
            var mark = new L.marker([44.981014, -93.270520]).addTo(this.map);
    		var popDiv = L.DomUtil.create("div");
    		var pop = new L.popup();
    		mark.bindPopup(pop);
    
            //Initilize the enyo button and control
    		var ctrl = new enyo.Control({
    			myHandler: function(){
    				alert("The foo button was tapped");
    			}
    		});
            var button = new enyo.Button({
                name: "thefoobutton",
                content: "foo",
                ontap: "myHandler",
                owner: ctrl,
            });
            
            //Add click handler
            //inspired by https://github.com/NBTSolutions/Leaflet/commit/466c0e3507cf0934a9d1441af151df2324a4537b#L2R129
            function forward(e){
                if (window.enyo && window.enyo.$ && e.srcElement && e.srcElement.id && window.enyo.$[e.srcElement.id]){
                        window.enyo.$[e.srcElement.id].bubble("ontap", e);
                }
            }
            this.map.on("popupopen", function (e){
                if (! e.popup.hasForwarder){ //Note: this check may not be needed. The L.DomEvent.on() seems to handle multiple adds of named functions
                    L.DomEvent.on(pop._contentNode, "click", forward, this);
                    e.popup.hasForwarder = true;
                }
            }, this);
            
            
            button.renderInto(popDiv);
    		pop.setContent(popDiv);
            mark.openPopup();
        },
        
    });
    mapCont = new mapContainer();
    mapCont.renderInto(document.body);
Sign In or Register to comment.