jQuery extension: why does it not work on all matching elements? - javascript

I have an extension going like:
$.fn.crazything = function() {
var self = $(this);
// do some crazy stuff
return self;
}
And when I call it like:
$("div.crazydiv").crazything();
It works, but only on the first matching div. If I have more than one div on the page, I need to do:
$("div.crazydiv").each(function(i) { $(this).crazything (); });
Why is this, and how can I rewrite my extension to work on multiple divs?

Most jQuery plugins use this pattern which handles your crazy stuff:
(function($) {
$.fn.crazything = function() {
// allow setup on jQuery objects that conatin multiple elements:
return this.each(function() {
// this function is called once for each element in the jQuery object
var self = $(this);
// do some crazy stuff
});
};
})(jQuery);

Related

JQuery.one() event that fires immediately

I'm making a jquery plugin in which you can set the event for something to happen.
$.fn.makeSomething = function(options) {
var defaults = {
activationEvent: "mouseover"
};
options = $.extend(defaults, options);
this.each(function() {
var elem = $(this);
elem.one(options.activationEvent, function(){
// some code to be called at the event (in which I use elem)
// but by default should be called immediately on load
});
});
return this;
}
I would like the default to be that it just happens without any needed interaction. Is this possible?
A little more info:
I have several divs in which some extra content should be loaded. By default I want the content to be loaded when the page loads. However, on some pages I don't want all the content to be loaded with the page, but I want each piece to be loaded only when you hover your mouse over its div.
Thanks!
If you separate the function definition from the binding:
$.fn.makeSomething = function(options) {
// ...
function doSomething() {
// ...
}
$(this).one(options.activationEvent, doSomething);
};
You can test the activationEvent for a default value that isn't an event, such as null, providing the that same function to .each():
$.fn.makeSomething = function(options) {
var defaults = {
activationEvent: null
};
options = $.extend(defaults, options);
function doSomething() {
var $elem = $(this);
// ...
}
if (!options.activationEvent)
this.each(doSomething);
else
this.one(options.activationEvent, doSomething);
};
// act immediately
$('...').makeSomething();
// act on mouseover
$('...').makeSomething({ activationEvent: 'mouseover' });
Both .one() and .each() will invoke doSomething() with this referring to the DOM Element. (Note: the arguments provided to doSomething() will, however, be different.)

Calling a function inside a jQuery plugin from outside

I am trying to work out how to call functions within my jQuery plugin from outside the plugin. The code I have tried is not working. I'm sure I will have to restructure my plugin to allow this, but I'm not sure how to. In this example, I'm trying to access the underline() function.
jsFiddle
jQuery plugin
(function($) {
"use strict";
$.fn.testPlugin = function(options) {
// Settings
var settings = $.extend({
newText : "Yabadabado"
}, options);
return this.each(function(i, el) {
var init = function(callback) {
if( $(el).attr("class") === "red" ) {
$(el).css("color","red");
}
$(el).text(settings.newText);
if( callback && typeof(callback) === "function" ) {
callback();
}
};
var underline = function() {
$(el).addClass("underline");
};
init();
});
};
}(jQuery));
Assign the plugin to selectors
var doTest = $("#testItem").testPlugin({
newText: "Scoobydoo"
});
var doNewTest = $("#newTestItem").testPlugin({
newText: "kapow!"
});
Call a function that is located within the plugin
$("#underline").click(function(e) {
e.preventDefault();
doTest.underline();
});
Take a look at closures.
Here is a basic example of what a closure looks like in a jQuery plugin.
$.fn.plugin = function() {
return {
helloWorld: function() {
console.log('Hello World!');
}
}
};
// init plugin.
var test = $('node').plugin();
// call a method from within the plugin outside of the plugin.
test.helloWorld();
You can see another example at the following jsfiddle.
http://jsfiddle.net/denniswaltermartinez/DwEFz/
First thing first we need to understand each step in building a jQuery plugin, its like build a javascript plugin (class) but we have in addition to it a jQuery class.
//We start with a function and pass a jQuery class to it as a
//parameter $ to avoid the conflict with other javascript
//plugins that uses '$ as a name
(function($){
//We now append our function to the jQuery namespace,
//with an option parameter
$.fn.myplugin = function(options) {
//the settings parameter will be our private parameter to our function
//'myplugin', using jQuery.extend append 'options' to our settings
var settings = jQuery.extend({
param:'value',
}, options);
//Define a reference to our function myplugin which it's
//part of jQuery namespace functions, so we can use later
//within inside functions
var $jquery=this;
//Define an output object that will work as a reference
//for our function
var output={
//Setup our plugin functions as an object elements
'function1':function(param){
//Call jQuery reference that goes through jQuery selector
$jquery.each(function(){
//Define a reference of each element of jQuery
//selector elements
var _this=this;
});
//This steps is required if you want to call nested
//functions like jQuery.
return output;
},
//If we want to make our plugin to do a specific operations
//when called, we define a function for that
'init':function(){
$jquery.each(function(){
var _this=this;
//Note that _this param linked to each jQuery
//functions not element, thus wont behave like
//jQuery function.
//And for that we set a parameter to reference the
//jQuery element
_this.$this=$(this);
//We can define a private function for 'init'
//function
var privatefun=function(){}
privatefun();
//We can now do jQuery stuffs on each element
_this.$this.on('click',function(){
//jQuery related stuffs
});
});
//We can call whatever function we want or parameter
//that belongs to our plugin
output.function1("value");
}
};
//Our output is ready, if we want our plugin to execute a
//function whenever it called we do it now
output.init();
//And the final critical step, return our object output to
//the plugin
return output;
};
//Pass the jQuery class so we can use it inside our plugin 'class'
})(jQuery);
Using our function now is very easy
<div class="plugintest">
<span>1</span>
<span>2</span>
<span>3</span>
<span>4</span>
</div>
<script>
$(function(){
var myplugin=$(".plugintest > span").myplugin({
param:'somevalue'
});
myplugin.function1(1).function1(2).function1(3);
});
</script>
In short, jQuery plugins and any Javascript plugins are simply about parameters scope.
Fiddle version
https://jsfiddle.net/eiadsamman/a59uwmga/

Is it possible to add function to jQuery's dialog from separate .js file?

I want to add a function to jQuery UI Dialog. I want to do that without actually downloading .js file with jQuery UI Dialog source code and editing it. Is it possible to do this from separate .js file?
Some further explanation: let's say I want to add custom function that's called e.g. "func1". After I've coded it, I should be able to call it like this:
($"#dialog").dialog("func1");
Is that possible without editing original jQuery Dialog source code?
Ok, I've finally found the answer :D
(function($){
var _init = $.ui.dialog.prototype._init;
//Init
$.ui.dialog.prototype._init = function() {
var self = this;
_init.apply(this, arguments);
//here you can do custom init
};
//Custom Dialog Functions
$.extend($.ui.dialog.prototype, {
func1: function() {
alert("f1");
},
func2: function() {
alert("function 2");
}
});
})(jQuery);
I have figured it out from this post :
http://www.droptoframe.com/?p=35
I have not tested, but I think it should work:
$.fn.dialog = (function() {
var cached_function = $.fn.dialog;
return function() {
if (arguments[0] !== "func1")
cached_function.apply(this, arguments);
else {
// Do what you want here...
}
};
}());​

jQuery: Determine if jQuery object is root html tag

Let's say I'm writing a jQuery extension method. This method should climb the ancestor tree of an element until it reaches the document's root <html> tag, at which point it should stop. I've implemented this as shown here:
$.fn.foo = function() {
var $foo = this;
while($foo[0] !== $(document).children()[0]) {
// do stuff with $foo
$foo = $foo.parent();
}
// do stuff
};
My question is: is there a better way than $foo[0] !== $(document).children()[0] to know whether I've reached the root <html> tag?
$foo.is('html')
You seem to be reimplementing parents(), though.
Don't compare against the first child, just see if a parent is returned:
var $foo = $(this);
while($foo.parent().length > 0) {
// do stuff with $foo
$foo = $foo.parent();
}
Here's a working fiddle.
What about this?
$.fn.foo = function() {
var $foo = this;
while($foo[0].tagName != 'HTML') {
// do stuff with $foo
$foo = $foo.parent();
}
// do stuff
};
Alternatively, if you don't actually need to traverse up, but only want to do things to all ancestors of a given node, you could use .parents() like so:
$.fn.foo = function() {
var $foo = this;
$foo.parents().andSelf().each(function() {
// do stuff with $foo
});
// do stuff
};
This should stop at HTML.
​$foo.parents().andSelf().each(function() {
// do something
console.log(this.nodeName);
});​​​
Or if you're running the same jQuery method(s) against each node, do this:
$foo.parents().andSelf().someJQueryMethod();
http://api.jquery.com/parents/
http://api.jquery.com/andself/

How do I add a function to a specific element type in jQuery?

I can do this
jQuery.fn.validate = function(options) {
var defaults = {
validateOPtions1 : '',
validateOPtions2 : ''
};
var settings = $.extend({}, defaults, options);
return this.each(function() {
// you validation code goes here
});
};
but that will make validate() available for every element. I could do this to any element: $('some selector').validate().
Is there a way I can make this only available to, say, form elements? eg. $('.mySpecialFormClass').validate()?
You'd have to have the function throw an exception if you really don't want it to work for anything but a <form> tag.
jQuery.fn.formsOnly = function() {
return this.each(function() {
if (!$(this).is('form')) throw "Forms only!";
// whatever
});
};
The answer is simple:
$('form').validate();
Selectors work a bit like this in jQuery (just as in CSS)
$('elementType.className')
See this page for more details on selectors.

Categories