Authoring a Custom Plugin
In this page:
(function ($) {
$.fn.pluginName = function (options) {
var settings = $.extend({ option: defaultValue }, options);
return this.each(function () {
// plugin logic
});
};
})(jQuery);
Start a Plugin
Writing a plugin starts by attaching a named function directly to $.fn, so it can be invoked the same way as any of jQuery's own built-in methods, like $('.box').myPlugin(). The function itself typically receives an options object as its argument.
Example: Start a Plugin
<!DOCTYPE html>
<html>
<head>
<script src="https://code.jquery.com/jquery-3.7.1.min.js"></script>
<style>
button { padding:6px 14px; margin:4px; background:#2c6aa0; color:white; border:none; border-radius:4px; cursor:pointer; }
#resetBtn { background:white; color:#2c6aa0; border:1px solid #2c6aa0; }
#output { margin-top:10px; padding:8px; border:1px solid #ccc; border-radius:4px; background:#f7f7f7; font-family:monospace; min-height:24px; }
#demo :where(p, div, span, li, h1, h2, h3, h4, td, th, blockquote, label, section, article, aside) { border:1px solid #4a7fb5; background:#eaf2fb; padding:6px 10px; margin:4px 0; border-radius:4px; }
#demo :where(ul, ol) { border:1px dashed #888; background:#fafafa; padding:8px 8px 8px 32px; margin:6px 0; }
#demo :where(table) { border-collapse:collapse; }
#demo :where(td, th) { border-radius:0; }
#demo :where(input, select, textarea) { margin:4px 0; }
</style>
</head>
<body>
<button id="runBtn">Run</button>
<button id="resetBtn">Reset</button>
<section id="demo">
<div class="box">Box</div>
</section>
<div id="output"></div>
<script>
var original = $("#demo").html();
$("#runBtn").click(function() {
$.fn.myPlugin = function() {
return this.css("border", "2px solid blue");
};
$(".box").myPlugin();
});
$("#resetBtn").click(function() {
$("#demo").html(original);
$("#output").empty();
});
</script>
</body>
</html>
Add Options
Options make a plugin flexible enough to be reused across different situations, and defining sensible defaults means the plugin still works correctly even when the caller supplies no options at all. Merging user-supplied options over the defaults, usually with $.extend(), is the standard way to combine the two.
Example: Add Options
<!DOCTYPE html>
<html>
<head>
<script src="https://code.jquery.com/jquery-3.7.1.min.js"></script>
<style>
button { padding:6px 14px; margin:4px; background:#2c6aa0; color:white; border:none; border-radius:4px; cursor:pointer; }
#resetBtn { background:white; color:#2c6aa0; border:1px solid #2c6aa0; }
#output { margin-top:10px; padding:8px; border:1px solid #ccc; border-radius:4px; background:#f7f7f7; font-family:monospace; min-height:24px; }
#demo :where(p, div, span, li, h1, h2, h3, h4, td, th, blockquote, label, section, article, aside) { border:1px solid #4a7fb5; background:#eaf2fb; padding:6px 10px; margin:4px 0; border-radius:4px; }
#demo :where(ul, ol) { border:1px dashed #888; background:#fafafa; padding:8px 8px 8px 32px; margin:6px 0; }
#demo :where(table) { border-collapse:collapse; }
#demo :where(td, th) { border-radius:0; }
#demo :where(input, select, textarea) { margin:4px 0; }
</style>
</head>
<body>
<button id="runBtn">Run</button>
<button id="resetBtn">Reset</button>
<section id="demo">
<div class="box">Box</div>
</section>
<div id="output"></div>
<script>
var original = $("#demo").html();
$("#runBtn").click(function() {
$.fn.myPlugin = function(options) {
const settings = $.extend({color: "blue"}, options);
return this.css("border", "2px solid " + settings.color);
};
$(".box").myPlugin({color: "red"});
});
$("#resetBtn").click(function() {
$("#demo").html(original);
$("#output").empty();
});
</script>
</body>
</html>
Use each for Elements
Use each() inside a plugin whenever it needs to perform its operation separately for every element in the current selection, since a plugin might be called on one element or on many at once. Looping explicitly with each() ensures the plugin behaves correctly either way.
Example: Use each for Elements
<!DOCTYPE html>
<html>
<head>
<script src="https://code.jquery.com/jquery-3.7.1.min.js"></script>
<style>
button { padding:6px 14px; margin:4px; background:#2c6aa0; color:white; border:none; border-radius:4px; cursor:pointer; }
#resetBtn { background:white; color:#2c6aa0; border:1px solid #2c6aa0; }
#output { margin-top:10px; padding:8px; border:1px solid #ccc; border-radius:4px; background:#f7f7f7; font-family:monospace; min-height:24px; }
#demo :where(p, div, span, li, h1, h2, h3, h4, td, th, blockquote, label, section, article, aside) { border:1px solid #4a7fb5; background:#eaf2fb; padding:6px 10px; margin:4px 0; border-radius:4px; }
#demo :where(ul, ol) { border:1px dashed #888; background:#fafafa; padding:8px 8px 8px 32px; margin:6px 0; }
#demo :where(table) { border-collapse:collapse; }
#demo :where(td, th) { border-radius:0; }
#demo :where(input, select, textarea) { margin:4px 0; }
</style>
</head>
<body>
<button id="runBtn">Run</button>
<button id="resetBtn">Reset</button>
<section id="demo">
<div class="box">One</div><div class="box">Two</div>
</section>
<div id="output"></div>
<script>
var original = $("#demo").html();
$("#runBtn").click(function() {
$("#output").empty();
$.fn.myPlugin = function() {
return this.each(function() {
$(this).css("border", "2px solid blue");
});
};
$(".box").myPlugin();
});
$("#resetBtn").click(function() {
$("#demo").html(original);
$("#output").empty();
});
</script>
</body>
</html>
Avoid Global Variables
Plugin code should keep its helper variables private rather than creating them as globals, since global names can silently collide with other scripts running on the same page. Wrapping the plugin in a closure — a function that creates its own private scope — is a simple, standard way to achieve this.
Example: Avoid Global Variables
<!DOCTYPE html>
<html>
<head>
<script src="https://code.jquery.com/jquery-3.7.1.min.js"></script>
<style>
button { padding:6px 14px; margin:4px; background:#2c6aa0; color:white; border:none; border-radius:4px; cursor:pointer; }
#resetBtn { background:white; color:#2c6aa0; border:1px solid #2c6aa0; }
#output { margin-top:10px; padding:8px; border:1px solid #ccc; border-radius:4px; background:#f7f7f7; font-family:monospace; min-height:24px; }
#demo :where(p, div, span, li, h1, h2, h3, h4, td, th, blockquote, label, section, article, aside) { border:1px solid #4a7fb5; background:#eaf2fb; padding:6px 10px; margin:4px 0; border-radius:4px; }
#demo :where(ul, ol) { border:1px dashed #888; background:#fafafa; padding:8px 8px 8px 32px; margin:6px 0; }
#demo :where(table) { border-collapse:collapse; }
#demo :where(td, th) { border-radius:0; }
#demo :where(input, select, textarea) { margin:4px 0; }
</style>
</head>
<body>
<button id="runBtn">Run</button>
<button id="resetBtn">Reset</button>
<section id="demo">
<div class="box">Box</div>
</section>
<div id="output"></div>
<script>
var original = $("#demo").html();
$("#runBtn").click(function() {
(function($) {
$.fn.myPlugin = function() {
const borderStyle = "2px solid blue";
return this.css("border", borderStyle);
};
})(jQuery);
$(".box").myPlugin();
});
$("#resetBtn").click(function() {
$("#demo").html(original);
$("#output").empty();
});
</script>
</body>
</html>
Complete Custom Plugin
A genuinely useful, reusable plugin combines a clear, specific name; sensible defaults; a flexible options object; chainability by returning this; and straightforward internal logic that does one job well rather than trying to do everything.
Example: Complete Custom Plugin
<!DOCTYPE html>
<html>
<head>
<script src="https://code.jquery.com/jquery-3.7.1.min.js"></script>
<style>
button { padding:6px 14px; margin:4px; background:#2c6aa0; color:white; border:none; border-radius:4px; cursor:pointer; }
#resetBtn { background:white; color:#2c6aa0; border:1px solid #2c6aa0; }
#output { margin-top:10px; padding:8px; border:1px solid #ccc; border-radius:4px; background:#f7f7f7; font-family:monospace; min-height:24px; }
#demo :where(p, div, span, li, h1, h2, h3, h4, td, th, blockquote, label, section, article, aside) { border:1px solid #4a7fb5; background:#eaf2fb; padding:6px 10px; margin:4px 0; border-radius:4px; }
#demo :where(ul, ol) { border:1px dashed #888; background:#fafafa; padding:8px 8px 8px 32px; margin:6px 0; }
#demo :where(table) { border-collapse:collapse; }
#demo :where(td, th) { border-radius:0; }
#demo :where(input, select, textarea) { margin:4px 0; }
</style>
</head>
<body>
<button id="runBtn">Run</button>
<button id="resetBtn">Reset</button>
<section id="demo">
<div class="box">Box</div>
</section>
<div id="output"></div>
<script>
var original = $("#demo").html();
$("#runBtn").click(function() {
$("#output").empty();
(function($) {
$.fn.myPlugin = function(options) {
const settings = $.extend({color: "blue"}, options);
return this.each(function() {
$(this).css("border", "2px solid " + settings.color);
});
};
})(jQuery);
$(".box").myPlugin({color: "green"});
});
$("#resetBtn").click(function() {
$("#demo").html(original);
$("#output").empty();
});
</script>
</body>
</html>
- Writing the plugin without
this.each(...), so it only affects the first element in the selection. - Overwriting defaults by assigning
optionsdirectly instead of$.extend({}, defaults, options), losing settings the user did not supply. - Using
$inside the plugin without wrapping it in(function ($) { ... })(jQuery), which breaks when$is reassigned by another library.
Chapter Quiz — Complete all 4 topics to unlock
0/4 topics done
Complete these topics first: