Topic: Javascript / link_to_function / prototype issue.

Help - I'm simply trying to toggle a div using link_to_function and Prototype , but I'm using JQuery also!!!

It works in a simple test case as expected:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
        "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html>
  <head>
    <meta http-equiv="Content-type" content="text/html; charset=utf-8" />
    <title>TEST</title>
    <%= javascript_include_tag :defaults %>
    <%= javascript_include_tag "nav" %>
    <%= javascript_include_tag "jquery-1.3.2.min" %>
    <%= javascript_include_tag "jquery.easing.1.3" %>
    <%= javascript_include_tag "jquery.slideViewerPro.1.0" %>
    <%= javascript_include_tag "jquery.timers-1.1.2" %>
  </head>
  <body>
    <div id="page">
    <div id="help7" style="display:none">
      <p>This is help</p>
    </div>
    Click here for <%= link_to_function "help", "$('help7').toggle()" %>
    </div>
  </body>
</html>

BUT,  if I run the same code in my real application,  the JavaScript isn't firing or working as the div will not toggle between visible/invisible.

First of all,  the HTML generated in each case is:

<a href="#" onclick="$('help7').toggle(); return false;">help</a>

My test application is setup with the root route set in routes.rb as:

  map.root :controller => "home"

and my test code is in views/home/index.rhtml

When I run this code in the simple test case (http://172.30.1.10:3004) , and hover over the link,  I see the following in the status display at the very bottom of Firefox:

http://172.30.1.10:3004/?onclick=$('help7').toggle()#

And it WORKS!

In my real (non-working) app,  the link_to_function is in controller=>'app', action=>'new'.   I have this route in routes.rb

map.connect 'app/new/:type', :controller=> 'app', :action=>'new', :type=>nil   

I use the type to set a 'type' in my app model.

So,  when my app links to the page in question with:

<%= link_to image_tag("prodnav/bt_apply-now.gif"), 'app/new/film_app' , :height=>31, :class=>"prodbt"  %>

and I hover over the link generated by link_to_function, I see this in the status bar:

http://172.30.1.10:3003/app/new/film_app#

The difference between the two invocations of link_to_function are:

The working version is called from the default application index page
The working version is toggling a div right at the top of the HTML heirarchy of the page.
The working version contains NO calls to JQuery

The non-working version is called from views/app/new.rhtml thusly:
<% form_for [@app], :id => "editForm" , :url => { :action => :create} do |f| %>
    <%= render :partial => session['app_type'] , :locals=>{:f => f, :aid => 0, :ins_type => 1  }%>

the session variable 'app_type' contains the name of the partial template,  in this case

'_film_app'

My thoughts are:

There are no JavaScript errors reported,  and I haven't figured out if I can debug the local JavaScript in firebug.  Can I?

But it should work,  there is only one div on the page with the id of 'help7'.  Isn't $('help7').toggle enough to always toggle the div, regardless of the page complexity?

Could it be the combined use of Prototype and J Query?  Even though I included the J Query JavaScript,  it isn't called in the test case,  it is called a lot in the real application.

If anybody thinks that Prototype & J Query combined may be behind my problem,  I can easily just eliminate Prototype.  My web designer delivered a site with the J Query stuff,  that has to stay,  but Prototype can go.

My biggest clue I THINK is the difference in the status displays of Firefox.  When the JavaScript call isn't  displayed,  it doesn't work,  when it is displayed in the status bar it does work.

I can't figure out why the difference, why does the ?onlcick=$('help7').toggle()#  disappear from my display in the non-working version?  and is that why it doesn't work?

Or is it the fact that JavaScript is generated from a partial?  Do I need to pass some additional context to the partial to get the JavaScript to work??

Thanks in Advance

Last edited by BradHodges (2009-06-18 19:29:23)

Joe got a job, on the day shift, at the Utility Muffin Research Kitchen, arrogantly twisting the sterile canvas snout of a fully charged icing anointment utensil.

Re: Javascript / link_to_function / prototype issue.

OK, I figured it out,  it WAS the JQuery colliding with Prototype in some way.

So the lesson learned is this: If by some strange reason you 'railsify' an existing site that has JQuery based JavaScript already in it,  pay attention when you start new JavaScript stuff.

I started out by acquiring a basic website 'design' consisting of html/css/javascript.  The javascript relied on JQuery, (jquery-1.3.2,jquery.easing.1.3,jquery.slideViewerPro.1.0 & jquery.timers-1.1.2).  I modified this site and brought it up as a rails app, no real problem so far.

So I got to the point of needing to do my own new JavaScript stuff on the site.  I started using JavaScript helpers/Prototype/Script.aculo.us , because it was already there.  MISTAKE!

The JQuery and Prototype got in each others way.  I read around and decided to use JRails,  which allowed me to keep my use of Rails built-in JavaScript helpers,  but pull out the Prototype and do it all with JQuery.  There was also a way I could of kept Prototype and JQuery and forced them to co-exist, (noConflict plugin ??? for JQuery).  In my case the inherited JQuery was extensive,  and I had just started my own JavaScript,  so I had no real motivation to use TWO different frameworks.

So here is what I had to do:

1) Download jrails, it's a plugin

ruby ./script/plugin install http://ennerchi.googlecode.com/svn/trunk/plugins/jrails


2) Remove all of the prototype JavaScript files from public/JavaScript

3) Remove reference to above mentioned javascript files in your views, i.e. delete:

  <%= include_javascript_tag "prototype" %>

  or

  <%= include_javascript_tag :default %>

  or whatever you've done to utilize JavaScript in your app.


4) Move the jrails JavaScript files from vendor/plugins/jrails/javascripts directory to my site's public/javascripts directory.  Turns out I only had to move two of the jrails JavaScript files, (jquery-ui.js and jrails.js),  the rest were already there due to the existing jquery based stuff needed them.

I had to make one simple change to my code to get it to work.  To be honest,  this change could of been my problem all along,  and the change over to pure JQuery via JRails wasn't nessecary,  but I'm so sick of this problem I don't care to go back and investigate.  Anyway I THINK there was a subtle difference in the JQuery and Prototype syntax.

In Protytype , I was doing this:

$('id_of_div').toggle();

In JQuery, I had to do this:

$('#id_of_div').toggle();


Anyway,  it works now, hope this helps someone!!!

P.S.

I read some about unobtrusive JavaScript.  I'm probably going to abandon the Rails JavaScript helpers altogether, and go unobtrusive.

Joe got a job, on the day shift, at the Utility Muffin Research Kitchen, arrogantly twisting the sterile canvas snout of a fully charged icing anointment utensil.