Project

Profile

Help

Feature #5142

New <ixsl:add-listener> instruction

Added by Martynas Jusevicius about 1 month ago. Updated about 1 month ago.

Status:
New
Priority:
Normal
Assignee:
-
Category:
IXSL extensions
Sprint/Milestone:
-
Start date:
2021-10-23
Due date:
% Done:

0%

Estimated time:
Applies to JS Branch:
2
Fix Committed on JS Branch:
2
Fixed in JS Release:
SEF Generated with:
Platforms:
Company:
-
Contact person:
-
Additional contact persons:
-

Description

Hi. I think there is a generic use case that shows up especially when integrating Saxon-JS with JS libraries. For example, with Google Maps one needs to use this to add an onlick listener for a marker:

  marker.addListener("click", () => {
    infowindow.open({
      anchor: marker,
      map,
      shouldFocus: false,
    });
  });

It requires a JS callback function, which is anonymous () in this case. I would like to use IXSL to handle the marker onclick event instead.

The native IXSL way would be:

<xsl:template match="a[@class = 'marker']" mode="ixsl:onclick">

but the problem is that the DOM generated by Google Maps, including marker IDs or class names, cannot be relied upon. So the match pattern approach does not really work.

I propose a second, generalized mechanism to handle events using a new extension instruction <ixsl:add-listener>. It could be used like this:

<ixsl:add-listener name="click" object="$marker">
    <xsl:call-template name="onMarkerClick"/>
</ixsl:add-listener>

<xsl:template name="onMarkerClick" mode="ixsl:onclick">
    <xsl:variable name="event" select="ixsl:event()"/> <!-- MapMouseEvent -->
    <xsl:variable name="lat-lng" select="ixsl:get(ixsl:event(), 'latLng')"/>
    ...
</xsl:template>

If the native match/mode/ approach can be used instead, one could replace the name="onMarkerClick" with mode="ixsl:onclick" and the same template body should still work.

The <ixsl:add-listener> call would translate to this pseudo-JS:

marker.addListener('click', (event) => { SaxonJS.callTemplate('onMarkerClick', event); });

History

#1 Updated by Martynas Jusevicius about 1 month ago

I realized just now that Google Maps' google.maps.MVCObject.addListener() is not the same as EventTarget.addEventListener(), so maybe this approach is not generic after all...

#2 Updated by Martynas Jusevicius about 1 month ago

So I got the following working, but I cannot see how it could be generalized since addListener() is GMaps-specific :/ If the addGoogleMapsListener could also be implemented in IXSL, it could at leaset be used to create a native GMaps API wrapper for Saxon-JS.

var addGoogleMapsListener = function(object, type, options, templateName, params)
{
    object.addListener(type, 
        function (event)
        {
            SaxonJS.transform({
                "stylesheetLocation": contextUri + "static/com/atomgraph/linkeddatahub/xsl/client.xsl.sef.json",
                "initialTemplate": templateName,
                "templateParams": Object.assign(params, { "event": event })
            });
        },
        options);
};
<xsl:variable name="params" select="map{ 'url': string(@rdf:about) }" as="map(xs:string, xs:string)"/>
<xsl:variable name="params-obj" select="ixsl:call(ixsl:window(), 'JSON.parse', [ $params => serialize(map { 'method': 'json' }) ])"/>
<xsl:sequence select="ixsl:call(ixsl:window(), 'addGoogleMapsListener', [ $marker, 'click', (), 'onInfoWindowLoad', $params-obj ])[current-date() lt xs:date('2000-01-01')]"/>
<xsl:template name="onInfoWindowLoad">
    <xsl:param name="event"/>
    <xsl:param name="url" as="xs:string"/>
    
    <xsl:sequence select="ixsl:call(ixsl:window(), 'alert', [ 'onInfoWindowLoad' ])"/>
</xsl:template>

#3 Updated by Martynas Jusevicius about 1 month ago

onInfoWindowLoad in all the examples should have been onMarkerClick...

Please register to edit this issue

Also available in: Atom PDF Tracking page