Forum: Ruby on Rails how to create RJS visual effects callbacks

Announcement (2017-05-07): www.ruby-forum.com is now read-only since I unfortunately do not have the time to support and maintain the forum any more. Please see rubyonrails.org/community and ruby-lang.org/en/community for other Rails- und Ruby-related community platforms.
Charlie B. (Guest)
on 2006-04-06 02:43
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
Peter (Guest)
on 2006-04-06 03:06
I presume you realise that if there are no errors the div will stay
empty!
Charlie B. (Guest)
on 2006-04-06 03:29
Peter wrote:
> I presume you realise that if there are no errors the div will stay
> empty!

Yes, this is actually a fabricated example.
Peter (Guest)
on 2006-04-06 03:53
so whats not working?
Kevin O. (Guest)
on 2006-04-06 04:30
(Received via mailing list)
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
Charlie B. (Guest)
on 2006-04-06 04:51
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?
Kevin O. (Guest)
on 2006-04-06 06:04
(Received via mailing list)
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
Charlie B. (Guest)
on 2006-04-06 07:30
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.
Kevin O. (Guest)
on 2006-04-06 19:39
(Received via mailing list)
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
Kevin O. (Guest)
on 2006-04-06 20:44
(Received via mailing list)
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
Charlie B. (Guest)
on 2006-04-06 21:00
(Received via mailing list)
I'm dieing to get home now and try this out! I hope it works.  It would
make things soooo much simpler!
Charlie B. (Guest)
on 2006-04-07 01:49
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.
Sebastian F. (Guest)
on 2006-04-07 02:19
(Received via mailing list)
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
Peter (Guest)
on 2006-04-07 03:22
Here is where everything is explained

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

See Ya
Sebastian F. (Guest)
on 2006-04-07 03:38
(Received via mailing list)
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
Charlie B. (Guest)
on 2006-04-07 03:55
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?
Kevin O. (Guest)
on 2006-04-07 04:08
(Received via mailing list)
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
Kevin O. (Guest)
on 2006-04-07 04:26
(Received via mailing list)
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
Jonathan V. (Guest)
on 2006-04-07 04:26
(Received via mailing list)
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 ... :)

-Jonathan.
Jonathan V. (Guest)
on 2006-04-07 04:32
(Received via mailing list)
Pretty much all Prototype does is execute all the generated javascript
in
another thread. Out of the box, Scriptaculous visual effects run
asynchronously, so to keep things executing in order you need to add a
page.delay after any page.visual_effect call.

page.delay simply puts the javascript generated from the block inside a
setTimeout to be run at a later stage.

Off the top of my head you'll end up with javascript something like:

new Effect.Fade('comment_error', {duration: 0.5});
setTimeout(function(){
  Element.update('comment_error', '<result of error_messages_for
here>');
  new Effect.Appear('comment_error', {duration: 0.5});
}, 500);

-Jonathan.

On 7 Apr 2006 00:24:21 -0000, Kevin O. <
Charlie B. (Guest)
on 2006-04-07 05:11
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.
Kevin O. (Guest)
on 2006-04-07 05:21
(Received via mailing list)
Here's a link to a plugin I patched together a while back.

https://opensvn.csie.org/traccgi/rjscallback/trac.cgi/

Don't get too attached to that URL, I'm trying to move it to rubyforge.

This plugin lets you specify RJS templates to be used for each of the
various remote_function callbacks.

For example,

controller/view/action_before.rjs will be loaded and used for the
'before' callback for any remote_function that calls
'controller/action'.

If you use the same ones a lot, you can put them into the 'view/shared'
folder.

It really is not well tested, and it can be inefficient if you have a
lot of remote_function calls on a page, but it works.


On Friday, April 07, 2006, at 12:25 PM, Jonathan V. wrote:
>-Jonathan.
>
>
>_______________________________________________
>Rails mailing list
>removed_email_address@domain.invalid
>http://lists.rubyonrails.org/mailman/listinfo/rails
>


_Kevin
Kevin O. (Guest)
on 2006-04-07 05:57
(Received via mailing list)
Except it doesn't work right now.  Need to make sure it's 1.1.1
compatible.


On Friday, April 07, 2006, at 1:18 AM, Kevin O. wrote:
>
>On Friday, April 07, 2006, at 12:25 PM, Jonathan V. wrote:
>>-Jonathan.
>
>--
>Posted with http://DevLists.com.  Sign up and save your mailbox.
>_______________________________________________
>Rails mailing list
>removed_email_address@domain.invalid
>http://lists.rubyonrails.org/mailman/listinfo/rails


_Kevin
Kevin O. (Guest)
on 2006-04-07 08:06
(Received via mailing list)
Works now with edgerails.  A couple of points that need clarification.

You are going to need to use the page.delay function anyway.

If you set up a 'action_before.rjs' file like this...

page.visual_effect :slide_up, 'testdiv'

and a regular RJS template like this...

page.replace_html 'testdiv','I'm done!'
page.visual_effect :slide_down, 'testdiv'

You can still get things out of sync if the server responds fast enough.

Since you know how long the visual effect will last, simply modify the
second template to..

page.delay(1) do
  page.replace_html 'testdiv','I'm done!'
  page.visual_effect :slide_down, 'testdiv'
end

Worst case scenario would be that there would be a short delay between
the first and second effects due to the server response time.  If this
is really a problem, that means your server is really slow and you have
other problems to worry about.

On Friday, April 07, 2006, at 1:55 AM, Kevin O. wrote:
>>This plugin lets you specify RJS templates to be used for each of the
>>It really is not well tested, and it can be inefficient if you have a
>>>end
>>>
>
>
>_Kevin
>
>--
>Posted with http://DevLists.com.  Sign up and save your mailbox.
>_______________________________________________
>Rails mailing list
>removed_email_address@domain.invalid
>http://lists.rubyonrails.org/mailman/listinfo/rails


_Kevin
This topic is locked and can not be replied to.