├── renderers
├── rendererSkeleton.js
├── example
│ └── helloWorldRenderer.js
└── README.md
├── plugins
├── README.md
├── external
│ ├── README.md
│ ├── example
│ │ └── helloWorldPlugin.js
│ └── externalPluginSkeleton.js
└── internal
│ ├── README.md
│ ├── example
│ └── helloWorldPlugin.js
│ └── internalPluginSkeleton.js
├── LICENSE
└── README.md
/renderers/rendererSkeleton.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Sample renderer skeleton.
3 | *
4 | * @param {Object} instance Currently processed Handsontable instance.
5 | * @param {HTMLElement} td Currently rendered cell TD element.
6 | * @param {Number} row Row index.
7 | * @param {Number} col Column index.
8 | * @param {String|Number} prop Column index or property name.
9 | * @param {String} value Cell contents.
10 | * @param {Object} cellProperties Currently processed cell properties object, containing the cell's metadata.
11 | */
12 | function rendererSkeleton(instance, td, row, col, prop, value, cellProperties) {
13 |
14 | // Sample operation on the cell. In this case, we modify the currently rendered cell's style property.
15 | if (row === 0 && col === 0) {
16 | td.style.fontWeight = 'bold';
17 | }
18 | }
--------------------------------------------------------------------------------
/plugins/README.md:
--------------------------------------------------------------------------------
1 | # Plugins
2 |
3 | ## What is a plugin?
4 | Basically, a plugin is a class which extends the original functionality of Handsontable.
5 |
6 | ## Internal or external?
7 | If you wish to make your own Handsontable build, it's a good idea to choose the internal approach.
8 | This way you'll simply need to include a customized `handsontable.js` (or `handsontable.full.js`, [see the difference](https://github.com/handsontable/handsontable/tree/master/dist)) to your website.
9 |
10 | However, if you want to add a new functionality to the Handsontable without making your own build, and you don't mind linking more files to your site, you can go with the external approach.
11 |
12 | * [Internal plugin details](internal)
13 | * [External plugin details](external)
14 |
15 | Regardless of the chosen approach, you can access any plugin's instance by calling:
16 | ```js
17 | handsontableInstance.getPlugin('nameOfThePlugin');
18 | ```
--------------------------------------------------------------------------------
/plugins/external/README.md:
--------------------------------------------------------------------------------
1 | ## External plugin approach
2 | * The plugin code doesn't need to be written in [ES6](http://www.ecma-international.org/ecma-262/6.0/),
3 | * Your class has to extend the [BasePlugin](https://github.com/handsontable/handsontable/blob/master/src/plugins/_base.js) class,
4 | * Your plugin files need to be included to your site, see the following example:
5 | ```html
6 |
7 |
8 | ```
9 |
10 | ## Quick start step by step tutorial
11 | * Copy the [externalPluginSkeleton.js](externalPluginSkeleton.js) file and rename it to describe your plugin. Let's use `myPlugin.js` for this example.
12 | * Change the class name to fit the filename, in our case:
13 | ```js
14 | function MyPlugin(hotInstance) {
15 | ```
16 | and in the method definitions:
17 | ```js
18 | // for example
19 | MyPlugin.prototype.isEnabled = function() {
20 | }
21 | ```
22 | * Implement your functionality using the guidelines from the comments,
23 | * Include the `handsontable.full.js` and `myPlugin.js` files on your website, and you're good to go!
24 | ```html
25 |
26 |
27 | ```
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | (The MIT License)
2 |
3 | Copyright (c) 2012-2014 Marcin Warpechowski
4 | Copyright (c) 2015 Handsoncode sp. z o.o.
5 |
6 | Permission is hereby granted, free of charge, to any person obtaining
7 | a copy of this software and associated documentation files (the
8 | 'Software'), to deal in the Software without restriction, including
9 | without limitation the rights to use, copy, modify, merge, publish,
10 | distribute, sublicense, and/or sell copies of the Software, and to
11 | permit persons to whom the Software is furnished to do so, subject to
12 | the following conditions:
13 |
14 | The above copyright notice and this permission notice shall be
15 | included in all copies or substantial portions of the Software.
16 |
17 | THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
18 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
20 | IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
21 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
22 | TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
23 | SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24 |
--------------------------------------------------------------------------------
/renderers/example/helloWorldRenderer.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Hello world renderer. It renders "Hello World!" in a cell, when it's value equals "hello" and "Handsontable is awesome!",
3 | * when it's value is "handsontable". It also changes the cell's background color.
4 | *
5 | * @param {Object} instance Currently processed Handsontable instance.
6 | * @param {HTMLElement} td Currently rendered cell TD element.
7 | * @param {Number} row Row index.
8 | * @param {Number} col Column index.
9 | * @param {String|Number} prop Column index or property name.
10 | * @param {String} value Cell contents.
11 | * @param {Object} cellProperties Currently processed cell properties object, containing the cell's metadata.
12 | */
13 | function helloWorldRenderer(instance, td, row, col, prop, value, cellProperties) {
14 | var changed = false;
15 |
16 | if (value && value.toString().toLowerCase() === 'hello') {
17 | td.textContent = 'Hello World!';
18 | changed = true;
19 |
20 | } else if (value && value.toString().toLowerCase() === 'handsontable') {
21 | td.textContent = 'Handsontable is awesome!';
22 | changed = true;
23 |
24 | } else {
25 | td.textContent = value;
26 | }
27 |
28 | if (changed) {
29 | td.style.background = '#E5EDEF';
30 | } else {
31 | td.style.background = '';
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Handsontable Skeleton
2 |
3 | ## What is it?
4 | This repo contains the sample structures of components commonly used in Handsontable.
5 |
6 | Over the last years Handsontable has become more and more complex. Many developers started contributing to this project, too.
7 | If you plan to contribute, or just extend your local implemention's functionality, please use our unified templates, as they help us keep the library easy to maintain and extend.
8 |
9 | #### Currently available:
10 | * [Plugins](plugins)
11 | * [Internal plugins](plugins/internal/)
12 | * [External plugins](plugins/external/)
13 | * [Renderers](renderers)
14 |
15 | ## Why use it?
16 | It's much easier to start with an established structure than create new feautures from scratch.
17 |
18 | This skeleton will save your time and allow to focus on the logic behind the functionality instead of setting up the proper structure.
19 |
20 | ## Who made these?
21 | The Handsontable Skeleton was created by the core Handsontable team.
22 |
23 | ## The License
24 | Handsontable Skeleton is distributed under the [MIT License](LICENSE).
25 |
26 | ## Found a bug?
27 | [Add a new issue](https://github.com/handsontable/handsontable-skeleton/issues/new) or [make a pull request](https://github.com/handsontable/handsontable-skeleton/pulls).
28 |
29 | ## Contact
30 | Get in touch at hello@handsontable.com.
31 |
--------------------------------------------------------------------------------
/renderers/README.md:
--------------------------------------------------------------------------------
1 | # Renderers
2 |
3 | ## What is a renderer?
4 | Renderer is basically a function run every time a cell is being rendered.
5 |
6 | ## Sample renderer step by step tutorial
7 | * Write a function based on the guidelines provided in the [rendererSkeleton.js](rendererSkeleton.js) file,
8 | * Define the renderer in your Handsontable configuration:
9 |
10 | To apply it to every cell in Handsontable:
11 | ```js
12 | var hot = new Handsontable(container1, {
13 | data: data,
14 | renderer: yourRendererFunction
15 | });
16 | ```
17 |
18 | To apply it only to certain columns:
19 | ```js
20 | // This setup would apply your custom renderer only to the second table column.
21 |
22 | var hot = new Handsontable(container1, {
23 | data: data,
24 | columns: [
25 | {},
26 | {renderer: yourRendererFunction}
27 | ]
28 | });
29 | ```
30 |
31 | To apply it to certain cells:
32 | ```js
33 | // This setup would apply your custom renderer only to the cell at coordinates (1,1).
34 |
35 | var hot = new Handsontable(container1, {
36 | data: data,
37 | cells: function(row, col, prop) {
38 | if (row === 1 && col === 1) {
39 | var cellProperties = {};
40 | cellProperties.renderer = yourRendererFunction;
41 |
42 | return cellProperties;
43 | }
44 | }
45 | });
46 | ```
47 |
48 | To read more about custom renderers, see our documentation: http://docs.handsontable.com/demo-custom-renderers.html.
49 |
--------------------------------------------------------------------------------
/plugins/internal/README.md:
--------------------------------------------------------------------------------
1 | # Internal plugin approach
2 |
3 | ## General guidelines
4 | * The plugin code should be written in [ES6](http://www.ecma-international.org/ecma-262/6.0/). The currently supported ES6 features are (listed in our documentation)[http://docs.handsontable.com/tutorial-seven-principles.html],
5 | * Your class has to extend the [BasePlugin](https://github.com/handsontable/handsontable/blob/master/src/plugins/_base.js) class,
6 | * Your plugin files need to be places under `src/plugins/nameOfYourPlugin/` directory to be properly recognized by our builder,
7 | * You need to make your own Handsontable build to incorporate your changes into the Handsontable source. [Learn how to do it in our documentation](http://docs.handsontable.com/tutorial-custom-build.html).
8 |
9 | ## Quick start step by step tutorial
10 | * Copy the [internalPluginSkeleton.js](internalPluginSkeleton.js) file and rename it to describe your plugin. Let's use `myPlugin.js` for this example.
11 | * Change the class name to fit the filename, in our case:
12 | ```js
13 | class MyPlugin extends BasePlugin
14 | ```
15 | * Implement your functionality using the guidelines from the comments,
16 | * Put your plugin in the `src/plugins/myPlugin` Handsontable's subdirectory,
17 | * Open the terminal, navigate to your Handsontable location,
18 | * [Follow this steps to run your build](http://docs.handsontable.com/tutorial-custom-build.html#page-running)
19 | * Include the `handsontable.full.js` file on your website, and you're good to go!
--------------------------------------------------------------------------------
/plugins/internal/example/helloWorldPlugin.js:
--------------------------------------------------------------------------------
1 | import BasePlugin from './../_base';
2 | import {arrayEach} from './../../helpers/array';
3 | import {registerPlugin} from './../../plugins';
4 |
5 | /**
6 | * @plugin HelloWorldPlugin
7 | *
8 | * @description
9 | * Every time you type "Hello" in a cell, HelloWorldPlugins adds "World!" in the next cell.
10 | * Also, when you type "Handsontable", it adds "is awesome!" in the next cell.
11 | */
12 | class HelloWorldPlugin extends BasePlugin {
13 | constructor(hotInstance) {
14 | super(hotInstance);
15 |
16 | /**
17 | * Array containing the vocabulary used in the plugin.
18 | *
19 | * @type {Array}
20 | */
21 | this.vocabularyArray = [];
22 | }
23 |
24 | /**
25 | * Check if the plugin is enabled in the settings.
26 | */
27 | isEnabled() {
28 | return !!this.hot.getSettings().helloWorldPlugin;
29 | }
30 |
31 | /**
32 | * Enable the plugin.
33 | */
34 | enablePlugin() {
35 | this.vocabularyArray = [
36 | ['Hello', 'World!'],
37 | ['Handsontable', 'is awesome!']
38 | ];
39 |
40 | this.addHook('afterChange', this.onAfterChange.bind(this));
41 |
42 | super.enablePlugin();
43 | }
44 |
45 | /**
46 | * Disable the plugin.
47 | */
48 | disablePlugin() {
49 | this.vocabularyArray = [];
50 |
51 | super.disablePlugin();
52 | }
53 |
54 | /**
55 | * Update the plugin.
56 | */
57 | updatePlugin() {
58 | this.disablePlugin();
59 | this.enablePlugin();
60 |
61 | super.updatePlugin();
62 | }
63 |
64 | /**
65 | * The afterChange hook callback.
66 | *
67 | * @param {Array} changes Array of changes.
68 | * @param {String} source Describes the source of the change.
69 | */
70 | onAfterChange(changes, source) {
71 |
72 | // Check wheter the changes weren't blank or the hook wasn't triggered inside this callback.
73 | if (!changes || source === 'helloWorldPlugin') {
74 | return;
75 | }
76 |
77 | arrayEach(changes, function(change, i) {
78 | arrayEach(this.vocabularyArray, function(entry, j) {
79 |
80 | if (change[3] && change[3].toString().toLowerCase() === entry[0].toString().toLowerCase()) {
81 | this.hot.setDataAtCell(change[0], change[1] + 1, entry[1], 'helloWorldPlugin');
82 | }
83 |
84 | });
85 | });
86 | }
87 |
88 | /**
89 | * Destroy the plugin.
90 | */
91 | destroy() {
92 | super.destroy();
93 | }
94 | }
95 |
96 | export {HelloWorldPlugin};
97 |
98 | registerPlugin('helloWorldPlugin', HelloWorldPlugin);
99 |
--------------------------------------------------------------------------------
/plugins/external/example/helloWorldPlugin.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @plugin HelloWorldPlugin
3 | *
4 | * @description
5 | * Every time you type "Hello" in a cell, HelloWorldPlugins adds "World!" in the next cell.
6 | * Also, when you type "Handsontable", it adds "is awesome!" in the next cell.
7 | *
8 | * @param hotInstance
9 | * @constructor
10 | */
11 | function HelloWorldPlugin(hotInstance) {
12 | Handsontable.plugins.BasePlugin.call(this, hotInstance);
13 | this._superClass = Handsontable.plugins.BasePlugin;
14 |
15 | /**
16 | * Array containing the vocabulary used in the plugin.
17 | *
18 | * @type {Array}
19 | */
20 | this.vocabularyArray = [];
21 | }
22 |
23 | HelloWorldPlugin.prototype = Object.create(Handsontable.plugins.BasePlugin.prototype, {
24 | constructor: {
25 | writable: true,
26 | configurable: true,
27 | value: HelloWorldPlugin
28 | }
29 | });
30 |
31 | /**
32 | * Check if the plugin is enabled in the settings.
33 | */
34 | HelloWorldPlugin.prototype.isEnabled = function() {
35 | return !!this.hot.getSettings().helloWorldPlugin;
36 | };
37 |
38 | /**
39 | * Enable the plujgin.
40 | */
41 | HelloWorldPlugin.prototype.enablePlugin = function() {
42 | this.vocabularyArray = [
43 | ['Hello', 'World!'],
44 | ['Handsontable', 'is awesome!']
45 | ];
46 |
47 | this.addHook('afterChange', this.onAfterChange.bind(this));
48 |
49 | this._superClass.prototype.enablePlugin.call(this);
50 | };
51 |
52 | /**
53 | * Disable the plugin.
54 | */
55 | HelloWorldPlugin.prototype.disablePlugin = function() {
56 | this.vocabularyArray = [];
57 |
58 | this._superClass.prototype.disablePlugin.call(this);
59 | };
60 |
61 | /**
62 | * Update the plugin.
63 | */
64 | HelloWorldPlugin.prototype.updatePlugin = function() {
65 | this.disablePlugin();
66 | this.enablePlugin();
67 |
68 | this._superClass.prototype.updatePlugin.call(this);
69 | };
70 |
71 | /**
72 | * The afterChange hook callback.
73 | *
74 | * @param {Array} changes Array of changes.
75 | * @param {String} source Describes the source of the change.
76 | */
77 | HelloWorldPlugin.prototype.onAfterChange = function(changes, source) {
78 |
79 | // Check wheter the changes weren't blank or the hook wasn't triggered inside this callback.
80 | if (!changes || source === 'helloWorldPlugin') {
81 | return;
82 | }
83 |
84 | var arrayEach = Handsontable.helper.arrayEach;
85 | var _this = this;
86 |
87 | arrayEach(changes, function(change, i) {
88 | arrayEach(_this.vocabularyArray, function(entry, j) {
89 |
90 | if (change[3] && change[3].toString().toLowerCase() === entry[0].toLowerCase()) {
91 | _this.hot.setDataAtCell(change[0], change[1] + 1, entry[1], 'helloWorldPlugin');
92 | }
93 |
94 | });
95 | });
96 | };
97 |
98 | /**
99 | * Destroy the plugin.
100 | */
101 | HelloWorldPlugin.prototype.destroy = function() {
102 | this._superClass.prototype.destroy.call(this);
103 | };
104 |
105 | Handsontable.plugins.registerPlugin('helloWorldPlugin', HelloWorldPlugin);
--------------------------------------------------------------------------------
/plugins/internal/internalPluginSkeleton.js:
--------------------------------------------------------------------------------
1 | // You need to import the BasePlugin class in order to inherit from it.
2 | import BasePlugin from './../../_base';
3 | import {registerPlugin} from './../../../plugins';
4 |
5 | /**
6 | * @plugin InternalPluginSkeleton
7 | * Note: keep in mind, that Handsontable instance creates one instance of the plugin class.
8 | *
9 | * @description
10 | * Blank plugin template. It needs to inherit from the BasePlugin class.
11 | */
12 | class InternalPluginSkeleton extends BasePlugin {
13 |
14 | // The argument passed to the constructor is the currently processed Handsontable instance object.
15 | constructor(hotInstance) {
16 | super(hotInstance);
17 |
18 | // Initialize all your public properties in the class' constructor.
19 | /**
20 | * yourProperty description.
21 | *
22 | * @type {String}
23 | */
24 | this.yourProperty = '';
25 | /**
26 | * anotherProperty description.
27 | * @type {Array}
28 | */
29 | this.anotherProperty = [];
30 | }
31 |
32 | /**
33 | * Checks if the plugin is enabled in the settings.
34 | */
35 | isEnabled() {
36 | return !!this.hot.getSettings().internalPluginSkeleton;
37 | }
38 |
39 | /**
40 | * The enablePlugin method is triggered on the beforeInit hook. It should contain your initial plugin setup, along with
41 | * the hook connections.
42 | * Note, that this method is run only if the statement in the isEnabled method is true.
43 | */
44 | enablePlugin() {
45 | this.yourProperty = 'Your Value';
46 |
47 | // Add all your plugin hooks here. It's a good idea to make use of the arrow functions to keep the context consistent.
48 | this.addHook('afterChange', (changes, source) => this.onAfterChange(changes, source));
49 |
50 | // The super method assigns the this.enabled property to true, which can be later used to check if plugin is already enabled.
51 | super.enablePlugin();
52 | }
53 |
54 | /**
55 | * The disablePlugin method is used to disable the plugin. Reset all of your classes properties to their default values here.
56 | */
57 | disablePlugin() {
58 | this.yourProperty = '';
59 | this.anotherProperty = [];
60 |
61 | // The super method takes care of clearing the hook connections and assigning the 'false' value to the 'this.enabled' property.
62 | super.disablePlugin();
63 | }
64 |
65 | /**
66 | * The updatePlugin method is called on the afterUpdateSettings hook (unless the updateSettings method turned the plugin off).
67 | * It should contain all the stuff your plugin needs to do to work properly after the Handsontable instance settings were modified.
68 | */
69 | updatePlugin() {
70 |
71 | // The updatePlugin method needs to contain all the code needed to properly re-enable the plugin. In most cases simply disabling and enabling the plugin should do the trick.
72 | this.disablePlugin();
73 | this.enablePlugin();
74 |
75 | super.updatePlugin();
76 | }
77 |
78 | /**
79 | * The afterChange hook callback.
80 | *
81 | * @param {Array} changes Array of changes.
82 | * @param {String} source Describes the source of the change.
83 | */
84 | onAfterChange(changes, source) {
85 | // afterChange callback goes here.
86 | }
87 |
88 | /**
89 | * The destroy method should de-assign all of your properties.
90 | */
91 | destroy() {
92 | // The super method takes care of de-assigning the event callbacks, plugin hooks and clearing all the plugin properties.
93 | super.destroy();
94 | }
95 | }
96 |
97 | export {InternalPluginSkeleton};
98 |
99 | // You need to register your plugin in order to use it within Handsontable.
100 | registerPlugin('internalPluginSkeleton', InternalPluginSkeleton);
101 |
--------------------------------------------------------------------------------
/plugins/external/externalPluginSkeleton.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @plugin External plugin skeleton.
3 | * Note: keep in mind, that Handsontable instance creates one instance of the plugin class.
4 | *
5 | * @param hotInstance
6 | * @constructor
7 | */
8 | function ExternalPluginSkeleton(hotInstance) {
9 |
10 | // Call the BasePlugin constructor.
11 | Handsontable.plugins.BasePlugin.call(this, hotInstance);
12 |
13 | this._superClass = Handsontable.plugins.BasePlugin;
14 |
15 | // Initialize all your public properties in the class' constructor.
16 | /**
17 | * yourProperty description.
18 | *
19 | * @type {String}
20 | */
21 | this.yourProperty = '';
22 | /**
23 | * anotherProperty description.
24 | * @type {Array}
25 | */
26 | this.anotherProperty = [];
27 | }
28 |
29 | // Inherit the BasePlugin prototype.
30 | ExternalPluginSkeleton.prototype = Object.create(Handsontable.plugins.BasePlugin.prototype, {
31 | constructor: {
32 | writable: true,
33 | configurable: true,
34 | value: ExternalPluginSkeleton
35 | },
36 | });
37 |
38 | /**
39 | * Checks if the plugin is enabled in the settings.
40 | */
41 | ExternalPluginSkeleton.prototype.isEnabled = function() {
42 | return !!this.hot.getSettings().externalPluginSkeleton;
43 | };
44 |
45 | /**
46 | * The enablePlugin method is triggered on the beforeInit hook. It should contain your initial plugin setup, along with
47 | * the hook connections.
48 | * Note, that this method is run only if the statement in the isEnabled method is true.
49 | */
50 | ExternalPluginSkeleton.prototype.enablePlugin = function() {
51 | this.yourProperty = 'Your Value';
52 |
53 | // Add all your plugin hooks here. It's a good idea to make use of the arrow functions to keep the context consistent.
54 | this.addHook('afterChange', this.onAfterChange.bind(this));
55 |
56 | // The super class' method assigns the this.enabled property to true, which can be later used to check if plugin is already enabled.
57 | this._superClass.prototype.enablePlugin.call(this);
58 | };
59 |
60 | /**
61 | * The disablePlugin method is used to disable the plugin. Reset all of your classes properties to their default values here.
62 | */
63 | ExternalPluginSkeleton.prototype.disablePlugin = function() {
64 | this.yourProperty = '';
65 | this.anotherProperty = [];
66 |
67 | // The super class' method takes care of clearing the hook connections and assigning the 'false' value to the 'this.enabled' property.
68 | this._superClass.prototype.disablePlugin.call(this);
69 | };
70 |
71 | /**
72 | * The updatePlugin method is called on the afterUpdateSettings hook (unless the updateSettings method turned the plugin off).
73 | * It should contain all the stuff your plugin needs to do to work properly after the Handsontable instance settings were modified.
74 | */
75 | ExternalPluginSkeleton.prototype.updatePlugin = function() {
76 |
77 | // The updatePlugin method needs to contain all the code needed to properly re-enable the plugin. In most cases simply disabling and enabling the plugin should do the trick.
78 | this.disablePlugin();
79 | this.enablePlugin();
80 |
81 | this._superClass.prototype.updatePlugin.call(this);
82 | };
83 |
84 | /**
85 | * The afterChange hook callback.
86 | *
87 | * @param {Array} changes Array of changes.
88 | * @param {String} source Describes the source of the change.
89 | */
90 | ExternalPluginSkeleton.prototype.onAfterChange = function(changes, source) {
91 | // afterChange callback goes here.
92 | };
93 |
94 | /**
95 | * The destroy method should de-assign all of your properties.
96 | */
97 | ExternalPluginSkeleton.prototype.destroy = function() {
98 | // The super method takes care of de-assigning the event callbacks, plugin hooks and clearing all the plugin properties.
99 | this._superClass.prototype.destroy.call(this);
100 | };
101 |
102 | // You need to register your plugin in order to use it within Handsontable.
103 | Handsontable.plugins.registerPlugin('externalPluginSkeleton', ExternalPluginSkeleton);
--------------------------------------------------------------------------------