[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(/]*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,

> 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  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:
> > ']*>([\\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 = ']*>([\\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(/]*src="(.*)"[^>]*>/, function(match){
>                 ActionUtils.loadScript(match[1]);
>         });
>   }
>
> });
>
> ActionUtils = {
>
>         ...
>
>         Resources : [],
>
>         loadScript : function(resource, onload) {
>                 if(

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

2009-05-06 Thread almeidap

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:
> ']*>([\\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 = ']*>([\\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(/]*src="(.*)"[^>]*>/, function(match){
ActionUtils.loadScript(match[1]);
});
  }
});

ActionUtils = {

...

Resources : [],

loadScript : function(resource, onload) {
if(!this.Resources.include(resource)){
var script = new Element('script', {
'type' : 'text/javascript',
'src' : resource
});

script.onload = onload | this.emptyFunction;
this.getHtmlHead().insert(script);
this.Resources.push(resource);
}
}
}

(Prototype's ScriptFragment property has not been changed in this
scenario!)

In this way, developpers don't bother how to include external JS
files, the asynchronous circuit does all the job for them.
Nevertheless, I think that inline scripts may be executed before
external resource has been completely interpreted, which may lead to
invalid references.

This has only been tested on Firefox, so let me know if it works with
other main browsers.

[1] http://www.phpied.com/javascript-include-ready-onload/

--~--~-~--~~~---~--~~
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:
']*>([\\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:



you could have it do this:

loadExternalScript('somescriptfile.js');

...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  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>
>
> 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
-~--~~~~--~~--~--~---