Login Register

executeScripts: how to in v9?

The executeScripts property has been removed from Dojo 9.

Could you provide an example of how to obtain the same result?

Thanks

Luca

I'd like to know as well

The porting guide mentions something about ... but I haven't seen an example using that in the tests.
Anyone?

--jamesholder

Look at the dojo.parser test

Here:
http://archive.dojotoolkit.org/nightly/dojotoolkit/dojo/tests/parser.htm...

It is limited to connecting scriptblocks to widgets, it comes from dojo.parser and has nothing to do with dijit.layout.ContentPane.

If you want a more 0.4 like thing, look in a previous thread in this forum.

The iavascript is inside the loaded content

I could not find the solution in old posts. Can you point me to that?

blind luck

alex posted this oneline on another thread somewhere. execute scripts on a domNode: node.
dojo.query("script", node).forEach(function(n){ eval(n.innerHTML); });
it may help not to be buried in a long discussion about 0.4 vs 0.9 ... so give it a whack.

Thanks dante I'll give it

Thanks dante

I'll give it try. It doesn't solve the case of included scripts though

Thanks to ...

the help of dante and alex this is more or less a possible solution: [edited for highlighting/styleguideness by dante]
if(!dojo._hasResource["dijit.layout.ContentPaneExt2"])
{
        dojo._hasResource["dijit.layout.ContentPaneExt2"] = true;
        dojo.provide("dijit.layout.ContentPaneExt2");
        dojo.require("dijit.layout.ContentPane");
        dojo.declare ("dijit.layout.ContentPaneExt2", dijit.layout.ContentPane,null, {
                executeScripts: false,
                scriptSeparation: true,
                scriptScope: null,
               
                postCreate: function() {
                        if(this.parseOnload){ this.parseOnLoad = false; this._parseOnLoad = true; }
                        if(this.executeScripts){
                                dojo.connect (this,"onLoad",this,"_executeScripts");
                        }
                },
                _executeScripts:function (){
                        var self = this;
                        self.code = [];
                        var scripts = dojo.query ("script", this.domNode);
                       
                        for(var i = 0; i < scripts.length; i++){
                                var src = scripts[i].getAttribute ("src");
                                if(src){
                                        dojo.xhrGet ({
                                                url: src,
                                                sync: true,
                                                preventCache:  (this.preventCache || this.refreshOnShow),
                                                handle: function (response, ioArgs){
                                                        if(response instanceof Error){
                                                                self._onError.call (self, 'Download', response);
                                                        }else{
                                                                self.code.push (response);
                                                        }
                                                }
                                        });
                                }else{
                                        self.code.push (scripts[i].innerHTML);
                                }
                        }
                        var code = self.code.join (";");
                        try {
                                if (this.scriptSeparation){
                                        delete this.scriptScope;
                                        this.scriptScope = new (new Function("_container_", code + "; return this;"))(self);
                                }else{
                                        var djg = dojo.global;
                                        if (djg.execScript){
                                                djg.execScript(code);
                                        }else{
                                                var djd = dojo.doc;
                                                var sc = djd.createElement("script");
                                                sc.appendChild(djd.createTextNode(code));
                                                (this.containerNode || this.domNode).appendChild(sc);
                                        }
                                }
                        }catch (e){
                                e.text = "Error running scripts from content:\n" + e.description;
                                self._onError.call (self, 'Content', e);
                        }
                }
        });
}

Typo

Thanks for that code, exactly what I required. I would appreciate to find it in later "official" dojo versions...

Just a little hint: In the first line of the postCreate method there is a typo: addOnload should have a capital L, shouldn't it?

Martin

Dante may help here

That part of code was contributed by Dante. This is his comment:

as an aside, i did the 'parseOnLoad' borking in my example because if you dojo.require() something in a script tag in a remote ContentPane, it tries to parse the body first, then execute the scripts. that workaround parses if you wanted to parse, after it loads stuff in via script tags.

It also seems to break in IE6 for some reason (i suspect async dojo.require() and IE not being fast enough to pull in a bunch of stuff before the code get's executed)

yes

the first parseOnLoad should be mixed case all the way through. it just over-rides the old old one, but keeps its value in mind.

the ie6 issue still applies.

but I can't see...

...how this line with _parseOnLoad works, because _parseOnLoad is assigned but never used, is it?

Thanks for a hint,
Martin

yes his example removed the

yes his example removed the bit (or maybe i never showed it) but the seqeuence was:

if (this.parseOnLoad) { this._parseOnLoad = true; this.parseOnLoad=false; }
{{ .. later .. (in _executeScripts) }}

{{ eval(n.innerHTML); }}
if (this._parseOnLoad) { dojo.parser.parse(this.domNode); }

it was inteded to store the orig state of a user's parseOnLoad var, and defer its usage until after page contentes (scripts) have been eval'd. but yes, it's inclusion in the code above is bloaty. (if only by a line or two)

could you post the complete method?

Thanks for the answer, but I cannot find the eval(n.InnerHTML), so I do not know where to paste the line of code for parsing the domNode.
Could you perhaps post the complete method? Or ist the complete ContentPaneExt2 file available anywhere?

Martin

This was the original code

This was the original code from Dante:

dojo.declare("my.contentPane",dijit.layout.ContentPane,null,{
   executeScripts: true,
   postCreate: function() {
               if (this.parseOnload) { this.parseOnLoad = false; this._parseOnLoad = true; }
               if (this.executeScripts) {
                       dojo.connect(this,"onLoad",this,"_executeScripts");
               }
   },
   _executeScripts: function() {
          dojo.query("script",this.domNode).forEach(function(n){
                        eval(n.innerHTML);
          },this);
          if (this._parseOnLoad) { dojo.parser.parse(this.domNode); }
   }
});

The above code executes the scripts that are in the loaded file, but does not executes included scripts in the form  .
This is the reason why I went back to the 0.4 code and replaced the _executeScripts method. Doing so deleted the line in question.
Please note that I named this widget "dijit.layout.ContentPaneExt2" only because I was doing some fast copy&paste, nothing to do with the Dojo project.

there is no 'complete'

there is no 'complete' method, so ymmv ... mumme is working on porting dojox.layout.ContentPane as we speak, so it will land in SVN trunk soon enough. His version will probably fix some of the issues i am encountering with my little hack (which works, but not very fault-tolerant) ...

dojox.layout.ContentPane ready for test

>His version will probably fix some of the issues i am encountering with my
>little hack (which works, but not very fault-tolerant) ...
Not necessarily :-)

I just checked in a enhanced ContentPane in under layout project in Dojox.
You all know that dojox is a extenal tree from dojo and dijit, open for more experimental stuff.
It includes executeScripts, among other things.

changes from 0.4 (some names might be badly chosen, please help in finding logical ones)
scriptScope -> gone
scriptSeparation -> gone, always in global
executeScripts -> default true
adjustPaths -> default false

new:
cleanContent -> default false
        removes tags that is likely the throw DOM or JS errors, <DOCTYPE ..>,
        <title> and html comments <!-- *JS code* //-->,
        <![CDATA[ *JS code*]]> from JS.

renderStyles -> default false
        snarfs <style>*cssText*</style> tags and <link rel='stylesheet' href='..'>
        and inserts those into document head.
        ensures that it works X browser, innerHTML <style> actually throws in old
        Opera's or was it old Khtml, any way innerHTML a <style> tag doesn't do a
        thing in other browsers

ioArgs -> default {}
        ioArgs to xhrGet,
        example:
        pane1.ioArgs.headers ={
                'X-myOwnHeader': 'yepp it works!',
                'X-getMePage': 2
        };
        pane1.refresh();

ioMethod -> default dojo.xhrGet
        ioMethod used to download data
        example:
        pane1.ioArgs.content = {page:2};
        pane1.ioMethod = dojo.xhrPost;
        pane1.refresh();

scriptHasHooks -> default false, Bad name?
        The keyword _container_ in your JS code
        is replaced before eval with dijit.byId('this.id')
        example of form handler (could of course go into onLoad just as easily):
       <div dojoType='dojox.layout.ContentPane'
                scriptHasHooks='true'
                ioMethod='dojo.xhrPost'
                href='myFormPage'
       ></div>

       myFormPage:
        <script>
             _container_.onLoadDeferred.addCallback(function(){
                   var form = dojo.query('>form', _container_.domNode)[0];
                   var conn = dojo.connect(form, 'onsubmit', null, function(evt){
                         dojo.disconnect(form); dojo.stopEvent(evt);
                         _container_.ioArgs.form = form;
                         _container_.refresh();
                   });
            });
       </script>
       <form>
          <input name='value1'/>
          <input name='value2'/>
          <input type='submit'/>
       </form>

new methods:
onLoadDeferred  is a dojo.Deferred
        callback on onLoad, if isLoaded = true fires immediately

onUnloadDeferred is a dojo.Deferred
        callback on onUnload

onExecError, event
        script download, but doesn't fire on parse or runtime error, havent figured
        out why yet

setHref(), refresh() and setContent() returns a handle
        handle = {
                cancel()
                addOnLoad(func)
                addOnUnload(func)
        }

        example:
        pane1.ioMethod = dojo.xhrPost;
        var handle = pane1.setHref('getform');
        handle.addOnLoad(function(){
                var ev = dojo.connect(dojo.byId('myForm'), 'onsubmit', null, function(e){
                        dojo.stopEvent(e);
                        dojo.disconnect(ev);
                        pane1.ioArgs.form = dojo.byId('myForm');
                        pane1.refresh(); // we should set up handle here again,
                                                 // but you get the idea
                });
        });

It is also possible to use a <table>,<thead|tbody>,<tr> as a DOM node (they
are readonly to innerHTML in IE)
Content must still be valid though, if domNode is <table> your content must be
"<tbody><tr><td>*new content*</td></tr></tbody>"

It just works as expected in IE just as in FF.

So go ahead and test it and comment on errors, brainslips, hard to understand features, namechanges etc.

/ Fredrik

scriptHasHooks example does

scriptHasHooks example does not work. When submitting I get an error "node.submit is not a function".