19

I put the following function in my application.js:

function test() {
  alert("See Me")
}

classrooms/_new_small.html.haml:

:javascript
  alert('test');
  test();

In my application.html.haml I'm using the following:

= javascript_include_tag 'application'

I'm getting a test is not defined error in my firebug console. Isn't the test function supposed to be available project-wide because its in the application.js file? Thanks

edit: I'm rendering the page via javascript. Would that affect it?

$('#test_container').html("<%= escape_javascript(render :partial => 'classrooms/new_small') %>");
5
  • yes it should be, can you post your partial? Commented Dec 31, 2012 at 0:53
  • Just updated it with the partial code that is calling the function. Commented Dec 31, 2012 at 1:04
  • Are you sure your controller is rendering a layout that includes application.js ? Commented Jan 5, 2013 at 1:09
  • Why the partial and not just the javascript in your response? Commented Jan 6, 2013 at 20:09
  • Is your javascript_include_tag in your <head>, or is it at the end of your <body>? If it appears at the end of your <body>, (i.e.: after you try to call it from your view), then it won't have been defined yet. Try replacing your call to test() with $(function () { test() }); to see if it succeeds. Commented Jan 7, 2013 at 20:09

7 Answers 7

28
+50

Assuming you are using asset pipeline & coffeescript: Don't write code in application.js

In order to keep clean structure, create a folder (eg: application) in app/assets/javascripts

then require it in your application.js

//= require jquery
//= require jquery_ujs

//= require_tree ./application

Create a coffee file (eg: app/assets/javascripts/application/my_feature.js.coffee

@test = ->
  alert('Hello world')

Coffee output:

(function() {

  this.test = function() {
    return alert('Hello world');
  };

}).call(this);

It's preferable to use namespaces:

@myGreatFeature =
  test: ->
    alert('Hello world')

or according to the coffeescript FAQ, you could write

namespace = (target, name, block) ->
  [target, name, block] = [(if typeof exports isnt 'undefined' then exports else window), arguments...] if arguments.length < 3
  top    = target
  target = target[item] or= {} for item in name.split '.'
  block target, top

namespace 'myGreatFeature', (exports) ->
  exports.test = ->
    alert('Hello world')

then you can call myGreatFeature.test() everywhere

Sign up to request clarification or add additional context in comments.

2 Comments

How is Coffeescript directly relevant?
@JackHasaKeyboard Perhaps it is not directly relevant, but it seems at least indirectly relevant as "Rails ships with CoffeeScript by default" per guides.rubyonrails.org/working_with_javascript_in_rails.html.
1

Simple solution, remove escape_javascript, but it's dangerous see Why escape_javascript before rendering a partial? . Currently you want to execute

$('#test_container').html("<script>
//<![CDATA[
 alert('test');
 test();
//]]>
</script>

which is converted into

$('#test_container').html("<script>\n  //<![CDATA[\n    alert(\'test\');\n    test();\n  //]]>\n<\/script>\n");

How do i solve this problem ?

i will include project_wide.js in app/assets/javascripts/ and then tell application.js to include my file .

//= require project_wide

Be sure to put the above line after

//= require jquery
//= require jquery_ujs

Now, whatever i put in app/assets/javascripts/project_wide.js it will shamelessly appear in whole project except the files which are in public/ folder . In this file, i will put everything which i want to execute .

Follow common practice

Currently,you are adding javascript directly inside classrooms/_new_small.html.haml which is uncommon. Mostly , rails developer put such things in assets/javascripts/*.js or call content_for :javascript_custom block in views , which is added in layout file by yield :javascript_custom

Comments

1

I tried this without an issue. Here's how I did it.

// application.js

var test=function(){
  alert("hello");
}

// in a view, whichever one, i have a content_for :additional_javascripts

<% content_for :additional_javascripts do %>
  <%= javascript_tag do %>
    test();
  <% end %>
<% end %>

// in application layout

<%= javascript_include_tag "application" %>
<%= yeild(:additional_javascripts) %>

Furthermore, if I want to alert this dynamically later on I could append it to the page and call it then, or put it in a click listener or something.

I like the syntax var functionName = function(){...} because it properly scopes the method. Also, because of the way javascripts are compiled through the asset pipeline, adding the ; at the end of every executed line is very important.

This also worked for me as far as loading the script dynamically and calling it from anywhere in the page:

$("#click_me").live("click", function(){
  $("<script />").text("test();").appendTo("body");
});

And in the page I had a simple link.

<a href="#" id="click_me">click</a>

Comments

0

You're probably thinking of the line

= javascript_include_tag "application"

rather than

= stylesheet_link_tag 'application', :media => 'all'

If the former is missing, your javascript won't be included.

2 Comments

Thanks - I mis-copied. I was using the javascript_include_tag
If you View Source on the page, is a script tag being generated? If so, is your test function in the URL the script tag points to?
0

Try using:

<%= javascript_include_tag :all %>

in your application.html.erb file

Comments

0

I noticed your function test() is indented, which suggests it is nested. If you define a function in the scope of another function, it will not be available outside of it.

For example this should work, using jQuery:

function test() { /* do something */ }

// another file or inline script

$(function() {
   test();
});

But this won't

(function() {
   function test() {}
})();

// another file

test(); // undefined

1 Comment

Thanks for looking but its not indented in the actual code. Cutting and pasting in into stackoverflow caused the indent.
0

put all those javascript functions in application.js file and include <%= javascript_include_tag 'application' %> in head tag of your layout file

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.