Craig Lafferty
Craig Lafferty

Reputation: 791

Can't call Javascript object method

I get a console error TypeError: bodys.show is not a function when loading my page. What am I doing wrong?

function loadingScreen(selector,css)
{
    this.loadingAnimation = $("<div><p>Loading</p><div></div></div>").appendTo(selector);
    this.containerCss = $.extend({'border-radius':"20px",position:"absolute",height:"40px",width:"120px","display":"none"}, css);
    this.loadingAnimation.css(this.containerCss);
    this.p = this.loadingAnimation.children("p").first();
    this.p.css({width:"100%",'text-align':"center"});
    this.div = this.loadingAnimation.children("div").first();
    this.div.css({position:"abslolute",left:"0",top:"0",'background-color':"rgba(255,100,100,0.5)",height:"100%",width:"10%"});
    function show(){
        this.loadingAnimation.css("display","block");
        animate(this.div,"right");
    }
    function hide(){
        this.loadingAnimation.css("display","none");
        this.div.stop(true,true);
        this.div.css("margin-left","0px");
    }
    function animate(element,direction)
    {
        if(direction === "right"){
            element.animate({"margin-left":"120px"},animate(element,"left"));
        }
        else if(direction === "left"){
            element.animate({"margin-left":"0px"},animate(element,"right"));
        }
    }
}

$(document).ready(function()
{
    var bodys = new loadingScreen("body",{});
    bodys.show();
});

Upvotes: 1

Views: 109

Answers (3)

Mulan
Mulan

Reputation: 135187

You can attach show to your new instance using this.show = show; inside your constructor

Or you can do this

// loading-screen.js
(function(window, $) {

  var LoadingScreen = function (selector, css) {
    this.$elem = $(selector);
    this.$elem.css(css);
  };

  LoadingScreen.prototype.show = function () {
    return this.$elem.show();
  };

  LoadingScreen.prototype.hide = function () {
    return this.$elem.hide();
  };

  window.LoadingScreen = LoadingScreen;

})(window, jQuery);

As part of the prototype, the show and hide functions will now be accessible to any instance of LoadingScreen. To top it off, you have an nice little module of code that can be included separately from all of your other scripts.

Usage

<script src="loading-screen.js"></script>
<script>
  $(function() {
    var ls = new LoadingScreen("body", {});
    ls.show();
    ls.hide();
  });
</script>

jQuery plugina demo

Since you're using jQuery anyway, instead of passing a selector and some css to vanilla constructor function, it might make sense to wrap this up in a jQuery plugin.

(function(window, $) {

  var LoadingScreen = function($elems, css) {
    this.$elems = $elems;
    this.$elems.css(css);
  };

  LoadingScreen.prototype.show = function() {
    this.$elems.slideDown(250);
  };

  LoadingScreen.prototype.hide = function() {
    this.$elems.slideUp(250);
  };

  $.fn.loadingScreen = function(css) {
    return new LoadingScreen(this, css);
  };

})(window, jQuery);

Usage is pretty similar but looks like much more conventional jQuery

$(function() {
  var ls = $("p").loadingScreen({backgroundColor: "blue"});

  // notice .show and .hide delegate to our plugin methods now
  ls.show();
});

Upvotes: 1

MickMalone1983
MickMalone1983

Reputation: 1054

When declaring variables/functions inside the body of a function, they are 'private' unless they are attached as properties of the function itself - inside the body, you'd use the this keyword to do this.

The function show() is private inside loadingScreen, to make it accessible as a member of its parent function, declare it with this:

this.show  = function(){...

...}

...it will still be able to access everything inside the scope of loadingScreen, but will be able to be called externally as a method of loadingScreen.

EDIT:

As Naomik points out below, you can also attach it to the prototype of the object:

loadingScreen.prototype.show = function()...

...apparently prototypal functions are executed more quickly than standard member declarations, however - as you'll be declaring it outside of the main function body, it won't have access to the private variables inside the function, so in this case it wouldn't be much use.

Upvotes: 1

Satpal
Satpal

Reputation: 133403

Currently show() function is defined in the local/private scope of loadingScreen, in order to making show publicly visible use this.show

So change your code as

 this.show = function() {

instead of

function show(){

Upvotes: 1

Related Questions