Reputation: 791
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
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 plugin — a 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
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
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