How to write a simple jQuery plugin [closed] - javascript

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 8 years ago.
Improve this question
I wanted to create simple plugin using jquery.
Also suggest me standard practice while writing jQuery plugin.
Please folks suggest me some better pointers.

a good starting pattern looks like:
(function($){
$.fn.yourplugin = function() {
};
}(jQuery));

A simple template I created years ago and still works great:
(function($) {
if (!$.myExample) { // check your plugin namespace does not already exist
$.extend({ // this will allow you to add your plugin to the jQuery lib
myExample: function(elm, command, args) {
// keep in mind, right here you might want to do a class or data check to determine which direction this call is going
// for example, upon init the plugin on an element you may add the plugin name as a class,
// this way, when it's recalled, you can see it alrady has that class and might be calling a command,
// thus make an if statemnt to push the process through
return elm.each(function(index){
// do work to each element as its passed through
// be sure to use something like
// return elm.each(function(e) { dor work });
// as your final statement in order to maintain "chainability"
});
}
});
$.fn.extend({ // this gives the chainability functionality seen with $ funcs like: $("#eleID").css("color", "red") <--returns original element object
myExample: function(command) {
return $.myExample($(this), command, Array.prototype.slice.call(arguments, 1));
}
});
$.myExample.props = { // Here you can establish specific properties to your plugin, prehaps even make them "Over-writable"
key1: "value",
key2: "value"
};
$.myExample.methods = { // Here you can establish specific methods/functions for your plguin to carry out and maintain your namespace as well
key1: function(param) {
/* do work */
},
key2: function(param) {
/* do work */
}
};
// This next part is not seen in many plugins but useful depending on what you're creating
$.myExample.init = function(param) { // If you have an initialize method to apply, namespace it in here and calll on initializing your plugin
var key = "value",
key2 = {
subKey: "value"
};
/*
/ run any number of initializing functions here
/ I prefer to make my param a value that can be a
/ string with a possible object
/ the string for holding a base configuration
/ the object for any change in properties or base values for that config
*/
};
$.myExample.defaults = { // establish base properties here that can be over-written via .props, but their values should never truly change
key1: "value",
key2: {
prop1: {
subKey1: "value",
subKey2: "value"
},
prop2: {
subKey1: "value"
}
},
key3: function(param) {
}
};
}
})(jQuery);

Summary and Best Practices while writing a jQuery Plugin
(function($){
// $('p').greenify() turns all text in p elements green.
$.fn.greenify = function() {
this.css( "color", "green" ); // set text color
return this; // for chaining;
};
})(jQuery);

Related

Adding code to a javascript module pattern from an outside file

First of all I'm pretty new to javascript.
I have wrote a javascript plug-in that filters html records. Using Knockout.js, basically keyword/s are typed into a text box and the plug-in filters through the html records to reveal the records that contain the keyword/s.
I have wrote the javascript using the Module pattern, and would like the opportunity for the .js file to stand alone, whilst also giving the user the opportunity to change ways in which the filter works.
Here is a brief and simple overview of the structure of my .js file:
$(function(){
var s,
Filter = {
settings:{
//default settings
},
initialise: function(){
s = this.settings;
this.someFunction1;
this.someFunction2;
},
someFunction1: function(){
//
},
someFunction2: function(){
//
},
}
Filter.initialise();
});
As you can see, I have specified one function to be called - initialise. Within initialise I have set the variable s (declared at the same level as the module) to point to settings so that all sub functions of the module can access it.
What I want to know is, is it possible for the overriding settings to be passed via the html file that calls the .js file?
Ideally I would like there to be default settings for the plug-in, but give the user the option to specify/override certain settings unique to their need.
Any help would be appreciated. Thanks.
First up, there's a few peculiarities in your code.
One thing is that you have this.someFunction1; (and one for the second function) in your initialize function, but that doesn't quite do anything. It's just a statement.
Another thing is that you declare Filter as an object, but you're missing , (commas) between the various properties.
Finally, you declare someFunction2 twice (though I assume it's an copy/paste error?), and you're missing a semi-colon.
To find these problems you can use a JavaScript linting tool, for example JSHint. Try copy-pasting your question's code there and you'll see all those issues pop up.
If I fix those issues I get to this:
$(function(){
var s,
Filter = {
settings:{
//default settings
},
initialise: function(){
s = this.settings;
},
someFunction1: function(){
//
},
someFunction2: function(){
//
}
};
Filter.initialise();
});
Currently in this code, the Filter is only visible in the outer closure. To make it available to other bits of code you'll have to export it, either to your own namespace object or as a jQuery plugin.
The first option is possible, but will require a bit more work and assumptions about your setup. So let me stick to showing the second option. The jQuery's plugin tutorial is pretty good, but I've based the following code on this blogpost because it's a bit more complete IMO:
(function($) {
$.filter = function(element, options) {
var defaults = {
// default settings
}
var filter = this;
filter.settings = {};
var initialise = function() {
filter.settings = $.extend({}, defaults, options);
filter.element = element;
// code goes here
}
// This function is *public*, just save it in a 'var' instead of setting it
// as a property of 'plugin' to keep it private to your plugin.
filter.someFunction1 = function() {
//
}
filter.someFunction2 = function() {
//
}
initialise();
}
})(jQuery);
In this code the jQuery extend function is used above to extend default settings with user provided options.
You can call your plugin in its most basic form like this:
var options = { filterEmptyOptions: true, showTimeZone: false, /* etc */ };
$.filter($('#myDiv'), options);
Additionally you could save the result of last line and call the plugin's public methods later on.

Can you use a JS object as the interface for a JQuery plugin?

I've had a look at this thread: How to create a jQuery plugin with methods?, and while there are plenty of solutions regarding multi-function plugins, I'm interested if it's possible to use an object so that you don't have ugly constructions like $("selector").plugin().dostuff(), and instead can use it more like this: $("selector").plugin.dostuff(), ie 'plugin' is an object not a function.
I can write the plugin like this:
$.fn.plugin = {
dostuff: function() {},
domorestuff: function(){}
};
But then the inner functions won't have access to the JQuery object that's calling it in the first place, as this returns the plugin object. Is there any way to structure a plugin based around an object that would work with JQuery?
No, and for the reason you gave: You lose this, and this is hugely important when writing a plugin. To get this, your plugin must be a function.
You basically have three ways of implementing methods:
Using string arguments, e.g.:
$("selector").plugin("dostuff");
...where you dispatch to your handler methods within the plugin function. This is by far the most popular way. It's the way used by jQuery UI, Bootstrap, and others. Full example of this below.
Using the "ugly construction" as you put it, where your plugin is a function and it returns an object (a new object each time, to preserve this) with functions you can call.
Adding several plugin methods to jQuery rather than just one, using a prefix of some kind, so it ends up being $("selector").pluginDoThis(); and $("selector").pluginDoThat(); and $("selector").pluginDoTheOther(); The key is to use a prefix to avoid name conflicts. I've only seen this done once, a long time ago, and I haven't seen that plugin in a while. Not really a popular choice.
I just recently posted this other answer showing the full pattern for #1 (in their case, the methods were callThis and destroy), e.g.:
// Create the plugin
(function ($) {
var methods = {
init: function(options) {
// Determine options
var opts = $.extend({
opacity: 0.5
}, options);
// Remember them
this.data("pluginname", opts);
// Initial stuff
this.css("opacity", opts.opacity);
},
callThis: function(opts) {
// Use 'opts' if relevant
this.css("display","none");
},
destroy: function(opts) {
this.removeData("pluginame");
this.css("display", "").css("opacity", "");
}
};
jQuery.fn.pluginname = function (options) {
var method, args;
// Method?
if (typeof options === "string") {
// Yes, grab the name
method = options;
// And arguments (we copy the arguments, then
// replace the first with our options)
args = Array.prototype.slice.call(arguments, 0);
// Get our options from setup call
args[0] = this.data("pluginname");
if (!args[0]) {
// There was no setup call, do setup with defaults
methods.init.call(this);
args[0] = this.data("pluginname");
}
}
else {
// Not a method call, use init
method = "init";
args = [options];
}
// Do the call
methods[method].apply(this, args);
};
})(jQuery);
// Example usage
function doInit() {
$("#target").pluginname();
setTimeout(doCallThis, 700);
}
function doCallThis() {
$("#target").pluginname("callThis");
setTimeout(doDestroy, 700);
}
function doDestroy() {
$("#target").pluginname("destroy");
setTimeout(doInit, 700);
}
setTimeout(doInit, 700);
<div id="target">This is the target</div>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

Object Literal or Modular Javascript Design Pattern

This may have already been asked lots of times, and I've searched around SO but so far all the answers I read aren't exactly what I'm looking for.
I'm working on a website with moderate DOM elements showing/hiding, some AJAX calls, and probably something else. So I'll be having two main script files (HTML5 Boilerplate standard)
plugins.js // third party plugins here
site.js // all my site specific code here
Previously I'm using object literal design pattern, so my site.js is something like this:
var site = {
version: '0.1',
init: function() {
site.registerEvents();
},
registerEvents: function() {
$('.back-to-top').on('click', site.scrollToTop);
},
scrollToTop: function() {
$('body').animate({scrollTop: 0}, 400);
}
};
$(function() {
site.init();
});
So far so good, it's nicely readable, all methods are public (I kinda like this, as I can test them via Chrome Dev Tools directly if necessary). However, I intend to decouple some of the site's functionality into more modular style, so I want to have something like this below the code above (or in separate files):
site.auth = {
init: function() {
site.auth.doms.loginButton.on('click', site.auth.events.onLoginButtonClicked);
},
doms: {
loginButton: $('.login'),
registerButton: $('.register')
},
events: {
onLoginButtonClicked: function() {
}
},
fbLogin: function() {
}
};
site.dashboard = {
};
site.quiz = {
};
// more modules
As you can see, it is very readable. However there is one obvious downside, which is I have to write code like site.auth.doms.loginButton and site.auth.events.onLoginButtonClicked. Suddenly it becomes hard to read, and it will only grow longer the more complex the functionality gets. Then I tried the modular pattern:
var site = (function() {
function init() {
$('.back-to-top').on('click', scrollToTop);
site.auth.init();
}
function scrollToTop() {
$('body').animate({scrollTop: 0}, 400);
}
return {
init: init
}
})();
site.auth = (function() {
var doms = {
loginButton: $('.login'),
registerButton: $('.register')
};
function init() {
doms.loginButton.on('click', onLoginButtonClicked);
}
function onLoginButtonClicked() {
}
return {
init: init
}
})();
// more modules
As you can see, those long names are gone, but then I guess I have to init all other modules in the site.init() function to construct them all? Then I have to remember to return the functions that need to be accessible by other modules. Both of them are okay I guess albeit a bit of a hassle, but overall, am I onto a better workflow working with modular pattern?
The correct answer, here, of course, is: "it depends".
If you're totally okay with all data and all methods, for every section of your site being 100% public, then just using a single literal (or multiple literals), with nested objects if desired, is totally fine, assuming that you can keep it from turning into one gigantic ball of code.
If you want any kind of private state, which has any kind of persistence (ie: doesn't reset every time you run a function), then the revealing-module is great.
That said:
It's not a requirement of the revealing-module for you to have an .init method, at all.
If your module can be self-contained, then just focus on exporting what you WOULD like to make public.
To this end, when I'm writing code which a team might look at, later, I'm finding myself creating a public_interface object and returning it (the named version of the anonymous object you return).
The benefit of this is minimal, except to add the understanding that anything which needs to be made public needs to be appended to the interface.
The way you're currently using it:
var module = (function () { /* ... */ return {}; }());
module.submodule = (function () { /*...*/ return {}; }());
Is no better or worse than literals, because you can just as easily do this:
var module = {
a : "",
method : function () {},
meta : { }
};
module.submodule = {
a : "",
method : function () {},
meta : { }
};
Until you hit something which doesn't work for you, work with what fills your needs.
Personally, I'll typically build any data-only objects as literals: config-objects, objects which come in from other connections, etc...
Any dirt-simple object which requires maybe one or two methods, and can be built by nesting only one or two levels deep, I might build literally, as well (as long as it doesn't require initialization).
// ex:
var rectangle = {
width : 12,
height : 24,
area : 0,
perimeter : 0,
init_area : function () { this.area = this.width * this.height; return this; }, // buh...
init_perimeter : function () { this.perimeter = (this.width * 2) + (this.height * 2); return this; } // double-buh...
}.init_area().init_perimeter();
If I needed several of these, perhaps I'd make a constructor.
But if I only ever needed one of something unique like this, wouldn't it save me some headaches to just do something like this:
var rectangle = (function (width, height) {
var public_interface = {
width : width,
height : height,
area : width * height,
perimeter : (2 * width) + (2 * height)
};
return public_interface;
}(12, 24));
If there were more-advanced calculations required, I could keep any extra vars private, and work on them from the inside.
If I needed to have sensitive data inside of an object, and functions to work on that data, then I could have public-functions which call those private functions, and return results, rather than providing access.
Also, if I refactor my code, and decide to rename rectangle at some point, then any functions nested 3 or more deep, which are referring to rectangle will have to be modified, as well.
Again, if you're structuring your methods so that they don't need to directly ask for any object which is further up than this, then you won't have this problem...
...but if you have an interface that looks like:
MyApp.myServices.webService.send();
and it's expecting to find:
MyApp.appData.user.tokens.latest; // where personally, I might leave tokens in a closure
If you change the structure of your appData module, you're going to have all kinds of errors in your webService module, until you find every reference to the old format, and rename them all.

What is a way to make JQuery plugin extendible?

I try to move some common application specific actions to jQuery plug-in by:
$.fn.extpoint = function() {...}
But I don't want to declare several extension points:
$.fn.extpoint1 = function() {...}
$.fn.extpoint2 = function() {...}
...
Instead I would like to use syntax sugar like:
$("#id").extpoint.func1().extpoint.func2()
With definition:
$.fn.extpoint = {}
$.fn.extpoint.func1 = function() {
this.val();
this.data("ip");
...
return this;
}
and call:
$("#id").extpoint.func1(...)
this point to $.fn.extpoint (dictionary with func1, func2, ... elements) instead of original jQuery object, when func1 evaluated.
Is it possible to make jQuery plug-in extendible?
PS. It is possible to pass function name as first argument to $.fn.extpoint and implement $.fn.extpoint('extend', func) call to extend (save to internal dictionary association between names and implementations) extension point. In that case use-cases look like:
$("#id").extpoint('func1', ...).extpoint('func2', ...)
but I look for way to make in more syntactic sugar...
The task I ask is hard to implement.
Official docs say:
Under no circumstance should a single plugin ever claim more than one namespace in the jQuery.fn object:
(function( $ ){
$.fn.tooltip = function( options ) {
// THIS
};
$.fn.tooltipShow = function( ) {
// IS
};
$.fn.tooltipHide = function( ) {
// BAD
};
})( jQuery );
This is a discouraged because it clutters up the $.fn namespace. To remedy this, you should collect all of your plugin's methods in an object literal and call them by passing the string name of the method to the plugin.
Another approach is maintain link to this as in http://code.google.com/p/jquery-plugin-dev/source/browse/trunk/jquery.plugin.js
So your calls looks like:
$.fn.addPlugin('test2', {
__construct : function(alertText) { alert(alertText); },
alertAttr : function(attr) { alert($(this).attr(attr)); return this; },
alertText : function() { alert($(this).text()); return this; }
});
$('#test2').bind('click', function() {
var btn = $(this);
btn.test2('constructing...').alertAttr('id').alertText().jQuery.text('clicked!');
setTimeout(function() {
btn.text('test2');
}, 1000);
});
Some related links:
http://milan.adamovsky.com/2010/02/how-to-write-advanced-jquery-plugins.html
http://milan.adamovsky.com/2010/09/jquery-plugin-pattern-20.html
http://ludw.se/blog/articles/19/patching-milans-jquery-plugin-pattern-for-jquery-16
http://code.google.com/p/jquery-plugin-dev/source/browse/trunk/jquery.plugin.js
Old style plug-in extention:
http://docs.jquery.com/Plugins/Authoring
jQuery Plugin Authoring and Namespacing
http://coding.smashingmagazine.com/2011/10/11/essential-jquery-plugin-patterns/
http://mahtonu.wordpress.com/2010/09/20/jquery-plugin-authoring-step-by-step/
http://www.capricasoftware.co.uk/corp/template.php
Here is an overview of creating a plugin. I believe what you are asking about is called "chaining". It is what makes jQuery so easy to use, and it's good that you want to make sure that you are implementing it correctly.
The key thing to remember while developing your plugin in regards to chaining is to always return this; from your methods. That is what will allow you to keep the chain going.

jQuery: plugin inter-communication

Here is the problem:
I have a very complex plugin that does lots of different initialization and binding when it is executed.
I want to be able to run the same plugin multiple times on the same element, giving it different options. After it runs once on the element, certain initialization does not need to be done again on subsequent executions on that element.
Currently the plugin code is inside of a closure and it doesnt know anything about other times the same plugin has run on the element.
Is there a pattern that people follow when they want inter-communication?
I am thinking of something like this:
$.plugin = {
globalRefs = [];
}
$.fn.plugin = function() {
var that = {};
$.fn.plugin.id ++; //each execution gets its unique id
var privateFn = function() { ... };
that.privateFn = privateFn; //expose all useful inner functions to that.
$.plugin.globalRefs[$.fn.plugin.id] = that; //make that global
}
$.fn.plugin.id = 0;
You talk about "other plugins", but it's not clear what you mean by that; what other plugins? What do they need to "know" about each other?
If you just want to maintain state, why not just use the jQuery data() mechanism to store whatever you need right on the target DOM elements? That would let your plugin find out about previous invocations, and it would also allow these mysterious "other plugins" to use that stored data too.
// ...
$(theElement).data('pluginName', { 'fabulous': 'data' });
The data that you store with this mechanism can be anything you like:
$(theElement).data('pluginName', {
'aNumber': 23.5,
'anArray': ['hello', 'world'],
'aFunction': function(arg) {
alert("wow a function! Here is the argument: " + arg);
}
'anObject': {
'more': 'stuff'
}
});

Categories

Resources