I have a long jquery function and I want to separate it as an plugin.
Normally, most jquery plugin has a selector element as below.
;( function( $, window, document, undefined )
{
'use strict';
$.fn.myPlugin = function( options )
{
// codes goes here
}
})( jQuery, window, document );
and the usage is something like this.
$('.element').myPlugin();
But in my case, the javascript function doesn't really need a selector element, it only expect a value(parameter).
e.g
function coolMethods(Str){
return Str + doSomething;
}
So, how can I use this as a plugin?
I would expect the usage is like this
myPlugin.coolMethods(Str) // and this should return a value.
If you don't need any jquery functionality (the $(selector). part) and you want to call it like
myPlugin.CoolMethod("abc")
then you need a namespace rather than a plugin.
There's a number of ways to generate namespaces and scripts to help this, but essentially a namespace is an object that contains functions, the basic setup would be:
var myPlugin = {};
myPlugin.CoolMethod = function(param1) {
return param1 + param1;
};
// to use this:
console.log(myPlugin.CoolMethod("abc"))
Once you start using namespaces, you can then have private methods/variables within that namespace if needed and can easily add other methods / sub-namespaces.
Another common way to setup a namespace is something like:
var myPlugin = myPlugin || {};
(function(myplugin, $) {
// can also use $ within the namespace declaration
myplugin.CoolMethod = function(param1) {
return param1 + param1;
};
})(myPlugin, jQuery);
// to use this:
console.log(myPlugin.CoolMethod("abc"))
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
There is no problem! you can create your plugin in this case and use it on each element without any relation with it!
generally, is not necessary that your function uses JQuery elems.
example:
$.fn.NewFunc /*Your plugin function*/ = function(param1){
console.log("Oh! It's ok!!");
console.log(arguments);
};
Usage:
$.fn.NewFunc("Hello!");
or
$("").NewFunc("I Am An Argument!");
or even:
$("AnySelector").NewFunc("param1", "param2");
If you dont need selected elems by selector, you can use other way similar these (this is not a plugin):
$.NewFunc = function(p1, p2){/*do somethings*/};
and use it similar this:
$.NewFunc("param1", "param2");
Here is my version
(function ($, window, document, undefined) {
'use strict';
var PLUGIN_NAME = 'myPlugin';
function plugin(options) {
var opts = $.extend(true, {}, $[PLUGIN_NAME].defaults, options);
_print(opts.name);
}
var _print = function (name) {
console.log(name);
};
$[PLUGIN_NAME] = function (options) {
new plugin(options);
};
$[PLUGIN_NAME].defaults = {
name: 'John'
};
}(jQuery, window, document));
Usage:
$.myPlugin({
name: 'Suzy'
});
Or
$.myPlugin();
Working example
Related
I create component from Trumbowyg plugin to vue.js library. I need add two way binding in this beautiful wysiwyg editor.
How to rewrite buildEditor() method?
This method is private. how to do it correctly?
<script>
jQuery.trumbowyg = {
// options object
};
(function (navigator, window, document, $, undefined) {
$.fn.trumbowyg = function (options, params) {
// ... code ...
$(this).data('trumbowyg', new Trumbowyg(this, options));
// ... code ...
};
var Trumbowyg = function (editorElem, o) {
var t = this;
// ... code ...
t.init();
};
Trumbowyg.prototype = {
init: function () {
var t = this;
t.buildEditor();
// ... code ...
},
buildEditor: function () {
// i need rewrite this method
}
// code for otner method
};
})(navigator, window, document, jQuery);
// -------------------------------------
// other file. I want init this plugin
// here do need to rewrite buildEditor() method? What best way to do this?
$('.selector').trumbowyg();
If this plugin doesn't return 'Trumbowyg' variable it's not possible. I recommend fork this plugin and create your own version with your settings.
The best way to do it would be to fork the plugin yourself, as Slava answered. But technically you're able to modify that function.
Whenever you construct a class, that instance has its own constructor property. This is equal to the class function.
So, if you can get access to an instance of Trumbowyg, you're able to use its class:
$foo.trumbowyg(...)
var trumbowyg = $foo.data('trumbowyg')
var TrumbowygClass = trumbowyg.constructor
Now we can modify its prototype:
TrumbowygClass.prototype.buildEditor = function() {
// ...
}
You might want to make $foo be a temporary or unused element. That's because it'll have called the old buildEditor (as soon as you ran $foo.trumbowyg()), not your own modified version.
After you've set the prototype function you could run it on the element you actually want to use trumbowyg on (e.g. $('#target'))
As an example:
(function() {
window.makeInstance = function() {
return new HiddenClass()
}
var HiddenClass = function() {
this.setGreeting()
this.showGreeting()
}
HiddenClass.prototype.setGreeting = function() {
this.greeting = 'Hello, world!'
}
HiddenClass.prototype.showGreeting = function() {
console.log(this.greeting)
}
})()
var myTempInstance = makeInstance()
// Should log 'Hello, world!'
var HiddenClass = myTempInstance.constructor
console.log(HiddenClass) // Should be the HiddenClass function
// Now we overwrite our function..
HiddenClass.prototype.setGreeting = function() {
this.greeting = 'Redefined!'
}
var myUsedInstance = makeInstance()
// Should log 'Redefined!', since we redefined setGreeting
// And later we can use `myUsedInstance`.
// In this code myTempInstance is like $foo, and myUsedInstance
// is like $('#target').
I have a JavaScript module that I would like to create a jQuery plugin interface to.
The module itself is like this:
var Foo = (function () {
"use strict";
var self = {};
self.add = function (selector, otherParam)
{
// Does things unto selector.
// Precisely what it does doesn't matter.
};
return self;
}());
and is used, with success, like this:
Foo.add(a);
Now, I would like to create a plugin that interfaces to this module,
so I can use it somewhat like this:
$.fn.foo = Foo;
$.fn.foo.add = function (param) {
var selector = this;
Foo.add(selector, param);
}
$(elem).foo.add(a);
The problem I'm facing is that I can't get "this" working in .add().
The best way I managed to do it was to not have Foo be self-initializing,
and use a syntax like:
$.fn.foo = Foo;
$(elem).foo().add(a);
It works, but I find it less aesthatically pleasing and less "clean".
Is there a way to do this? Am I on the wrong approach altogether?
Thankful for any input, and I apologize in advance if this has already been answered or is unfit in any other way.
I did search for answers, but I'm not well-versed in plugin authoring nor an expert on jQuery itself.
TL;DR: I have a module like Foo above, and would like to access it's members like a jQuery plugin.
Here is a simplified version of the pattern I normally use (error checking and extra features removed).
It uses a single class function and a plugin bridge extension method to allow attachment to multiple elements. Methods are called by using a string option value:
var Foo = (function () {
"use strict";
// Constructor
function Foo($element, options){
this.$element = $element;
this.options = options
this.fooVal = 0;
}
// Create method (called from bridge)
Foo.prototype.onCreate = function(){
this.fooVal = ~~this.$element.text()
};
// Add the specified val to the elements current value
Foo.prototype.add = function (val) {
this.fooVal += val;
// Update the element text with the new value
this.$element.text(this.fooVal);
};
return Foo;
})();
// Create a bridge to each element that needs a Foo
$.fn.foo = function (options, args) {
this.each(function () {
var $element = $(this);
// Try to get existing foo instance
var foo = $element.data("Foo");
// If the argument is a string, assume we call that function by name
if (typeof options == "string") {
foo[options](args);
}
else if (!foo) {
// No instance. Create a new Foo and store the instance on the element
foo = new Foo($element, options);
$element.data("Foo", foo);
// Record the connected element on the Foo instance
foo.$element = $element;
// Call the initial create method
foo.onCreate();
}
});
}
// testing
console.clear();
$('#test').foo();
$('#button2').click(function () {
$('#test').foo("add", 2);
});
$('#button10').click(function () {
$('#test').foo("add", 10);
});
For your example Foo takes the initial value from the element text and subsequent "add" calls modify that value.
JSFiddle: http://jsfiddle.net/TrueBlueAussie/o2u7egfy/3/
Notes:
~~ is just a fast short-cut for parseInt()
You could supply an initial value via the options parameter (ignored in first example). See following:
e.g.
// Create method (called from bridge)
Foo.prototype.onCreate = function(){
this.fooVal = this.options.value || ~~this.$element.text()
// Set initial value
this.$element.text(this.fooVal);
};
and start with
$('#test').foo({value: 999});
JSFiddle: http://jsfiddle.net/TrueBlueAussie/o2u7egfy/4/
Is there anyway to limit the scope of a jquery function to an object other than using a main function:
(function( $ ) {
$.fn.myLib = function( funcName ) {
if ( action === "func1") {
// Open popup code.
}
if ( action === "func2" ) {
// Close popup code.
}
};
}( jQuery ));
I'd like to do it so that I could call functions like this:
$(el).myLib.func1();
$(el).myLib.func2();
There's really not a lot of good reason to try to do this:
$(el).myLib.func1();
Because the this pointer when func1() executes will be myLib and you won't be able to access $(el). So, it doesn't do you a whole lot of good unless all you want is static methods. If that's what you actually want, then you can do this:
$.fn.myLib = {};
$.fn.myLib.func1 = function(...) {...};
$.fn.myLib.func2 = function(...) {...};
If you actually want to be able to have acceess to the jQuery object (which I presume), then stick to one level and use a name prefix which gives you about the same level of name conflict protection anyway.
$.fn.myLibFunc1 = function(...) {...};
$.fn.myLibFunc2 = function(...) {...};
Then, you can do:
$(el).myLibFunc1();
And, the this pointer in myLibFunc1 will be the jQuery object that called it.
(function( $ ) {
$.fn.myLib = function( funcName ) {
var obj=new Object
obj.func1=function () {alert('first')}
obj.func2=function () {alert('second')}
return obj
};
}( jQuery ));
I am using a boilerplate plugin design which looks like this,
;(function ( $, window, document, undefined ) {
var pluginName = "test",
defaults = {};
function test( element, options ) {
this.init();
}
test.prototype = {
init: function() {}
}
$.fn.test = function(opt) {
// slice arguments to leave only arguments after function name
var args = Array.prototype.slice.call(arguments, 1);
return this.each(function() {
var item = $(this), instance = item.data('test');
if(!instance) {
// create plugin instance and save it in data
item.data('test', new test(this, opt));
} else {
// if instance already created call method
if(typeof opt === 'string') {
instance[opt].apply(instance, args);
}
}
});
};
})( jQuery, window, document );
Now say i have two <div> with same class container.
And now i would call my test plugin on these divs like so,
$(".container").test({
onSomething: function(){
}
});
Now when function onSomething is called from inside my plugin how can i call that plugin public methods referring to the instance onSomething function was called from?
For example something happened with the first container div and onSomething function was called for only first container div.
To make it a bit more clear I have tried to pass this instance to the onSomething function, that way i expose all plugin data and then i can do something like,
onSomething(instance){
instance.someMethod();
instance.init();
//or anything i want
}
To me me it looks quite wrong so there must be a better way... or not?
Well im not sure if it is the best idea, but you could pass the current object as a parameter. Let's say onSomething : function(obj) { }
So whenever "onSomething" is called by the plugin, you can call it like this: "onSomething(this)" and then refer to the object asobject`
Lets give a specific example.
var plugin = function (opts) {
this.onSomething = opts.onSomething;
this.staticProperty = 'HELLO WORLD';
this.init = function() {
//Whatever and lets pretend you want your callback right here.
this.onSomething(this);
}
}
var test = new Plugin({onSomething: function(object) { alert(object.staticProperty) });
test.init(); // Alerts HELLO WORLD
Hope this helps, tell me if its not clear enough.
Oh wait, thats what you did.
This is just a question of curiosity. But im wondering if I can add an extra variable in front of String.prototype.
For example:
$.String.prototype.functionName = function(){};
Of course I relize this doesnt work. But can I make it work somehow? I would like a syntax like:
$("Hi").functionName();
The, jQuery syntax, just with string inside of the () instead of a selector.
I would like the $ to be required.
Since:
String.prototype.functionName = function(){};
var $ = String;
$("Hi").functionName();
Works, but it makes it so the $ isn't required, so "Hi".functionName() works.
Thanks for the suggestions.
I'm not really sure what is meant by "the jQuery syntax", but if you mean using the $ variable as a reference to a function that manipulates strings, then that's pretty simple...
;(function(window, undefined) {
var MyStringLib = function(s) { this.string = s; };
window.$ = function(s) { return new MyStringLib(s); };
MyStringLib.prototype.addFooBar = function() {
this.string += "foobar";
return this;
};
MyStringLib.prototype.reverse = function() {
this.string = this.string.split('').reverse().join('');
return this;
};
MyStringLib.prototype.get = function() {
return this.string;
};
})(this);
Then use the library like this...
var result = $("My name is ").addFooBar().reverse().get();
alert(result); // raboof si eman yM
No, this is somewhat confused. If you had something like this
$.String.prototype.functionName = function(){};
you would have to address it like this:
(new $.String("Hi")).functionName();
(some parentheses are optional.)
If you want to be able to do something like this:
$("Hi").functionName();
then you would need to attach it like this:
$.prototype.functionName = function(){};
(Note that jQuery's magic fn parameter is just an alias to its constructor function's prototype property.)
What is your underlying goal here?