[Proto-Scripty] Re: Ajax.Updater and JavaScript source files inclusions

2009-05-27 Thread disccomp

I cam across these related tickets:
http://dev.rubyonrails.org/ticket/6722
http://dev.rubyonrails.org/ticket/9871

I think it would probably be critical for many use cases that the
scripts load synchronously in order of appearance after an element is
updated. Maybe another value for the evalScripts option could be used
like 'all' or 'all-sync', signifying that both inline and external js
would be loaded dynamically, async or sync.

-Mark
--~--~-~--~~~---~--~~
You received this message because you are subscribed to the Google Groups 
Prototype  script.aculo.us group.
To post to this group, send email to prototype-scriptaculous@googlegroups.com
To unsubscribe from this group, send email to 
prototype-scriptaculous+unsubscr...@googlegroups.com
For more options, visit this group at 
http://groups.google.com/group/prototype-scriptaculous?hl=en
-~--~~~~--~~--~--~---



[Proto-Scripty] Re: Ajax.Updater and JavaScript source files inclusions

2009-05-13 Thread almeidap

Thanks for all your advices T.J.! I read some snippets of the Proto-
Scripty wiki and my dynamic script loading was in the right way.

 It doesn't process them if you assign them as strings via innerHTML,
 which is what your modified update would do (Element#update uses
 innerHTML behind the scenes).  It does process them correctly if you
 insert them using DOM methods as your code does, even if you don't put
 them in the head.
Hm, actually I'm already using Prototype 1.6.1 RC2 (by the way, thanks
for this IE8 special release) and it seems that Element#update has
been completely reworked but still uses the innerHTML approach. I'm I
wrong?

 Ah, interesting approach.  I think I'd prefer to leave Prototype
 unmodified and build my own updater-like-thing via Ajax.Request, but
 obviously it's up to you.
Don't worry, the registration of the Ajax.Responders callback is not
done in prototype.js but in a specific initialization script! ;)
Actually, all our asynchronous updates are already delegating to
Ajax.Request because validation and exception messages thrown by the
usecase workflow do not produce failed requests but are instead
redirected to some specific forward page, which will allow to capture
these kind of errors:

Ajax.Request.prototype.error = false;

Ajax.Responders.register({
onComplete: function(responder) {
// Ensure that external scripts are successfully loaded:
var reponseText = responder.transport.responseText;
reponseText.scan(/script[^]*src=(.*)[^]*/, 
function(match){
Application.loadScript(match[1]);
});
}
});

/* This should be part of Prototype Ajax core... ;) */
Object.extend(Ajax.Updater, {
callbacks : [],

register : function(callback){
this.callbacks.push(callback);
},
});

Object.extend(Ajax, {
[...]
update: function(element, url, options){
element = $(element);
options = Ajax._checkOptions(options);
options.onComplete = options.onComplete.wrap(function(original,
transport){
element.update(transport.responseText);
// Apply update callbacks:
Ajax.Updater.callbacks.each(function(callback){
callback(element);
});
original(transport);
});

// Delegate:
return Ajax.request(url, options);
},

request : function(url, options){
options = Ajax._checkOptions(options);
options.onComplete = options.onComplete.wrap(function(original,
transport){
// Check for worflow errors (note that response has 
already been
evaluated):
if (transport.request.error){
options.onError(transport);
} else {
original(transport);
}
});

// Delegate:
return new Ajax.Request(url, options);
},

}

Don't hesitate to 'pimp' my code, if you detect some conflict. Hope
this may be usefull for anyone using the Struts forward engine.

 Very likely.  The inline scripts will get evaluated very, very soon
 after the content is updated (Element#update does it via Function#defer
 [1]), whereas the external scripts may still be downloading at that
 point.  A really robust solution would probably walk through the
 script tags (inline and external) in the order in which they appear
 and load/execute them sequentially...
You're right. Currently, I'm using events to notify observers that
script successfully loaded but your idea about scanning and executing
all script tags may be implemented when I'll get some time to spend on
JS optimization.

Thanks a lot!
--~--~-~--~~~---~--~~
You received this message because you are subscribed to the Google Groups 
Prototype  script.aculo.us group.
To post to this group, send email to prototype-scriptaculous@googlegroups.com
To unsubscribe from this group, send email to 
prototype-scriptaculous+unsubscr...@googlegroups.com
For more options, visit this group at 
http://groups.google.com/group/prototype-scriptaculous?hl=en
-~--~~~~--~~--~--~---



[Proto-Scripty] Re: Ajax.Updater and JavaScript source files inclusions

2009-05-06 Thread T.J. Crowder

Hi,

 Is there a work around to force Prototype to leave JavaScript source
 files inclusions after Ajax updates?

Nothing built into Prototype.  If you search through Lighthouse[1] or
this group (I forget which) there was a discussion about possibly
adding that at some stage.  In the meantime, I see two options:

One is that you can use Ajax.Request rather than Ajax.Updater and
process the result yourself.  At its core, Ajax.Updater just processes
a successful result by calling Element#update[2], which uses
String#evalScripts[3] to execute the inline scripts (but not the ones
referencing external files).  You could replace it with Ajax.Request,
look for the script tags referencing external files, and process them
yourself.

String#evalScripts uses String#extractScripts[4], which uses this
regex repeatedly to build an array of the contents of script tags:
'script[^]*([\\S\\s]*?)\/script'  As you can see, the only
capture group there is for the content between the script tags, and so
the array String#extractScripts builds is only for inline scripts.
You'd have to use a modified form to search for tags for external
scripts.

Once you have the external scripts, you can load them dynamically;
some tips on doing that here[5] on the unofficial wiki.

The second approach, which may be simpler, only works if you're in
control of what comes back (e.g., you're not calling some third-party
code you don't have control over).  If you are in control of it, you
could change it to use inline script to load external scripts, rather
than script tags.  E.g., instead of having the result contain:

script src='somescriptfile.js'/script

you could have it do this:

scriptloadExternalScript('somescriptfile.js');/script

...where loadExternalScript is defined on the main page and (again)
uses techniques like those suggested[5] on the unofficial wiki.

[1] http://prototype.lighthouseapp.com/projects/8886-prototype/overview
[2] http://prototypejs.org/api/element/update
[3] http://prototypejs.org/api/string/evalScripts
[4] http://prototypejs.org/api/string/extractScripts
[5] http://proto-scripty.wikidot.com/prototype:how-to-load-scripts-dynamically

HTH,
--
T.J. Crowder
tj / crowder software / com
Independent Software Engineer, consulting services available

On May 6, 9:30 am, almeidap almei...@gmail.com wrote:
 Hi,

 Our application has been enhanced with an asynchronous circuit (based
 over the Prototype's Ajax class) that is able to load and navigate
 through usecases in a modal window.

 When calling an usecase action in a asynchronous way, the circuit
 returns only the needed HTML content (and not a full web page with the
 HTML or HEAD tags) that may contain JavaScript source file inclusions,
 like:

 script type=text/javascript src=/MyUsecase/MyAction.js //
 script

 When performing a such update (using Ajax.Updater(container,
 actionUrl, {evalJS : true, evalScripts : true})), scripts are
 correctly evaluated and removed from output. But script tags that
 reference a source file are also removed and the contents of the
 Javascript file will never be interpreted!

 Is there a work around to force Prototype to leave JavaScript source
 files inclusions after Ajax updates?

 Thanks
--~--~-~--~~~---~--~~
You received this message because you are subscribed to the Google Groups 
Prototype  script.aculo.us group.
To post to this group, send email to prototype-scriptaculous@googlegroups.com
To unsubscribe from this group, send email to 
prototype-scriptaculous+unsubscr...@googlegroups.com
For more options, visit this group at 
http://groups.google.com/group/prototype-scriptaculous?hl=en
-~--~~~~--~~--~--~---



[Proto-Scripty] Re: Ajax.Updater and JavaScript source files inclusions

2009-05-06 Thread T.J. Crowder

Hi,

 Yes, I could control this as output mostly comes from source files
 that have been automatically generated (MDA approach) but I think this
 solution would break browser file cache.

It wouldn't, but you couldn't have known that as you couldn't see the
wiki article. :-)

 I couldn't check Proto-
 Scripty wiki (seems to be down...) to learn about dynamic script
 loading but this put me in the way.

Wow, I've never known wikidot (where the wiki is hosted) to be down.
I suppose it must happen. :-)  It's working right now as I write this
(I followed the link in my earlier note to make sure it wasn't a
typo).

 Nevertheless, it seems that Firefox does not load external script
 files unless they are inserted in the HTML head element (can someone
 confirm that?).

It doesn't process them if you assign them as strings via innerHTML,
which is what your modified update would do (Element#update uses
innerHTML behind the scenes).  It does process them correctly if you
insert them using DOM methods as your code does, even if you don't put
them in the head.  But putting them in the head is probably the most
appropriate thing to do anyway, and indeed is exactly what the
unofficial wiki article does. :-)

 In fact, I choose to use Ajax.Responders to parse response text from
 output and dynamically load any external source files...

Ah, interesting approach.  I think I'd prefer to leave Prototype
unmodified and build my own updater-like-thing via Ajax.Request, but
obviously it's up to you.

 Nevertheless, I think that inline scripts may be executed before
 external resource has been completely interpreted, which may lead to
 invalid references.

Very likely.  The inline scripts will get evaluated very, very soon
after the content is updated (Element#update does it via Function#defer
[1]), whereas the external scripts may still be downloading at that
point.  A really robust solution would probably walk through the
script tags (inline and external) in the order in which they appear
and load/execute them sequentially.  I think if you were going to do
that, you'd have to retrieve the script files directly (via XHR calls)
rather than inserting script tags, because otherwise I'm not sure how
you'd be able to know that the file had finished loading.  XHR stuff
*should* use the browser cache, and I understand it mostly does
although there are some revalidation issues reported in the XHR
Wikipedia article (mostly indicating that stale content may get
reused, as opposed to getting re-retrieved too often).[2]

[1] http://prototypejs.org/api/function/defer
[2] http://en.wikipedia.org/wiki/XMLHttpRequest

Have fun,
--
T.J. Crowder
tj / crowder software / com
Independent Software Engineer, consulting services available

On May 6, 2:45 pm, almeidap almei...@gmail.com wrote:
 Thanks for your quick and complete answer! I've followed your hints
 and I think that I've reached an elegant (but maybe not performant)
 solution.

  String#evalScripts uses String#extractScripts[4], which uses this
  regex repeatedly to build an array of the contents of script tags:
  'script[^]*([\\S\\s]*?)\/script' ...

 Right! I adapted Prototype's regex to leave script tags that reference
 an external source file, simply by redefining the Prototype's
 ScriptFragment property (argh, it took me about 1 hour to find that
 crazy regex):
 Prototype.ScriptFragment = 'script(?!.*src)[^]*([\\S\\s]*?)\/
 script';

 Nevertheless, it seems that Firefox does not load external script
 files unless they are inserted in the HTML head element (can someone
 confirm that?). That means that even if the script element was
 inserted into the DOM after update, script contents were never
 interpreted.

  The second approach, which may be simpler, only works if you're in
  control of what comes back (e.g., you're not calling some third-party
  code you don't have control over).  If you are in control of it, you
  could change it to use inline script to load external scripts, rather
  than script tags.

 Yes, I could control this as output mostly comes from source files
 that have been automatically generated (MDA approach) but I think this
 solution would break browser file cache. I couldn't check Proto-
 Scripty wiki (seems to be down...) to learn about dynamic script
 loading but this put me in the way.

 In fact, I choose to use Ajax.Responders to parse response text from
 output and dynamically load any external source files by appending a
 script element in the HTML head (inspired by [1], feel free to reveal
 problems or to suggest optimizations):

 Ajax.Responders.register({
   onComplete: function(responder) {
     var reponseText = responder.transport.responseText;
         reponseText.scan(/script[^]*src=(.*)[^]*/, function(match){
                 ActionUtils.loadScript(match[1]);
         });
   }

 });

 ActionUtils = {

         ...

         Resources : [],

         loadScript : function(resource, onload) {
                 if(!this.Resources.include(resource)){