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

Reply via email to