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