Writing jQuery extensions
When we use the method of jQuery object, because jQuery object can operate a set of DOM and support chain operation, it is very convenient to use.
But jQuery's built-in approach will never meet all the requirements. For example, we want to highlight some DOM elements, which can be achieved with jQuery:
$('span.hl').css('backgroundColor', '#fffceb').css('color', '#d85030');
$('p a.hl').css('backgroundColor', '#fffceb').css('color', '#d85030');
It's not good to always write duplicate code. In case it's more difficult to modify the font later, can we unify it and write a highlight() method?
$('span.hl').highlight();
$('p a.hl').highlight();
The answer is yes. We can extend jQuery to implement custom methods. In the future, if you want to modify the highlighted logic, you only need to modify one extension code. This approach is also known as writing jQuery plug-ins.
A new way to bind jQuery objects is by extending the $. fn object. Let's write the first extension, highlight1():
$.fn.highlight1 = function () {
// this is bound to the current jQuery object:
this.css('backgroundColor', '#fffceb').css('color', '#d85030');
return this;
}
Notice that this inside the function is bound to a jQuery object when invoked, so the code inside the function can call all the methods of the jQuery object normally.
For the following HTML structure:
<!-- HTML structure -->
<div id="test-highlight1">
<p>What is?<span>jQuery</span></p>
<p><span>jQuery</span>It's the most popular one at present.<span>JavaScript</span>Library.</p>
</div>
To test the effect of highlight1():
'use strict';
$('#test-highlight1 span').highlight1();
Careful children's shoes may be found, why return this last;? Because jQuery objects support chain operations, our own extension methods should continue to be chained:
$('span.hl').highlight1().slideDown();
Otherwise, when the user calls, he has to split the above code into two lines.
But this version is not perfect. Some users hope that the highlighted color can be specified by themselves. What should we do?
We can add a parameter to the method so that the user can pass the parameter in with the object himself. So we have a second version of highlight 2 ():
$.fn.highlight2 = function (options) {
// Consideration should be given to various situations:
// options is undefined
// options have only a few key s
var bgcolor = options && options.backgroundColor || '#fffceb';
var color = options && options.color || '#d85030';
this.css('backgroundColor', bgcolor).css('color', color);
return this;
}
For the following HTML structures:
<!-- HTML structure -->
<div id="test-highlight2">
<p>What is?<span>jQuery</span> <span>Plugin</span></p>
<p>To write<span>jQuery</span> <span>Plugin</span>Can be used to extend<span>jQuery</span>Functions.</p>
</div>
To measure highlight 2 ():
'use strict';
$('#test-highlight2 span').highlight2({
backgroundColor: '#00a8e6',
color: '#ffffff'
});
For the default value processing, we use a simple & and | short-circuit operator, always get a valid value.
Another method is to use the auxiliary method $. extend(target, obj1, obj2,...) provided by jQuery, which merges the attributes of multiple object objects into the first target object. When encountering the same name attribute, it always uses the value of the object that is later, that is, the higher the priority is later:
// Merge default values and user-passed options into the object {} and return:
var opts = $.extend({}, {
backgroundColor: '#00a8e6',
color: '#ffffff'
}, options);
Then the user put forward his opinion on highlight2(). Every call needs to pass in custom settings. Can I set a default value for myself, and use the parameterized highlight2() for future calls?
That is to say, the default values we set should allow users to modify them.
Which is the appropriate default value? It's certainly not appropriate to place global variables, and the best place is the $. fn.highlight2 function object itself.
So the final version of highlight() was born at last:
$.fn.highlight = function (options) {
// Merge defaults and user settings:
var opts = $.extend({}, $.fn.highlight.defaults, options);
this.css('backgroundColor', opts.backgroundColor).css('color', opts.color);
return this;
}
// Set default values:
$.fn.highlight.defaults = {
color: '#d85030',
backgroundColor: '#fff8de'
}
The user is satisfied at last. Users only need to set default values at one time when using:
$.fn.highlight.defaults.color = '#fff';
$.fn.highlight.defaults.backgroundColor = '#000';
Then you can call highlight() very simply.
For the following HTML structure:
<!-- HTML structure -->
<div id="test-highlight">
<p>How to Write<span>jQuery</span> <span>Plugin</span></p>
<p>To write<span>jQuery</span> <span>Plugin</span>,To set<span>Default values</span>,And allow users to modify<span>Default values</span>,Or run-time incoming<span>Other values</span>. </p>
</div>
Measure the effect of modifying the default value:
'use strict';
$.fn.highlight.defaults.color = '#659f13';
$.fn.highlight.defaults.backgroundColor = '#f2fae3';
$('#test-highlight p:first-child span').highlight();
$('#test-highlight p:last-child span').highlight({
color: '#dd1144'
});
Finally, we came up with the principle of writing a jQuery plug-in:
- Bind function to $. fn to realize the code logic of the plug-in.
- The plug-in function finally returns this to support chain invocation.
- Plug-in functions should have default values, which are bound to $. fn. < plugin Name >. defaults;
- Users can pass in a set value when invoking to override the default value.
Extensions for specific elements
We know that some methods of jQuery objects can only work on specific DOM elements, such as submit() methods that can only work on form s. What if we write extensions only for certain types of DOM elements?
Remember that jQuery selector supports filter() method filtering? We can use this method to achieve expansion for specific elements.
For example, now let's add jump hints to all hyperlinks pointing to the outside chain. What can we do?
Write the code that the user calls first:
$('#main a').external();
Then write an external extension as described above:
$.fn.external = function () {
// each() returned by return returns the result, supporting chain invocation:
return this.filter('a').each(function () {
// Note: this of the callback function inside each() is bound to the DOM itself!
var a = $(this);
var url = a.attr('href');
if (url && (url.indexOf('http://')===0 || url.indexOf('https://')===0)) {
a.attr('href', '#0')
.removeAttr('target')
.append(' <i class="uk-icon-external-link"></i>')
.click(function () {
if(confirm('You're sure you're going.' + url + '?')) {
window.open(url);
}
});
}
});
}
For the following HTML structure:
<!-- HTML structure -->
<div id="test-external">
<p>How to Learn<a href="http://jquery.com">jQuery</a>?</p>
<p>First of all, you have to learn.<a href="/wiki/001434446689867b27157e896e74d51a89c25cc8b43bdb3000">JavaScript</a>,And understand the basics<a href="https://developer.mozilla.org/en-US/docs/Web/HTML">HTML</a>. </p>
</div>
Measured external chain effect:
'use strict';
$('#test-external a').external();
Summary
Extending jQuery objects is very simple, but we have to follow the principle of jQuery. The extended methods we write can support chain invocation, have default values and filter specific elements, making the extended methods look like the methods of jQuery itself.