Jquery Options using $(this) - javascript

I'm trying to write a jquery plugin and i have a question about the famous "this".
Here is the call of the custom plugin :
$('.selector').myPlugin({
test: $(this).attr('rel')
});
And now, somewhere in my plugin :
$.myPlugin = function (options) {
alert(options.test);
}
My question is : How can i use the Rel attribute of my selector in the plugin using $(this)?
The previous code is always telling me that "this" is the Document.
Thanx a lot

$(this) isn't what you expect it to be in that object literal. Loop using each:
$('.selector').each(function() {
$(this).myPlugin({
test: $(this).attr('rel')
});
});
Inside each, this will point to the correct element, as opposed to the context of the calling function.

Related

Type error: "Not a function" using "this" keyword in a function

I have created the following function.
function showAllSelectOpts(select)
{
selectLength = select.children().length;
select.attr('size',selectLength);
select.css('height','auto');
select.focusout(function(){
select.attr('size','1');
});
}
When it is called directly on a select element like this showAllSelectOpts(mySelect); it works fine, but when called within another function, as below using the keyword "this", it returns the error. Type error: select.children not a function
$('select').on('focus',function(){
showAllSelectOpts(this);
})
Is this a scope issue or what, and how can I resolve it?
In an event handler, this is a reference to the DOM element, not a jQuery object. But your showAllSelectOpts expects its argument to be a jQuery object.
Either change the call to wrap the DOM element with $():
showAllSelectOpts($(this));
...or update showAllSelectOpts to do so itself:
function showAllSelectOpts(select)
{
select = $(select); // ***
selectLength = select.children().length;
select.attr('size',selectLength);
select.css('height','auto');
select.focusout(function(){
select.attr('size','1');
});
}
Side note: As A.Wolff points out, your function attaches a new focusout handler to the select every time it's called. You only want one.
I'd remove that part of the handler entirely, and replace it with a single focusout:
function showAllSelectOpts(select)
{
var selectLength = select.children().length;
select.attr('size',selectLength);
select.css('height','auto');
}
$('select')
.on('focus',function(){
showAllSelectOpts($(this));
})
.on('focusout', function(){
$(this).attr('size', '1');
});
Also note that I added a var for selectLength in showAllSelectOpts (although actually, you could just remove the variable entirely); without one, the code is falling prey to The Horror of Implicit Globals (that's a post on my anemic little blog). Be sure to declare your variables.
jQuery event listener callbacks set this as the HTMLElement that the event was fired on.
In your callback you are expecting a jQuery object, but you have the HTMLElement.
You can pass the HTMLElement to a jQuery constructor and pass it into the showAllSelectOpts function
$('select').on('focus',function(){
showAllSelectOpts($(this));
})
Try this one -
$('select').on('focus',function() {
showAllSelectOpts($(this)); })
Try this:
var myselect = $('select');
$('select').on('focus',function(){
showAllSelectOpts(myselect);
})
A better way could be:
$('select').on('focus',function(event){
showAllSelectOpts($(event.target));
})
Why your code not working?
$('select').on('focus',function(){
//Here `this` is bound with the dom html element, not the $('select') object.
showAllSelectOpts(this);
})
These previous answers fix it. I'd just add here to create it as an extension since $(this) refers to a prototype of one method call.
$.fn.showAllSelectOpts=function() {
$(this).on('focus',()=>{
$(this)
.css('height','auto')
.attr('size',$(this).children().length)
.focusout(()=>{
$(this).attr('size','1');
});
});
};
$('select').showAllSelectOpts();

Jquery appropriation

I encountered with snippet of code in the jQuery menu library. I'm new to jQuery so can somebody explain what $(this) in cssmenu variable means (its a kind of context?).
$.fn.menumaker = function(options) {
var cssmenu = $(this),
settings = $.extend({
title: "Menu",
format: "dropdown",
sticky: false
}, options);
}
That code defines a jQuery plugin, by adding a function to the jQuery's object prototype. In the context of a plugin's initializer function, $(this) is totally unecessary: this in the context of a plugin function already refers to a jQuery object.
Not only that, but the way the plugin is written doesn't follow jQuery principles where a plugin might be called on a jQuery object wrapping over multiple DOM elements.
The plugin's definition also doesn't take in account the fact that jQuery.noConflict() would be used.
A form that would make more sense is:
//Using an IIFE and passing jQuery allow us to use $ safely
(function($) {
$.fn.menumaker = function(options) {
//Apply defaults
options = $.extend({
title: "Menu",
format: "dropdown",
sticky: false
}, options);
//Initialize the plugin for every DOM element in the jQuery oject
//and return the jQuery object to avoid breaking chaining
return this.each(function() {
//In here, this points to a DOM element, that's why we wrap it
//in a DOM object
initPlugin($(this), options);
});
};
function initPlugin($el, options) {
//The plugin would be applied here to $el
}
})(jQuery);
Let's look at the whole thing step by step:
$.fn.menumaker = function(options) {
}
This defines a jQuery plugin called menumaker, taking an options object. It is run as $('mySelector').menumaker({}).
var cssmenu = $(this), settings = $.extend({}, options);
Now, this is going to be the jQuery object $('mySelector') from the above example. Wrapping it in another jQuery constructor ($(this)) is rather redundant.
But in any case, it's saved as a variable named cssmenu. A settings variable is also created, applying the passed in objects to the default settings.
So basically, yes, it's the context. It's also pointless.
Basically $.fn.menumaker means its allows you to extend jquery with your own function, which in turn will be available to all jquery objects.
So the this, is the Jquery equivalent of the DOM object with which you have used plugin function.

Passing correct jQuery selector to an object

I am writing a jQuery plugin which, ideally I would like in it's own namespace.
So far, this seems to work (in terms of namespace nesting)
(function($) {
$.fn.nspace = {
foo: function() {
// Does not work becuase $(this) is not the correct selector.
$(this).show();
}
}
})(jQuery);
So given then example above, I might call my function like so:
$("html, body").nspace.foo();
but $(this) is not [html, body]...How can I solve this?
EDIT: To clarify (based on user comments)...
$("html, body").nspace.foo(); should call foo for [html, body] but, $(this) inside nspace resolves to nspace...so it's trying to call nspace.foo();
You shouldn't do this, but just because I dislike when someone says "You can't" in programming (often untrue, especially in Javascript) - here's how you could do this:
The jQuery object is constructed each time using its prototype.init function, which is aliased to fn.init, so you could overwrite it with a wrapped function that adds your namespace object in a way that doesn't harm any existing usage or libraries, like so:
(function($) {
var baseInit = $.fn.init;
$.fn.init = function(selector, context, rootjQuery) {
// Instantiate jQuery the way it expects
var j = new baseInit(selector, context, rootjQuery);
// Add our extra object/namespace
// Use j inside to refer to the current jQuery object
j.nspace = {
foo: function() {
j.show();
}
};
// Return it all and other libraries are none the wiser
return j;
}
})(jQuery);
http://jsfiddle.net/b9chris/7TPZY/
You should consider using the classic pattern for a jQuery plugin: define only one method: in your case, nspace. Inside this method, you'll take every case into account. Sounds hard, but it's pretty easy once you've looked into that.
(By the way you definitely have to look at that when writing a jQuery plugin)
You can't add an object as a plugin and still get the jQuery object that was used to get the object. You simply have no reference to that jQuery object when you call a method in your object.
Put the function directly as the plugin:
(function($) {
$.fn.nspace = function() {
this.show();
};
})(jQuery);
Usage:
$("html, body").nspace();
(Note that the object is the jQuery instance, not a selector or an element, so you don't need to use $(this)).

In jQuery is it possible to set a method as a var?

Let's say I have a lot of instances of $(this).show("slow", function(){fVar;}); where $(this) are different objects at different times, but they all need .show("slow", function(){fVar;}); and fVar is a previously defined function var.
Is it possible to set .show("slow", function(){fVar;}); as a var like "myVar" so I could theoretically do something like $(this).myVar();
You sure can. Check out the jquery docs
(function( $ ) {
$.fn.myPlugin = function() {
// Do your awesome plugin stuff here
};
})( jQuery );
don't forget about proper namespacing! And just use the method that you declare (so mPlugin) just as you would any other JQuery method
I'm not so much into JQuery but try this -
$.prototype.myVar=function(){
//here goes your code
}
just create it as a function expression and you can use it wherever you want. this function takes in an event object that is created by an event listener. ie: click functions. use this var as your event function callback and pass in the event object so it knows what to show.
var showSlow = function(eventObject){
$(eventObject).show("slow", function(){
fVar;
});
}

refer to the plugin object within the plugin

I am trying to access plugin through this, in order to refer to methods added later down in the chain.
$.fn.test = function(){
console.log(this);
}
but this refers to the elements I have used to call the plugin, and not the plugin itself.
How can I access the plugin, and thus any methods attached to it?
Use $(this) if you want the jQuery object.
You can also try this to add plugin to jQuery.
(function($){
$.extend($.fn, {
test: function(){
//Plugin code here
//here this will point to jQuery object
}
};
})(jQuery);

Categories