admin管理员组文章数量:1025270
How can I extend a plugin's public methods its prototype?
For instance, I have method1 in my plugin, and I want to add another and more through its .prototype
. Is it possible?
var extensionMethods = {
method2: function(){
return this;
}
};
$.fn.MyPlugin.prototype = extensionMethods;
console.log($(".element").MyPlugin());
result,
Object { Element={...}, Options={...}, method1=function()}
Ideally,
Object { Element={...}, Options={...}, method1=function(), method2=function(), method2function()}
my plugin boilerplate,
(function ($) {
// Create the plugin name and defaults once
var pluginName = 'MyPlugin';
// Attach the plugin to jQuery namespace.
$.fn[pluginName] = function(PublicOptions) {
// Set private defaults.
var Defaults = {
param1: 'param1',
param2: 'param2',
onSuccess: function(){}
};
// Do a deep copy of the options.
var Options = $.extend(true, {}, Defaults, PublicOptions);
// Define a functional object to hold the api.
var PluginApi = function(Element, Options) {
this.Element = Element;
this.Options = Options;
};
// Define the public api and its public methods.
PluginApi.prototype = {
method1: function(PublicOptions) {
// Process the options.
var Options = $.extend(true, {}, this.Options, PublicOptions);
return this.Options;
}
};
//Create a new object of api.
return new PluginApi(this, Options);
};
})(jQuery);
Any ideas?
How can I extend a plugin's public methods its prototype?
For instance, I have method1 in my plugin, and I want to add another and more through its .prototype
. Is it possible?
var extensionMethods = {
method2: function(){
return this;
}
};
$.fn.MyPlugin.prototype = extensionMethods;
console.log($(".element").MyPlugin());
result,
Object { Element={...}, Options={...}, method1=function()}
Ideally,
Object { Element={...}, Options={...}, method1=function(), method2=function(), method2function()}
my plugin boilerplate,
(function ($) {
// Create the plugin name and defaults once
var pluginName = 'MyPlugin';
// Attach the plugin to jQuery namespace.
$.fn[pluginName] = function(PublicOptions) {
// Set private defaults.
var Defaults = {
param1: 'param1',
param2: 'param2',
onSuccess: function(){}
};
// Do a deep copy of the options.
var Options = $.extend(true, {}, Defaults, PublicOptions);
// Define a functional object to hold the api.
var PluginApi = function(Element, Options) {
this.Element = Element;
this.Options = Options;
};
// Define the public api and its public methods.
PluginApi.prototype = {
method1: function(PublicOptions) {
// Process the options.
var Options = $.extend(true, {}, this.Options, PublicOptions);
return this.Options;
}
};
//Create a new object of api.
return new PluginApi(this, Options);
};
})(jQuery);
Any ideas?
Share Improve this question asked Jan 11, 2015 at 15:32 RunRun 57.4k178 gold badges464 silver badges771 bronze badges 12-
According to your structure (pretty unfortunate, actually, because this is not jQuery plugin) you can only access
PluginApi.prototype
via some object returned$(".element").MyPlugin()
becausePluginApi
constructor is local inside IIFE. But this is of course not very good. – dfsq Commented Jan 11, 2015 at 15:39 - How can I change the structure to allow that then? – Run Commented Jan 11, 2015 at 15:40
-
most jquery plugins return
this
to maintain jQuery chainability. Why are you so set on wanting to create public methods on prototype? – charlietfl Commented Jan 11, 2015 at 15:40 - @charlietfl can you please provide an example for chainability? – Run Commented Jan 11, 2015 at 15:46
-
1
it wraps all the plugin code and insulates it (closure) as well as provides context for
$
so plugin won't break on page where other libraries use$
– charlietfl Commented Jan 11, 2015 at 16:28
2 Answers
Reset to default 2I think the best structure you can do in this case would not involve prototypes at all. Check this plugin base:
(function($) {
// Set private defaults.
var Defaults = {
param1: 'param1',
param2: 'param2',
onSuccess: function() {}
};
// Define the public api and its public methods.
var PluginApi = {
extend: function(name, method) {
PluginApi[name] = method;
return this;
},
init: function(PublicOptions) {
// Do a deep copy of the options.
var Options = $.extend(true, {}, Defaults, PublicOptions);
return this.each(function() {
console.log('set up plugin logic', this.tagName);
});
},
method1: function() {
console.log('called: method1');
return this;
}
};
// Create the plugin name and defaults once
var pluginName = 'MyPlugin';
// Attach the plugin to jQuery namespace.
$.fn[pluginName] = function(method) {
if (PluginApi[method]) {
return PluginApi[method].apply(this, Array.prototype.slice.call(arguments, 1));
}
else if (typeof method === 'object' || !method) {
return PluginApi.init.apply(this, arguments);
}
else {
$.error('Method ' + method + 'does not exist');
}
};
})(jQuery);
This plugin structure allows you to chain methods as expected:
$('h1').MyPlugin('method1').css('color', 'red');
In case of the need to use non-existent method you could do this:
// Extend plugin "prototype" with method2 and use it
$('h1, h2').MyPlugin('extend', 'method2', function(prop, value) {
return this.css(prop, value);
}).MyPlugin('method2', 'color', 'green');
Check usage example in the demo below.
(function($) {
// Set private defaults.
var Defaults = {
param1: 'param1',
param2: 'param2',
onSuccess: function() {}
};
// Define the public api and its public methods.
var PluginApi = {
extend: function(name, method) {
PluginApi[name] = method;
return this;
},
init: function(PublicOptions) {
// Do a deep copy of the options.
var Options = $.extend(true, {}, Defaults, PublicOptions);
return this.each(function() {
console.log('set up plugin logic', this.tagName);
});
},
method1: function() {
console.log('called: method1');
return this;
}
};
// Create the plugin name and defaults once
var pluginName = 'MyPlugin';
// Attach the plugin to jQuery namespace.
$.fn[pluginName] = function(method) {
if (PluginApi[method]) {
return PluginApi[method].apply(this, Array.prototype.slice.call(arguments, 1));
}
else if (typeof method === 'object' || !method) {
return PluginApi.init.apply(this, arguments);
}
else {
$.error('Method ' + method + 'does not exist');
}
};
})(jQuery);
// Call existen method1: should make h1 and h2 red
$('h1, h2').MyPlugin('method1').css('color', 'red');
// Call non-existent method2: should throw error in console
try {
$('h1, h2').MyPlugin('method2').css('color', 'green');
}
catch (e) {
// Extend "plugin" prototype with method2
$('h1, h2').MyPlugin('extend', 'method2', function(prop, value) {
return this.css(prop, value);
}).MyPlugin('method2', 'color', 'green');
}
<script src="https://ajax.googleapis./ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<h1>H1</h1>
<h2>H2</h2>
Or it may be more optimal to define a static method extend
within $[pluginName]
namespace:
// Attach the plugin to jQuery namespace.
$.fn[pluginName] = function(method) {
if (PluginApi[method]) {
return PluginApi[method].apply(this, Array.prototype.slice.call(arguments, 1));
}
else if (typeof method === 'object' || !method) {
return PluginApi.init.apply(this, arguments);
}
else {
$.error('Method ' + method + 'does not exist');
}
};
$[pluginName] = {};
$[pluginName].extend = function(name, method) {
PluginApi[name] = method;
};
and then use it like this when necessary to add additional methods:
$.MyPlugin.extend('method2', function(prop, value) {
return this.css(prop, value);
});
$('h1, h2').MyPlugin('method2', 'color', 'green');
Final demo: http://plnkr.co/edit/qqlfRqAM84goscU5BFNU?p=preview
You can't extend the prototype outside because you use hidden object PluginApi.
You can try to store PluginApi outside of a plugin function:
$[pluginName] = function(Element, Options) {
this.Element = Element;
this.Options = Options;
};
$[pluginName].prototype = {
method1: function(PublicOptions) {
// Process the options.
var Options = $.extend(true, {}, this.Options, PublicOptions);
return this.Options;
}
};
$.fn[pluginName] = function(PublicOptions) {
// Set private defaults.
var Defaults = {
param1: 'param1',
param2: 'param2',
onSuccess: function(){}
};
// Do a deep copy of the options.
var Options = $.extend(true, {}, Defaults, PublicOptions);
return new $[pluginName](this, Options);
};
and then you can extend the the prototype:
$.MyPlugin.prototype.method2 = function() {
return this;
}
How can I extend a plugin's public methods its prototype?
For instance, I have method1 in my plugin, and I want to add another and more through its .prototype
. Is it possible?
var extensionMethods = {
method2: function(){
return this;
}
};
$.fn.MyPlugin.prototype = extensionMethods;
console.log($(".element").MyPlugin());
result,
Object { Element={...}, Options={...}, method1=function()}
Ideally,
Object { Element={...}, Options={...}, method1=function(), method2=function(), method2function()}
my plugin boilerplate,
(function ($) {
// Create the plugin name and defaults once
var pluginName = 'MyPlugin';
// Attach the plugin to jQuery namespace.
$.fn[pluginName] = function(PublicOptions) {
// Set private defaults.
var Defaults = {
param1: 'param1',
param2: 'param2',
onSuccess: function(){}
};
// Do a deep copy of the options.
var Options = $.extend(true, {}, Defaults, PublicOptions);
// Define a functional object to hold the api.
var PluginApi = function(Element, Options) {
this.Element = Element;
this.Options = Options;
};
// Define the public api and its public methods.
PluginApi.prototype = {
method1: function(PublicOptions) {
// Process the options.
var Options = $.extend(true, {}, this.Options, PublicOptions);
return this.Options;
}
};
//Create a new object of api.
return new PluginApi(this, Options);
};
})(jQuery);
Any ideas?
How can I extend a plugin's public methods its prototype?
For instance, I have method1 in my plugin, and I want to add another and more through its .prototype
. Is it possible?
var extensionMethods = {
method2: function(){
return this;
}
};
$.fn.MyPlugin.prototype = extensionMethods;
console.log($(".element").MyPlugin());
result,
Object { Element={...}, Options={...}, method1=function()}
Ideally,
Object { Element={...}, Options={...}, method1=function(), method2=function(), method2function()}
my plugin boilerplate,
(function ($) {
// Create the plugin name and defaults once
var pluginName = 'MyPlugin';
// Attach the plugin to jQuery namespace.
$.fn[pluginName] = function(PublicOptions) {
// Set private defaults.
var Defaults = {
param1: 'param1',
param2: 'param2',
onSuccess: function(){}
};
// Do a deep copy of the options.
var Options = $.extend(true, {}, Defaults, PublicOptions);
// Define a functional object to hold the api.
var PluginApi = function(Element, Options) {
this.Element = Element;
this.Options = Options;
};
// Define the public api and its public methods.
PluginApi.prototype = {
method1: function(PublicOptions) {
// Process the options.
var Options = $.extend(true, {}, this.Options, PublicOptions);
return this.Options;
}
};
//Create a new object of api.
return new PluginApi(this, Options);
};
})(jQuery);
Any ideas?
Share Improve this question asked Jan 11, 2015 at 15:32 RunRun 57.4k178 gold badges464 silver badges771 bronze badges 12-
According to your structure (pretty unfortunate, actually, because this is not jQuery plugin) you can only access
PluginApi.prototype
via some object returned$(".element").MyPlugin()
becausePluginApi
constructor is local inside IIFE. But this is of course not very good. – dfsq Commented Jan 11, 2015 at 15:39 - How can I change the structure to allow that then? – Run Commented Jan 11, 2015 at 15:40
-
most jquery plugins return
this
to maintain jQuery chainability. Why are you so set on wanting to create public methods on prototype? – charlietfl Commented Jan 11, 2015 at 15:40 - @charlietfl can you please provide an example for chainability? – Run Commented Jan 11, 2015 at 15:46
-
1
it wraps all the plugin code and insulates it (closure) as well as provides context for
$
so plugin won't break on page where other libraries use$
– charlietfl Commented Jan 11, 2015 at 16:28
2 Answers
Reset to default 2I think the best structure you can do in this case would not involve prototypes at all. Check this plugin base:
(function($) {
// Set private defaults.
var Defaults = {
param1: 'param1',
param2: 'param2',
onSuccess: function() {}
};
// Define the public api and its public methods.
var PluginApi = {
extend: function(name, method) {
PluginApi[name] = method;
return this;
},
init: function(PublicOptions) {
// Do a deep copy of the options.
var Options = $.extend(true, {}, Defaults, PublicOptions);
return this.each(function() {
console.log('set up plugin logic', this.tagName);
});
},
method1: function() {
console.log('called: method1');
return this;
}
};
// Create the plugin name and defaults once
var pluginName = 'MyPlugin';
// Attach the plugin to jQuery namespace.
$.fn[pluginName] = function(method) {
if (PluginApi[method]) {
return PluginApi[method].apply(this, Array.prototype.slice.call(arguments, 1));
}
else if (typeof method === 'object' || !method) {
return PluginApi.init.apply(this, arguments);
}
else {
$.error('Method ' + method + 'does not exist');
}
};
})(jQuery);
This plugin structure allows you to chain methods as expected:
$('h1').MyPlugin('method1').css('color', 'red');
In case of the need to use non-existent method you could do this:
// Extend plugin "prototype" with method2 and use it
$('h1, h2').MyPlugin('extend', 'method2', function(prop, value) {
return this.css(prop, value);
}).MyPlugin('method2', 'color', 'green');
Check usage example in the demo below.
(function($) {
// Set private defaults.
var Defaults = {
param1: 'param1',
param2: 'param2',
onSuccess: function() {}
};
// Define the public api and its public methods.
var PluginApi = {
extend: function(name, method) {
PluginApi[name] = method;
return this;
},
init: function(PublicOptions) {
// Do a deep copy of the options.
var Options = $.extend(true, {}, Defaults, PublicOptions);
return this.each(function() {
console.log('set up plugin logic', this.tagName);
});
},
method1: function() {
console.log('called: method1');
return this;
}
};
// Create the plugin name and defaults once
var pluginName = 'MyPlugin';
// Attach the plugin to jQuery namespace.
$.fn[pluginName] = function(method) {
if (PluginApi[method]) {
return PluginApi[method].apply(this, Array.prototype.slice.call(arguments, 1));
}
else if (typeof method === 'object' || !method) {
return PluginApi.init.apply(this, arguments);
}
else {
$.error('Method ' + method + 'does not exist');
}
};
})(jQuery);
// Call existen method1: should make h1 and h2 red
$('h1, h2').MyPlugin('method1').css('color', 'red');
// Call non-existent method2: should throw error in console
try {
$('h1, h2').MyPlugin('method2').css('color', 'green');
}
catch (e) {
// Extend "plugin" prototype with method2
$('h1, h2').MyPlugin('extend', 'method2', function(prop, value) {
return this.css(prop, value);
}).MyPlugin('method2', 'color', 'green');
}
<script src="https://ajax.googleapis./ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<h1>H1</h1>
<h2>H2</h2>
Or it may be more optimal to define a static method extend
within $[pluginName]
namespace:
// Attach the plugin to jQuery namespace.
$.fn[pluginName] = function(method) {
if (PluginApi[method]) {
return PluginApi[method].apply(this, Array.prototype.slice.call(arguments, 1));
}
else if (typeof method === 'object' || !method) {
return PluginApi.init.apply(this, arguments);
}
else {
$.error('Method ' + method + 'does not exist');
}
};
$[pluginName] = {};
$[pluginName].extend = function(name, method) {
PluginApi[name] = method;
};
and then use it like this when necessary to add additional methods:
$.MyPlugin.extend('method2', function(prop, value) {
return this.css(prop, value);
});
$('h1, h2').MyPlugin('method2', 'color', 'green');
Final demo: http://plnkr.co/edit/qqlfRqAM84goscU5BFNU?p=preview
You can't extend the prototype outside because you use hidden object PluginApi.
You can try to store PluginApi outside of a plugin function:
$[pluginName] = function(Element, Options) {
this.Element = Element;
this.Options = Options;
};
$[pluginName].prototype = {
method1: function(PublicOptions) {
// Process the options.
var Options = $.extend(true, {}, this.Options, PublicOptions);
return this.Options;
}
};
$.fn[pluginName] = function(PublicOptions) {
// Set private defaults.
var Defaults = {
param1: 'param1',
param2: 'param2',
onSuccess: function(){}
};
// Do a deep copy of the options.
var Options = $.extend(true, {}, Defaults, PublicOptions);
return new $[pluginName](this, Options);
};
and then you can extend the the prototype:
$.MyPlugin.prototype.method2 = function() {
return this;
}
本文标签: javascriptHow to extend a jquery plugin39s public methods through its prototypeStack Overflow
版权声明:本文标题:javascript - How to extend a jquery plugin's public methods through its prototype? - Stack Overflow 内容由热心网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://it.en369.cn/questions/1745613652a2159156.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论