It seems that dev.rubyonrails.org is down at the moment. I think this
is the same bug reported in ticket 5228, which was closed with a
challenge to create a simple demonstration. I'll reopen that ticket
when I can get to the Trak site. Meanwhile, here's a demo.
Brief summary: when evalScripts is true, PeriodicalUpdater is
rendering the scripts as well as executing them. In what seems to be
a related problem, it seems to run for one extra iteration after
being stopped.
Demo Rails code:
(View foo.rhtml):
<%= link_to_remote "Test Periodical", :url => { :action =>
"test_periodical"}%>
<div id="stuff">Here is some stuff</div>
(Controller FooController.rb):
def test_periodical
logger.info "Called test_periodical"
@session[:per] = 1
render :update do |page|
page << %Q<
if (document.statChecker)
{ document.statChecker.options.onComplete = undefined;
document.statChecker.stop(); }
document.statChecker = new Ajax.PeriodicalUpdater('stuff','/
foo/periodical_res',
{asynchronous:true, frequency:2, evalScripts:true });
>
end
end
# http://dev.rubyonrails.org/ticket/5228
def periodical_res
logger.info "Called periodical_res"
t = @session[:per] if @session[:per]
s = "Update number #{t}"
@session[:per] = t + 1
if t == 3
render :update do |page|
page << %Q{
if (document.statChecker)
{ document.statChecker.options.onComplete = undefined;
document.statChecker.stop(); }
}
page.replace_html 'stuff', "All done"
end
return
else
render :text => "Update number #{t}"
end
end
end
It seems that what's happening is that the script gets evaluated at
line 761 of prototype.js (1.5.0_rc0)(this.evalResponse();), but
processing continues through the render. This causes any javascript
to be both evaluated and rendered.
This can be avoided by making a simple change inrespondToReadyState:
respondToReadyState: function(readyState) {
var event = Ajax.Request.Events[readyState];
var transport = this.transport, json = this.evalJSON();
var isJS = ((this.header('Content-type') || '').match(/^text\/
javascript/i))
if (event == 'Complete') {
try {
(this.options['on' + this.transport.status]
|| this.options['on' + (this.responseIsSuccess() ?
'Success' : 'Failure')]
|| Prototype.emptyFunction)(transport, json);
} catch (e) {
this.dispatchException(e);
}
if (isJS) {
this.evalResponse();
}
}
if (!isJS) {
try {
(this.options['on' + event] || Prototype.emptyFunction)
(transport, json);
Ajax.Responders.dispatch('on' + event, this, transport, json);
} catch (e) {
this.dispatchException(e);
}
}
/* Avoid memory leak in MSIE: clean up the oncomplete event
handler */
if (event == 'Complete')
this.transport.onreadystatechange = Prototype.emptyFunction;
},
As I said, I'll post a diff in proper form to the Trak site when it's
up again. In the meantime, I'm no Javascript wizard, and would
appreciate any comments on my solution or suggestions for a better one.
--Al Evans--
_______________________________________________
Rails-spinoffs mailing list
Rails-spinoffs@lists.rubyonrails.org
http://lists.rubyonrails.org/mailman/listinfo/rails-spinoffs