0

Original Question

Can't figure out why I can't call the second function from within that first function. I am using jQuery-turbolinks. (Also, if you happen to know of a better way to only run page-specific javascript in rails, let me know. Currently this is my best implementation where I check if the body has a certain class, and if it does then I run the init function within this javascript object).

app/assets/javascripts/blogs.js

$(document).ready(function(){

    var blogsjs = {   
        myBlog: this,  
        init: function(){
            alert("hello from blogs");
            $("input").on('click', function(){
                $(this).hide('slow', function(){
                    myBlog.another();
                });
            });
        },
        another: function(){
            alert("I was called!")
        }
    };


    if($('body').hasClass("blogs") == true){
        blogsjs.init(); 
    }
});

Solution After Feedback

Simply Just used object.method() syntax from within a method to call another method within that same object:

    $(document).ready(function(){

    var blogsjs = { 
        init: function(){
            alert("hello from blogs");
            $("input").on('click', function(){
                $(this).hide('slow', function(){
                   blogsjs.another();
                });
            });
        },
        another: function(){
            alert("I was called!");
            blogsjs.yetanother();
        },
        yetanother: function(){
             alert("yet another called");   
        }
    };
      blogsjs.init(); 

});

I don't like how messy this code looks, but the encapsulation benefits from an Object-oriented design, I think, is solid: Each resource's javascript only has access to the methods inside its javascript object.

Neil
  • 4,578
  • 14
  • 70
  • 155

2 Answers2

1

So you're probably getting an Cannot read property 'another' of undefined exception because you're specifying myBlog on the blogsjs object but do not reference it. Also myBlog will not be a reference to blogsjs but the scope jquery calls the document.ready function with.

You need to either create the reference inside your init method:

init: function(){
  var myBlog = this;
  alert("hello from blogs");
  $("input").on('click', function(){
    $(this).hide('slow', function(){
      myBlog.another();
    });
  });
}

or simply use blogsjs from one scope above your init method.

Have a look at this question to learn about scoping.

Community
  • 1
  • 1
LJᛃ
  • 7,655
  • 2
  • 24
  • 35
1

I don't know what you're trying to accomplish with this part of your declaration:

var blogsjs = {   
    myBlog: this 
}

but, this will NOT be set to blogsjs. It will be whatever it was in the above function. In Javascript, this is only set on a function call. It is NOT set in a Javascript literal declaration so you cannot statically declare a property that refers to the object itself. Javascript just does not support that.

You can add properties after the object is constructed that contain references to the object if desired.

If you want myBlog to be initialized to point to blogsjs, then you will have to do that after the object is defined:

var blogsjs = {   
    init: function() {...},
    another: function() {...}
};
blogsjs.myBlog = blogsjs;

In addition, this line of code won't work:

myBlog.another();

because myBlog is a property of an object, not a variable. It must be referenced with its parent object.

jfriend00
  • 683,504
  • 96
  • 985
  • 979