zerowidth positive lookahead

Inline Events With Scriptaculous and Rails

When making some javascripty interactive bits on a Rails application I was working on, I ran into a problem when updating a div at the same time as it was being animated.

With some data on the page (for this example in the #content div), I wanted to:

1. Submit an RJS request
2. Leave the existing #content intact until the request completed
3. Effect.BlindUp('content')
4. Replace the content
5. Effect.BlindDown('content')

The original try went something like this, in some_action.js.rjs:

page.visual_effect :blind_up, "content", :queue => "end"
page.replace_html "content", :partial => "new_content"
page.visual_effect :blind_down, "content", :queue => "end"

The queues for the events worked as expected, but the contents would be replaced in the middle of the BlindUp effect, causing flickering and other visual artifacts. Even if I put the BlindUp in the :completed callback in the rjs form_remote_tag the problem still existed, only changing where the initial BlindUp was called.

After some digging, I discovered an undocumented “effect” that has nonetheless been in scrip.aculo.us since November 2006: Effect.Event. From the release notes, “Add new special core effect Effect.Event for one-shot events that follow timelines defined by effect queues”

Wrapping this up in a helper, I had:

def inline_event
  page << "new Effect.Event({queue: 'end', afterFinish:function(){"
  yield
  page << "}})"
end

Now I could do exactly what I needed to: replace the contents of #content while it was hidden:

page.visual_effect :blind_up, "content", :queue => "end"
page.inline_event do
  page.replace_html "content", :partial => "new_content"
end
page.visual_effect :blind_down, "content", :queue => "end"

Easily generalized:

def inline_event
  page << "new Effect.Event({queue: 'end', afterFinish:function(){"
  yield
  page << "}})"
end

def replace_content(content_id, opts)
  page.visual_effect :blind_up, content_id, :queue => "end"
  page.inline_event do
    page.replace_html content_id, opts
  end
  page.visual_effect :blind_down, content_id, :queue => "end"
end

And finally,

page.replace_content "content", :partial => "new_content"