The SitePoint Forums have moved.

You can now find them here.
This forum is now closed to new posts, but you can browse existing content.
You can find out more information about the move and how to open a new account (if necessary) here.
If you get stuck you can get support by emailing forums@sitepoint.com

If this is your first visit, be sure to
check out the FAQ by clicking the
link above. You may have to register
before you can post: click the register link above to proceed. To start viewing messages,
select the forum that you want to visit from the selection below.

Toggling visibility of DIVs using RJS

I want to create an app which has a form with a list of inputs and when the focus is on an input a div appears which displays help relating to that input. For example, the user tabs onto first name and a div appears (with a scriptaculous effect) explaining why this field is required, the same will happen for surname, dob etc.

I am a total rails newbie and i'm having trouble figuring out how to do this.

I haven't done enough JavaScript wizardry but this is what I would try using something like observe_field on whichever inputs you need the helper div. If there are multiple helper divs, just render them next to the inputs (using a script.aculo.us helper, RJS, or a custom JS function) and make their display property initially set to none. The effect of observe_field would then show & hide the appropriate div. If there's only one helper div, then you could can have observe_field call an action with an RJS template, which would populate the helper div given the proper input field id.

Please use a Javascript function on the page instead of RJS. I don't see a need for the server to get involved in unhiding divs.

I thought a key reason for using RJS was that you could write the code in Ruby and not need to know about the JavaScript. That is, to let the framework worry about generating the JavaScript, in much the same way as systems like ASP.Net go about things.

The key point here is surely which language you choose to do your coding in, rather than where that code activates. If you think all client side JavaScript should be written in native JavaScript, there seems to me to be little point in Rails including the AJAX libraries it now has.

For example, most of the script.aclous.us functions create operations that are totally client side. For example, draggable_element and drop_receiving_element. Even the Prototype functions such as link_to_remote include a significant proportion of code that triggers client side.

I thought a key reason for using RJS was that you could write the code in Ruby and not need to know about the JavaScript. That is, to let the framework worry about generating the JavaScript, in much the same way as systems like ASP.Net go about things.

The key point here is surely which language you choose to do your coding in, rather than where that code activates. If you think all client side JavaScript should be written in native JavaScript, there seems to me to be little point in Rails including the AJAX libraries it now has.

For example, most of the script.aclous.us functions create operations that are totally client side. For example, draggable_element and drop_receiving_element. Even the Prototype functions such as link_to_remote include a significant proportion of code that triggers client side.

However, ignoring efficiency to the point that one would write code that asks the server "they clicked a text box, what do I do??" and waits for its response is not good.

Use RJS in the situations when you want to generate Javascript based on information from a database. The Javascript libraries are so high level that code for basic effects will look nearly like Ruby anyway.

You can also look at it from a compatibility standpoint. Browsers which support AJAX are a subset of browsers which support Javascript, which is a subset of browsers which support HTML and CSS. If you use observe_field to call a Javascript function that shows divs dynamically, your code can easily be made to downgrade to work in every browser.

If you pull the divs using AJAX, you can cater only to the smallest portion of web users.

You can also look at it from a compatibility standpoint. Browsers which support AJAX are a subset of browsers which support Javascript, which is a subset of browsers which support HTML and CSS. If you use observe_field to call a Javascript function that shows divs dynamically, your code can easily be made to downgrade to work in every browser.

That is just back-to-front reasoning. One of the main problems with writing pure JavaScript is that different browers work with different versions. For example, older version of MS Internet Explorer don't use JavaScript but instead the very similar JScript.

So while the subset of browsers that support JavaScript/JScript is large, you have to either be restrictive with your coding or write multiple versions of your code to be compatible with the differences between versions and the way browsers handle them.

One of the reasons for using AJAX is that it take the headache of having to deal with this multiplicity of brower environments away from the developer. The developer codes one set of AJAX instructions and the AJAX functions themselves detect the browser and handle the variation in output code needs to perform the required action.

Hopefully wardo has looked up observe_field, has figured how easy it is to use with AJAX and otherwise, and has had his question answered. And doesn't mind us hijacking the thread a little for an interesting cause.

Originally Posted by ReggieB

That is just back-to-front reasoning. One of the main problems with writing pure JavaScript is that different browers work with different versions. For example, older version of MS Internet Explorer don't use JavaScript but instead the very similar JScript.

So while the subset of browsers that support JavaScript/JScript is large, you have to either be restrictive with your coding or write multiple versions of your code to be compatible with the differences between versions and the way browsers handle them.

One of the reasons for using AJAX is that it take the headache of having to deal with this multiplicity of brower environments away from the developer. The developer codes one set of AJAX instructions and the AJAX functions themselves detect the browser and handle the variation in output code needs to perform the required action.

The original poster is talking about Javascript of a few calls to show() and hide(); that's code so simple that it either works or doesn't because the library handles all of the browser incompatibilities you talk about, and it's exactly the code RJS will be generating anyway. RJS does not generate different code depending on the browser, AFAIK. It relies on the Javascript library to be compliant.

The difference is that if you write the Javascript in the page yourself, the users wait less because their browsers already have the code, it works for users with and without AJAX, and the server isn't barraged with requests every time a user hits tab.

This would be a real easy one if observe_field could take a block like link_to_function.

Oh well.

That's a great point. I missed this functionality being added. It looks like link_to_remote is just using PrototypeHelper::update_page which takes a block and returns Javascript. You could probably embed the RJS with something like

Hopefully wardo has looked up observe_field, has figured how easy it is to use with AJAX and otherwise, and has had his question answered. And doesn't mind us hijacking the thread a little for an interesting cause.

Yes. I should also apologise to wardo for hijacking their thread. Hope you don't mind too much

Originally Posted by AllTom

The difference is that if you write the Javascript in the page yourself, the users wait less because their browsers already have the code, it works for users with and without AJAX, and the server isn't barraged with requests every time a user hits tab.

Just because the code is generated at the server, does not mean it has to call back to the server each time the resulting code is activated at the client.

Again, I 'll use the Rails function draggable_element as an example. When the page is first generated by the server, Rails on the server creates the page content as prescribed by the draggable_element function's code. What gets passed to the server is JavaScript. The Rails draggable_element function generates JavaScript code. That JavaScript code behaves at the client in exactly the same way as it would if it had been hand coded directly, rather than being generated by a Rails function. That is, the element made draggable does not call back to the server each time it is dragged. The server has created the JavaScript code that allows the element to be dragged in the browser. Job done. No further server side activity is required.

It is exactly the same as other Rails functions. For example, link_to is a Rails function and it causes HTML to be generated and passed to the server. The resulting HTML manifests as an anchor tag. That anchor behaves at the client in exactly the same way as it would if the developer had entered <A> tags manually.

Saying that AJAX and JavaScript code that is generated at the server has to connect back to the server each time the code is activated at the client browser just because it was server generated, is as erroneous as saying that a select list generated via the Rails function collection_select calls back to the server each time a user clicks on the resulting drop-down list and selects an option.

The difference between using RJS and writing the JavaScript natively is a choice of which language you prefer to code in. If you prefer to write the code directly as JavaScript that fine. But if you don't know JavaScript, or choose not to write native JavaScript, Rails AJAX libraries give you an alternative that is just as valid.

vSkyfluxx's original suggestion was to use observe_field with a "script.aculo.us helper, RJS, or a custom JS function," and I recommended not using RJS. That was because, before samsm's post, I did not realize that RJS could be used with observe_field to generate the Javascript in-place, instead of in an RJS view on the server (all I'd ever done). This is all my misunderstanding.