I am developing a JQuery plugin. I need to use OOP inside my plugin. However, the class not working as I expected. When I initiate a new instance of the class, it is only the first line of its code that is executing. What is wrong with this code and how to execute a constructor of this class on initiation?
(function ($) {
var FunClass;
FunClass = function () {
console.log("FunGlobal");
function FunClass() {
console.log("FunConstructor");
}
FunClass.prototype.letsFun = function () {
console.log("FunMethod");
}
}();
$.fn.fun = function () {
var funClass;
return this.each(function () {
funClass = new FunClass();
funClass.letsFun();
});
};
}(jQuery));
Here is the console output: Console Output
Thanks for help.
Seems you've forgot to return FunClass:
(function($) {
var FunClass;
FunClass = (function() {
console.log("FunGlobal");
function FunClass() {
console.log("FunConstructor");
}
FunClass.prototype.letsFun = function() {
console.log("FunMethod");
}
return FunClass; // you missed this line
})();
$.fn.fun = function() {
var funClass;
return this.each(function() {
funClass = new FunClass();
funClass.letsFun();
});
};
}(jQuery));
// Usage
$(function() {
$('body').fun();
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
Related
I'm quite new to JavaScript, and for the life of me I can't fugure out how to correctly construct a global object in my script:
var Global =
{
button1Handler: function () {
this.button1 = $("#button1");
this.init = function () {
this.button1.on("click", function () { alert("button1 clicked"); });
}
},
button2Handler: function () { /* ... */ },
init: function () {
this.button1Handler.init();
this.button2Handler.init();
}
};
$(function () {
Global.init();
});
This code produces the following error:
TypeError: this.button1Handler.init is not a function
If I change it to this.button1Handler().init(); the error goes away, but the Button1Handler.init() function never gets called.
How do I correct the code above?
I am not sure why you have to do like this. But if you really want to you can achieve what you want with this:
button1Handler: function () {
return {
button1: $("#button1"),
init: function () {
this.button1.on("click", function () { alert("button1 clicked"); });
}
};
},
and then you can call init as this.button1Handler().init().
In this case this.button1Handler() function returns an object which further has an init method.
You are getting error because this.button1Handler is a function and you will have to create an instance of it to access properties of it.
var Global = {
button1Handler: function() {
//this.button1 = $("#button1");
this.init = function() {
//this.button1.on("click", function () { alert("button1 clicked"); });
console.log("Button1 init")
}
},
button2Handler: function() {
this.init = function() {
console.log("Button2 init")
}
},
init: function() {
new this.button1Handler().init();
new this.button2Handler().init();
}
};
(function() {
Global.init();
})();
A better solution is to return necessary properties:
Sample
var Global = {
button1Handler: function() {
var button1 = $("#button1");
var init = function() {
button1.on("click", function() {
console.log("Button1 clicked")
});
}
return {
init: init
}
},
button2Handler: function() {
var button2 = $("#button2");
var init = function() {
button2.on("click", function() {
console.log("Button2 clicked")
});
}
return {
init: init
}
},
init: function() {
this.button1Handler().init();
this.button2Handler().init();
}
};
(function() {
Global.init();
})();
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.0/jquery.min.js"></script>
<button id="button1">button 1</button>
<button id="button2">button 2</button>
In the following code, button1 is a private variable since it is not exposed using return statement, but init is public property. So you can have any number of properties, but only the properties that you return will be public properties.
button1Handler: function() {
var button1 = $("#button1");
var init = function() {
button1.on("click", function() {
console.log("Button1 clicked")
});
}
return {
init: init
}
}
It is because button1Handler does not return an executed function. In this.button1Handler().init() button1Handler function is invoking the init there this will point to the button1Handler() scope hence function init will be accessible.
I have implemented several jQuery plugins for my current project.
Since some plugins have functions with the same name, the one called in the last one defined.
Here is the definition of my first plugin:
$(function($)
{
$.fn.initPlugin1 = function(parameters)
{
var defaultParameters = {};
$(this).data('parameters', $.extend(defaultParameters, parameters));
return $(this);
};
$.fn.function1 = function(){ console.log('Function 1.'); };
$.fn.callFunction = function(){ $(this).function1(); };
});
And here is the definition of my second plugin:
$(function($)
{
$.fn.initPlugin2 = function(parameters)
{
var defaultParameters = {};
$(this).data('parameters', $.extend(defaultParameters, parameters));
return $(this);
};
$.fn.function2 = function(){ console.log('Function 2.'); };
$.fn.callFunction = function(){ $(this).function2(); };
});
I have also this scenario :
$("#div1").initPlugin1().callFunction();
$("#div2").initPlugin2().callFunction();
For this specific scenario the consoles shows: Function 2. Function 2.
In fact, since the callFunction() is also defined in the second plugin, this is the one used.
I would like some advise on what is the best way to solve this problem.
Is it possible to create a thing similiar to a namespace ?
Thank to #syms answer, I have created the following example.
Plugin1:
$(function($) {
$.fn.initPlugin1 = function() {
console.log('Initialized Plugin1');
return $(this);
};
$.fn.initPlugin1.testFunction = function() {
$(this).append('Function 1.');
};
});
Plugin2:
$(function($) {
$.fn.initPlugin2 = function() {
console.log('Initialized Plugin2');
return $(this);
};
$.fn.initPlugin2.testFunction = function() {
$(this).append('Function 2.');
};
});
Main:
(function($)
{
$(document).ready(
function()
{
$("#div1").initPlugin1(); //Run correctly
$("#div2").initPlugin2(); //Run correctly
$("#div1").initPlugin1.testFunction(); //Fail
$("#div2").initPlugin2.testFunction(); //Fail
});
})(jQuery);
When I run my code, I got the following error: Cannot read property 'createDocumentFragment' of null.
Apparently, the this object is corrupted.
you can try this,
$(function($) {
$.fn.initPlugin1 = function() {
console.log('Initialized Plugin1');
return $(this);
};
});
$(function($) {
$.fn.initPlugin2 = function() {
console.log('Initialized Plugin2');
return $(this);
};
$.fn.callFunction = function(param) {
$(this).append(param);
};
});
(function($) {
$(document).ready(
function() {
$("#div1").initPlugin1(); //Run correctly
$("#div2").initPlugin2(); //Run correctly
$("#div1").initPlugin1().callFunction('function1');
$("#div2").initPlugin2().callFunction('function2');
});
})(jQuery);
I need to know how is possible to get a plugin variable outside the plugin, to test it with some test framework.
So this is my simplified plugin:
(function ($) {
$.fn.extend({
myPlugin: function (argumentOptions) {
var defaults = {
image: 'img/default.png',
};
this.textSend = '';
var options = $.extend(defaults, argumentOptions);
var globalHere = this;
return this.each(function () {
obj.mouseup(function(e) {
globalHere.textSend = 'test';
});
});
}
});
})(jQuery);
I need to the variable this.textSend outside the plugin.
I have tried in this way:
$(document).ready(function(){
var testfield = $('.txt');
testfield.myPlugin({
image:"../img/twitter.png"
});
testfield.focus();
testfield.trigger($.Event( "mouseup"));
console.log($.fn.myPlugin.textSend);
});
but the console.log return me undefined
How can i get that variable outside?
Thanks
You will want to make sure you are returning this like so:
(function($) {
$.fn.extend({
myPlugin: function(argumentOptions) {
var self = this;
self.textSend = 'something';
self.inc = 0;
self.mouseup(function(e) {
self.textSend = 'new thing #' + self.inc;
self.inc++;
});
return self;
}
});
})(jQuery);
var instantiated = $('button').myPlugin({});
$('input').val(instantiated.textSend);
$('button').click(function(e) {
$('input').val(instantiated.textSend);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.0/jquery.min.js"></script>
<label>Current textSend:</label>
<input />
<br/>
<button>Change textSend</button>
Hopefully will get you on the right track.
Update
Try new code.
You can store it inside the closed scope you created around your plugin and expose it through another function. Of course it'll need some refactoring, but this is the general idea:
(function ($) {
var whateverNameYouWant; //here
$.fn.extend({
myPlugin: function (argumentOptions) {
var defaults = {
image: 'img/default.png',
};
this.textSend = '';
whateverNameYouWant = this.textSend; //here
var options = $.extend(defaults, argumentOptions);
var globalHere = this;
return this.each(function () {
obj.mouseup(function(e) {
globalHere.textSend = 'test';
whateverNameYouWant = this.textSend; //here
});
});
}
});
$.extend({
getWhateverNameYouWant: function() {
return whateverNameYouWant;
}
})
})(jQuery);
var value = $.getWhateverNameYouWant();
At line console.log($.fn.myPlugin.textSend);
use testfield.textSend . now it has become proprty of selector via myplugin.
I have following js plugin to catch show hide events of elements. But i want to make it specific to One dom element only, i.e #div_loading_page
jQuery(function ($) {
$.each(['show','hide'], function (i, ev) {
var el = $.fn[ev];
$.fn[ev] = function () {
this.trigger(ev);
el.apply(this, arguments);
};
});
});
can anyone please help. thanks
jQuery(function ($) {
$.each(['show','hide'], function (i, ev) {
var el = $.fn[ev];
$.fn[ev] = function () {
this.each(function () {
if ( this.id == 'div_loading_page') {
$(this).trigger(ev);
return false; // break out of the loop
}
});
el.apply(this, arguments);
};
});
});
here's my basic code:
JS:
jQuery(function($)
{
function MyTest() {}
MyTest.prototype =
{
myMethod: function()
{
$(this).append("<div id='myId'></div>");
}
}
$(document).ready(function()
{
var myTest1 = new MyTest();
$("#anelement").click(function()
{
myTest1.myMethod();
});
});
});
HTML:
<div id='anelement'></div>
Clicking on "anelement", JS console returns:
TypeError: e is undefined ... jquery.min.js (line 5)
...and it doesn't append "myId" - why?
Thanks
You need to somehow pass the clicked element into your method. Here is one way to do it:
jQuery(function ($) {
function MyTest() {}
MyTest.prototype = {
myMethod: function (el) {
$(el).append("<div id='myId'></div>");
}
}
$(document).ready(function () {
var myTest1 = new MyTest();
$("#anelement").click(function () {
myTest1.myMethod(this);
});
});
});
You could also use .call to execute your method with the given context, however you then lose access to instance methods and variables.
jQuery(function ($) {
function MyTest() {}
MyTest.prototype = {
myMethod: function () {
$(this).append("<div id='myId'></div>");
}
}
$(document).ready(function () {
var myTest1 = new MyTest();
$("#anelement").click(function () {
myTest1.myMethod.call(this);
});
});
});
or simply
jQuery(function ($) {
function MyTest() {}
MyTest.prototype = {
myMethod: function () {
$(this).append("<div id='myId'></div>");
}
}
$(document).ready(function () {
var myTest1 = new MyTest();
$("#anelement").click(myTest1.myMethod);
});
});