Search code examples
javascriptjqueryecmascript-6babeljsextend

Extend ES6 plugin to jQuery prototype


I would like ask some help because i can't convert my classic jQuery (v2) plugin in ES6 with module and class.

In ECMAScript 5, we can attach jQuery plugin into jQuery prototype like this :

app.js - jQuery loaded via HTML <script> tag

$.fn.myPlugin = function() {};
$('div').myPlugin();

And it works :) . In ES6, I would write something like this:

myPlugin.es6 :

import $ from 'jquery';

export default class myPlugin extends $ {
 // Could i use constructor() method ???
}

app.es6 :

import $ from 'jquery';
import myPlugin from 'myPlugin.es6';

$('div').myPlugin();

And finally, it's not working ...
I've search and no people ask this question before.
I use Babel to transpile ES6 into ES5.


Solution

  • $.fn is just an object. There is no magic upon adding a new property to the prototype of $. So, the code $.fn.myPlugin = function() {} is equal to $.prototype.myPlugin = function() {}.

    $.fn === $.prototype; // true

    To be able to call a function on the $ object in a standard way ($('div').func()), you need to add this function to the $ object.

    You're not adding it in your es6 code.

    Thus,

    import $ from 'jquery';
    
    export default class myPlugin extends $ {
     // Could i use constructor() method ???
    }
    

    Means (almost)

    var myPlugin = function() {};
    
    myPlugin.prototype = Object.create($.prototype);
    
    return { default: myPlugin };
    

    I'm not sure you should extend $.fn, but maybe you need it.

    And with

    import $ from 'jquery';
    import myPlugin from 'myPlugin.es6';
    

    it means

    var $ = require('jquery');
    var myPlugin = require('myPlugin'); // a reference to the 'export.default' object from 'myPlugin.es6'
    

    Therefore, there is no connection between $.fn object and myPlugin function.

    You should create the connection somewhere. It could be in a special module like plugins where you'll inject all needed plugins into the $.fn object:

    import $ from 'jquery';
    import plugin1 from 'plugin1.es6'; // should contain 'name'
    import plugin2 from 'plugin2.es6';
    ...
    import plugin10 from 'plugin10.es6';
    
    [plugin1, plugin2, ..., plugin10].forEach(plugin => $.fn[plugin.name] = plugin);
    

    Or you could add an 'initialize' method to the exported object in 'myPlugin.es6', and call it before first use: init($) { $.fn.myPlugin = myPlugin; }

    And so on.