dhtmlopenlaszlolzx

OpenLaszlo <html> tag / iframe integration and JavaScript calls


I am trying to call one javascript function present in the html data that i am inserting but i am always getting an error getLoaded is not a method. I have attached the code snippet. What is wrong ?

<canvas width="100%" height="100%" >
        <simplelayout axis="y" spacing="2"/>
            <button>Set HTML
                <handler name="onclick">
                    <![CDATA[
                    if (canvas.main) {
                        canvas.main.setAttribute('html', '<html><head><style type="text/css">body {background-color: #ffffff;}</style><script>function getLoaded(){ return document.images.length;}</script></head><body><img id="imageTag" ></img></body></html>');
                    }
                    ]]>
                </handler>
            </button> 

               <button>test
                <handler name="onclick">
                    <![CDATA[
                    if (canvas.main) {
                        var del = new LzDelegate(this,'handlerFunc');
                        canvas.main.callJavascript('getLoaded',del);
                    }
                    ]]>
                </handler>
            </button> 
            <method name="handlerFunc" args="retVal">
                console.log("handlerFunc", retVal);
            </method>

        <html name="main" x = "50" y="50" width="600" height="400" >
            <handler name="oninit">
                this.bringToFront();
            </handler>

        </html>

</canvas>   

Solution

  • Here is a solution which works for the both the SWF10 and DHTML runtime. I've tested with IE 9, Firefox and Chrome.

    There are two problems with your code:

    1) The HTML snippet you are assigning to the @html attribute of the <html> tag should not contain a full HTML document structure. Here is the JavaScript from the iframemanager.js library (part of OpenLaszlo) which is used to assign the HTML snippet to the iFrame:

    ,setHTML: function(id, html) { 
        // must be called after the iframe loads, or it will be overwritten
        if (html) {
            var win = lz.embed.iframemanager.getFrameWindow(id);
            if (win) {
                win.document.body.innerHTML = html;
            }
        }
    }
    

    As you can see, the value of the html parameter is assigned to the innerHTML of the body element. Therefore it's sufficient to only include the body of the HTML document you are generating.

    2) If you want to add JavaScript sections to an iFrame, you cannot inline those into the HTML code you want to assign to the document, but have to create a 'script' element as you can see in the full example below. If you want to support the SWF runtime as well, the most efficient way is to create a small external JavaScript function has a helper function as shown below.

    There are two files I'm creating for this solution. The LZX file, and an external JavaScript file called iFrameHelperFunction.js.

    Here is a modified version of your LZX file:

     <canvas width="100%" height="100%" >
    
      <wrapperheaders>
        <script type="text/javascript" src="iFrameHelperFunction.js"></script>
      </wrapperheaders>
    
      <simplelayout axis="y" spacing="2"/>
    
      <button>Set HTML
         <handler name="onclick">
         <![CDATA[
            if (canvas.main) {
              // Create the HTML content; do not include <html><head><body> structure here,
              // since setting the 'html' attribute of an OpenLaszlo <html> tag will set
              // the innerHTML property of the iFrame's document.body.
              var innerHTML = '<style type="text/css">body {background-color: #ff0000;}</style>'
                       + '<img id="imageTag" src="https://www.google.com/images/srpr/logo3w.png"></img>',
                  jsCode = "function getLoaded() { alert('inside getLoaded()'); return 'getLoaded was called'; }";
              canvas.main.setAttribute('html', innerHTML);
              lz.Browser.callJS('addJavaScriptToFrame("' + canvas.main.iframeid + '", ' + jsCode + ')');
            }
            ]]>
        </handler>
      </button>
    
      <button>test
        <handler name="onclick">
        <![CDATA[
          if (canvas.main) {
            var del = new LzDelegate(canvas, 'handlerFunc');
            canvas.main.callJavascript('getLoaded', del);
          }
        ]]>
        </handler>
      </button>
    
      <method name="handlerFunc" args="retVal">
        Debug.info("handlerFunc", retVal);
      </method>
    
      <html name="main" x = "50" y="50" width="600" height="200" >
        <handler name="oninit">
          this.bringToFront();
        </handler>
      </html>
    
    </canvas>
    

    First, I'm adding my custom JavaScript file to the page:

      <wrapperheaders>
        <script type="text/javascript" src="iFrameHelperFunction.js"></script>
      </wrapperheaders>
    

    Then the HTML snipped for the iFrame is set, similar to your code. But any JavaScript which is added to iFrame HTML page has to be added using a helper function addJavaScriptToFrame defined in iFrameHelperFunction.js:

    function addJavaScriptToFrame(frameId, jsCode) {
        var iframeWin = lz.embed.iframemanager.getFrameWindow(frameId);
            doc = iframeWin.document;
    
        // Scripts can not be inlined in HTML snippets, but must be created through JavaScript
        var scriptEl = doc.createElement('script');
        // The JavaScript function or code you want to add
        scriptEl.text = jsCode;
    
        // Append the script to the head of the iFrame document
        doc.firstChild.appendChild(scriptEl);
    }
    

    The call to add the JavaScript to the iFrame in the LZX file:

      lz.Browser.callJS('addJavaScriptToFrame("' + canvas.main.iframeid + '", ' + jsCode + ')');
    

    Click the "Set HTML" button to set the content of the frame, and then click the "test" button to make the call to the getLoaded() function inside the iFrame.

    Example OpenLaszlo app with iFrame content set dynamically through JavaScript