How to create RJS visual effects callbacks


#1

I’m trying desperately to get visuall effects callbacks working in rjs
templates to no avail What I’m trying to do is fade an image, change
the div with the image to a new image, and then fade the new image back
in. How would I go about this in RJS Here’s a simple line from my rjs
that I can’t get to work. It is not using callbacks so the
“comment_error” div is being replaced before the fade out. I can’t find
any documentation on the subject.

page.visual_effect :fade, ‘comment_error’, :duration => 0.5
page.replace_html ‘comment_error’, “#{error_messages_for(‘comment’)}”
page.visual_effect :appear, ‘comment_error’, :duration => 0.5


#2

I presume you realise that if there are no errors the div will stay
empty!


#3

Peter wrote:

I presume you realise that if there are no errors the div will stay
empty!

Yes, this is actually a fabricated example.


#4

so whats not working?


#5

Kevin O. wrote:

If I am not mistaken, all these effects get triggered at the same time,
which is why things look wierd. I think they added support for effect
queues in 1.1, but I can’t come up with a link of the top of my head.
At the very least, you can read about them at script.aculo.us

Yes, they are all triggered at the same time. I have only been able to
get the effects queues working with visual effects and not with
page.replace_html. How do I add the page.replace_html to the effects
queue?


#6

If I am not mistaken, all these effects get triggered at the same time,
which is why things look wierd. I think they added support for effect
queues in 1.1, but I can’t come up with a link of the top of my head.
At the very least, you can read about them at script.aculo.us

On Thursday, April 06, 2006, at 12:43 AM, charlie bowman wrote:

page.visual_effect :appear, ‘comment_error’, :duration => 0.5


Posted via http://www.ruby-forum.com/.


Rails mailing list
removed_email_address@domain.invalid
http://lists.rubyonrails.org/mailman/listinfo/rails

_Kevin


#7

Kevin O. wrote:

look at this message

http://devlists.com/message/49383

That is only about visual effects. It also isn’t in reference to rjs
templates. I don’t know how to take that code and use it in a rjs
template.


#8

I haven’t tested this yet, but here’s my logic.

  1. You can create a visual effect queue, and they work fine.
  2. You can trigger specific js calls with the callbacks for the visual
    effects

So… If you make a visual effect queue and attach specific js calls to
affect the DOM, you can effectively queue the DOM calls. RJS templates
just generate some JS calls for you using a nice format. Making this
work smoothly with RJS will take a little work.

Note that the visual effects don’t actually have to do anything visible.

It’s sort of a hack, but it might work.

On Thursday, April 06, 2006, at 5:30 AM, charlie bowman wrote:


Posted via http://www.ruby-forum.com/.


Rails mailing list
removed_email_address@domain.invalid
http://lists.rubyonrails.org/mailman/listinfo/rails

_Kevin


#9

Having done a little digging and a little thinking, I think this might
work.

page.delay(0) do
page.do_something
page.do_something_else
end

The reasoning behind this is that browsers will execute each top level
script in a block of JS when rendering. The delay function wraps the
code in a function so that it can be triggered after a delay. Since the
subsequent code is in a function block, it should execute sequentially
instead of in parallel.

Again, not tested, but it should be easy to try. I’ll give it a shot
myself next time I’m on my dev box.

On Thursday, April 06, 2006, at 3:36 PM, Kevin O. wrote:

removed_email_address@domain.invalid
http://lists.rubyonrails.org/mailman/listinfo/rails
_Kevin


#10

look at this message

http://devlists.com/message/49383

On Thursday, April 06, 2006, at 2:51 AM, charlie bowman wrote:

queue?


Posted via http://www.ruby-forum.com/.


Rails mailing list
removed_email_address@domain.invalid
http://lists.rubyonrails.org/mailman/listinfo/rails

_Kevin


#11

I’m dieing to get home now and try this out! I hope it works. It would
make things soooo much simpler!


#12

Kevin O. wrote:

Having done a little digging and a little thinking, I think this might
work.

page.delay(0) do
page.do_something
page.do_something_else
end

It would of been great but it does’t work.


#13

Here is where everything is explained

http://www.railsdevelopment.com/2006/01/15/effectqueue/

See Ya


#14

I’ve been trying to figure out a good solution to this as well. The
problem, as you stated, is that queues are not supported for anything
but scriptaculous visual effects, which is too bad. Ideally, every
rjs call could be assigned to a queue and all would be wonderful. I
hope something like this will be added to prototype in the future.

First off, the hack Kevin provided works for me if you set the delay
to at least 1. So this should work:

page.delay(1) do
page.do_something
page.do_something_else
end

Essentially i have solved this for now by applying various chained
and nested delays. This is horribly hackish, of course, but i don’t
see a better solution at this point. When using nested and chained
delays, these are the assumptions i’m making:

  1. instructions executed within a delay block are executed serially
    (see above)

  2. a chain of delay calls are executed serially, eg:

page.delay(1) do
page.do_something_1
page.do_something_else_1 --> duration is 3 seconds
end

page.delay(1) do
page.do_something_2 --> guaranteed to execute after

do_something_else_1
page.do_something_else_2
end

At least this is what i have observed and it works in Safari/Camino/
FF. Please somebody confirm that this can indeed be relied upon
across platforms.

Sebastian


#15

Sure, but as it has been said a few times, this ONLY works for
scriptaculous visual effects not for DOM inserts/replace etc. The
problem described by Charlie has to do with chaining DOM manipulation
and visual effects and having them execute in an expected order
instead of the parallel default. Scriptaculous queues do not apply here.

Sebastian


#16

Sebastian F. wrote:

I’ve been trying to figure out a good solution to this as well. The
problem, as you stated, is that queues are not supported for anything
but scriptaculous visual effects, which is too bad. Ideally, every
rjs call could be assigned to a queue and all would be wonderful. I
hope something like this will be added to prototype in the future.

First off, the hack Kevin provided works for me if you set the delay
to at least 1. So this should work:

page.delay(1) do
page.do_something
page.do_something_else
end

Essentially i have solved this for now by applying various chained
and nested delays. This is horribly hackish, of course, but i don’t
see a better solution at this point. When using nested and chained
delays, these are the assumptions i’m making:

  1. instructions executed within a delay block are executed serially
    (see above)

I’m seeing different results in Firefox 1.5 Take the following example:
page.delay(1) do
page.visual_effect :highlight, ‘comments’, :duration => 3
page.insert_html :bottom, ‘comments’, :partial => ‘comment’
page.replace_html ‘total_comments’, “(#{@post.comments.length})”
page.replace_html ‘comment_number’, “#{@post.comments.length} total
comments”
end

According to your post, you would think that the highlight effect on the
comments div would occur, then the partial would be inserted into the
bottom of the div. This isn’t happening for me. I’m getting the
highlight effect occuring at the same time the partial is insterted into
the bottom of the div. Are you seeing a different result?


#17

Looking at this again, I realize that there are a couple of problems
with this approach.

It looks like what you want to do is fade out the element, replace it,
and then make it appear.

The correct way to do this with a remote call would be to fade the
element using a ‘before’ callback, and then let the RJS template worry
about the replacement and appearance.

If you put everything into the RJS template, then the browser waits
until the request completes before it does anything.

The real problem here is that RJS templates only get called at one point
in the process. You can’t specify an RJS template to be called as part
of the ‘before’ callback unless you do it by hand.

I realize this is a contrived example, so if you have an example that
runs into sync’ing problems that doesn’t use visual effects, I’d like to
see it.

By the way… one way to implement the OP’s RJS template would be
this…

page.visual_effect :fade, 'comment_error', :duration=>0.5
page.delay(0.5) do
    page.replace_html 'comment_error', 

“#{error_messages_for(‘comment’)}”
page.visual_effect :appear, ‘comment_error’, :duration=>0.5
end

I have some ideas about how to have rails load a RJS template before
calling the action. I’ll put together a plugin for testing once I get
it worked out.

On Thursday, April 06, 2006, at 12:43 AM, charlie bowman wrote:

page.visual_effect :appear, ‘comment_error’, :duration => 0.5


Posted via http://www.ruby-forum.com/.


Rails mailing list
removed_email_address@domain.invalid
http://lists.rubyonrails.org/mailman/listinfo/rails

_Kevin


#18

I think this has been slightly overcomplicated. Kevin had it right:

page.visual_effect :fade, ‘comment_error’, :duration => 0.5
page.delay 0.5 do
page.replace_html ‘comment_error’, error_messages_for(‘comment’)
page.visual_effect :appear, ‘comment_error’, :duration => 0.5
end

That should work … :slight_smile:

-Jonathan.


#19

I see what is happening now…
Visual effects return right away and run in a separate thread. If you
want execution to delay until it is done, you need to wrap the
subsequent stuff in a delay block.

so…

page.visual_effect :highlight, ‘comments’, :duration => 3
page.delay(3) do
page.insert_html :bottom, ‘comments’, :partial => ‘comment’
page.replace_html ‘total_comments’, “(#{@post.comments.length})”
page.replace_html ‘comment_number’, “#{@post.comments.length} total
comments”
end

This will keep in sync’d with the visual effect.
Forget what I said earlier about page.delay. It won’t work with visual
effects.

On Friday, April 07, 2006, at 1:55 AM, charlie bowman wrote:

page.delay(1) do
(see above)
According to your post, you would think that the highlight effect on the
Rails mailing list
removed_email_address@domain.invalid
http://lists.rubyonrails.org/mailman/listinfo/rails

_Kevin


#20

Kevin O. wrote:

I see what is happening now…
Visual effects return right away and run in a separate thread. If you
want execution to delay until it is done, you need to wrap the
subsequent stuff in a delay block.

so…

page.visual_effect :highlight, ‘comments’, :duration => 3
page.delay(3) do
page.insert_html :bottom, ‘comments’, :partial => ‘comment’
page.replace_html ‘total_comments’, “(#{@post.comments.length})”
page.replace_html ‘comment_number’, “#{@post.comments.length} total
comments”
end

Yes, the delay method works, but I’ve been trying to avoid using it. It
just seems like a hack to me. I also don’t trust this method for
precise timing. I know it will work, but it just does’t seem very rails
like.