views:

325

answers:

1

The init() is able to use the parameter passed to it in this example:

 <body onload="init(this);">

testdOnChange() in this example uses a more complicated technique with XSLT generate-id():

  <testd:test
    testd_id="TESTD_ID_id0x03cc1988"
    testd_on_load="testdOnChange(testdGetElementById('TESTD_ID_id0x03cc1988'));"
    />

Is there a more direct technique available?

XML code http://emle.sourceforge.net/emle020000/testd1.xml:

<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet href="testd1.xsl" type="text/xsl"?>
<emle xmlns="http://emle.sourceforge.net/emle020000" />

XSLT code http://emle.sourceforge.net/emle020000/testd1.xsl:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:emle="http://emle.sourceforge.net/emle020000" xmlns:testd="http://emle.sourceforge.net/emle020000/testd" xmlns="http://www.w3.org/1999/xhtml"&gt;
   <xsl:output method="xml" media-type="application/xhtml+svg+mathml" encoding="UTF-8" indent="yes" doctype-public="-//W3C//DTD XHTML 1.0 Transitional//EN" doctype-system="http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"/&gt;

   <xsl:template match="/emle:emle">
      <html>
      <head>
         <script type="text/javascript">
//<![CDATA[
function init(aThis) {alert("init(" + aThis + ")");
  var result = document.evaluate("//@testd_on_load",
    aThis.document, null, XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE, null);
  for (var i=0; i<result.snapshotLength; i++){
    n=result.snapshotItem(i).nodeValue;
    eval(n);
  }
}
function testdGetElementById(aTestdID){alert("testdGetElementById("+aTestdID+")");
  return document.evaluate("//*[@testd_id='" + aTestdID + "']",
      document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).
    singleNodeValue;
  }
function testdOnChange(aNode){alert("testdOnChange("+aNode.nodeName+")");}
//]]>
      </script>
      </head>
      <body onload="init(this);">
      <testd:test>
        <xsl:attribute name="testd_id">TESTD_ID_<xsl:value-of select="generate-id()"/>
        </xsl:attribute>
        <xsl:attribute name="testd_on_load">testdOnChange(testdGetElementById(
        'TESTD_ID_<xsl:value-of select="generate-id()"/>'));</xsl:attribute>
      </testd:test>
      </body>
       </html>
  </xsl:template>
</xsl:stylesheet>
+1  A: 

This is pretty strange looking, but if I understand correctly, you'd like to be able to write your custom event handlers such that they can easily obtain a reference to the element they're attached to. This shouldn't be hard; after all, you're calling the custom handler yourself, so you already know what element it's attached to - you just need to pass that along to the handler itself:

function init(aThis) {
  var result = document.evaluate("//@testd_on_load",
    aThis.document, null, XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE, null);

  for (var i=0; i<result.snapshotLength; i++) {
    var n = result.snapshotItem(i); // attribute node
    var s = n.nodeValue; // script to run
    var e = n.ownerElement; // element for context

    (new Function(s)).call(e); // run script with `this` set to the context node
  }
}

Now you can simplify your event code:

<xsl:attribute name="testd_on_load">testdOnChange(this);</xsl:attribute>
Shog9
In the for loop the nodeValue is the script so change to: var n = result.snapshotItem(i); var s = n.nodeValue; var e = n.ownerElement; Would you modify your answer since I cannot edit it.
C.W.Holeman II
Good catch - I've updated the answer.
Shog9