I am having trouble calling a jQuery plugin off the jQuery object itself. So rather than calling $(selector).myPlugin() I want to call $.myPlugin instead. For some reason it tells me that the function is undefined.
Here's my code:
(function ($) {
var _current = null;
var methods = {
init: function (options) {
_current = $('.rfgQuestionsWrapper').filter(function () {
return $(this).css('display') != 'none';
}).first();
console.log(_current);
$('.gaugeTitle').click(function (e) {
var rfgCode = $(this).parent().find('.gaugeWrapper').attr('id');
console.log(rfgCode);
showByCode(rfgCode);
return false;
});
},
showByCode: function (rfgCode) {
var target = $.utilities.filterById('.rfgQuestionsWrapper', rfgCode);
console.log(target);
_current.hide();
target.show();
}
};
$.fn.navigationManager = function (method) {
if (methods[method]) {
return methods[method].apply(this, Array.prototype.slice.call(arguments, 1));
} else if (typeof method === 'object' || !method) {
return methods.init.apply(this, arguments);
} else {
$.error('Method ' + method + ' does not exist on jQuery.tooltip');
}
};
})(jQuery);
I must be doing something wrong because this is the first time I call a plugin this way... Any suggestions?
Look at that question: in jQuery what is the difference between $.myFunction and $.fn.myFunction?
Basically instead of $.fn.navigationManager = function(){} you write $.navigationManager = function(){}.
Related
I have a plugin called "myPlugin" which uses the commonly used design pattern of default values which can be overridden upon initialization.
Instead of passing the overriding values upon initialization, I would like to extend the plugin as "myPlugin2" and change the default values so that when I initiate the extended plugin, it already has the desired new default values.
I've played around with adding new methods to the extended plugin, but I can't figure out how to change the default values.
In other words, I want the two lines of code to provide identical results.
$("body").myPlugin({'prop1':'prop1 modified','default_func4':function () {console.log('default_func4 modified')}});
$("body").myPlugin2();
How can I extend a jQuery plugin and change the default values?
http://jsfiddle.net/L1ng37wL/2/
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>Testing</title>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.js" type="text/javascript"></script>
<style type="text/css">
</style>
<script type="text/javascript">
(function ($) {
var defaults = {
'prop1' : 'prop1',
'default_func4' : function () {console.log('default_func4');},
'default_func5' : function () {console.log('default_func5');}
};
var methods = {
init: function (options) {
console.log("init");
console.log('defaults',defaults);
console.log('options',options);
var settings = $.extend({}, defaults, options);
console.log('settings',settings);
console.log('The value of "prop1" is '+settings.prop1);
settings.default_func4.call()
},
func1: function () {console.log("func1");},
func2: function () {console.log("func2");}
};
$.fn.myPlugin = function (method) {
// Method calling logic
if (methods[method]) {
return methods[method].apply(this, Array.prototype.slice.call(arguments, 1));
} else if (typeof method === 'object' || !method) {
return methods.init.apply(this, arguments);
} else {
$.error('Method ' + method + ' does not exist');
}
};
})(jQuery);
(function ($) {
var methods = {
'func1': function () {console.log("myPlugin2: func1");},
'func3': function () {console.log("myPlugin2: func3");}
}
$.fn.myPlugin2 = function (method) {
//HOW DO I CHANGE defaults.prop1 and defaults.default_func5?????
// Method calling logic
if (methods[method]) {
return methods[method].apply(this, Array.prototype.slice.call(arguments, 1));
} else if ((typeof method === 'object' || !method) && methods.init) {
return methods.init.apply(this, arguments);
} else {
try {
return $.fn.myPlugin.apply(this, arguments);
} catch (e) {
$.error(e);
}
}
}
})(jQuery);
$(function(){
$("body").myPlugin({
'prop1':'prop1 modified',
'default_func4':function () {console.log('default_func4 modified')}
});
$("body").myPlugin2();
//$("body").myPlugin2('func1');
//$("body").myPlugin2('func2');
//$("body").myPlugin2('func3');
});
</script>
</head>
<body>
</body>
</html>
The double check on the method parameter feels a bit weird to me, but if I replace your single line in the try-block to the code below, the thing works like it should, while still allowing you to supply an object with even different options.
var args = arguments;
if (typeof method === 'object' || !method) {
// Fill args with the new defaults.
args = {
'prop1': 'prop1 modified',
'default_func4': function () {
console.log('default_func4 modified')
}
};
$.extend(args, method);
args = [args];
}
return $.fn.myPlugin.apply(this, args);
For example, there is a simple jQuery plugin template
(function ($) {
var defaults = {
property: 'value'
},
methods = {
init: function (options) {
return this.each(function() {
var $this = $(this),
data = $this.data('myPlugin');
if (typeof data === 'undefined') {
var settings = $.extend({}, defaults, options);
$(this).data('photoBoard', {
target: $this,
settings: settings
});
}
});
},
destroy: function () {
return this.each(function () {
var $this = $(this),
data = $this.data('myPlugin');
$this.removeData('myPlugin');
})
},
somethingDo: function () {
// here i need get data
var data = $(this).data('myPlugin');
// something do with data
// ...
// and at the end put data back
$(this).data('myPlugin', data);
}
};
$.fn.myPlugin = function (method) {
if (methods[method]) {
return methods[method].apply(this, Array.prototype.slice.call(arguments, 1));
} else if (typeof method === 'object' || !method) {
return methods.init.apply(this, arguments);
}
$.error('Метод с именем ' + method + ' не существует для jQuery.myPlugin');
return this;
};
})(jQuery);
Do not quite understand, if i use the data, i have will in each method do something like this:
// here i need get data
var data = $(this).data('myPlugin');
// something do with data
// ...
// and at the end put data back
$(this).data('myPlugin', data);
Is this the only way? Perhaps there is another solution? How to use data in plugin methods?
No, you don't have to repeat this code. Just define data variable in the outer scope and refer to it in any methods. It will always hold the value you last put into it.
(function ($) {
var defaults = {
property: 'value'
},
data,
methods = {
somethingDo: function () {
// only needed if it wasn't set by methods called previously
// data = $(this).data('myPlugin');
// something do with data
// ...
// and at the end put data back
// you could move this call to a helper function as well
$(this).data('myPlugin', data);
}
};
})(jQuery);
(function( $ ){
var methods = {
init : function( options ) {
var settings = $.extend({ //Объявление настроек по умолчанию, которые можно переопределить в вызове плагина
code: 7,
listHeight: 160,
placeholder: "925000000",
phoneNumber: ""
}, options);
},
getCode : function( ) {
return $(this).settings.code;
}
};
$.fn.telephoneNumber = function( method ) {
if ( methods[method] ) {
return methods[ method ].apply( this, Array.prototype.slice.call( arguments, 1 ));
} else if ( typeof method === 'object' || ! method ) {
return methods.init.apply( this, arguments );
} else {
$.error( 'Метод с именем ' + method + ' не существует.' );
}
};
})( jQuery );
I need to refer to a variable code from a function getCode.
Function getCode returns nothing, how fix?
Since this in the call to your plugin will refer to the jQuery instance on which it was called, you can't use it to refer directly to your plugin's information.
The usual way to handle this is to store any information your plugin needs using jQuery's data function. Here's a simple example (this is loosely based in your code, but not an exact update of it; it's just an example):
(function ($) {
var methods = {
init: function (options) {
// Save settings using `data`
this.data("myplugin", $.extend({/*...*/}, options));
},
doSomething: function () {
// Get settings using `data`
var settings = this.data("myplugin");
// Use them...
}
};
var slice = Array.prototype.slice;
$.fn.myplugin = function (command) {
if (typeof command === "string") {
methods[command].apply(this, slice.call(arguments, 1));
} else {
methods.init.apply(this, arguments);
}
return this;
};
})(jQuery);
Live Example
Note that your code requires that the user call the plugin to initialize it, and then again to call a method on it, which I've reproduced above. So:
$("some selector").myplugin(); // Init
$("some selector").myplugin("doSomething"); // Use
You could auto-init with defaults if the user doesn't do that, by changing the plugin function like this:
$.fn.myplugin = function (command) {
if (typeof command === "string") {
if (!this.data("myplugin")) { // Not initialized?
methods.init.call(this); // Init with defaults
}
methods[command].apply(this, slice.call(arguments, 1));
} else {
methods.init.apply(this, arguments);
}
return this;
};
Here's that in action
settings has scope limited to init method as you've defined it there only. getCode function has no access to this variable.
Just define the settings globally, and you can access it in getCode.
I'm just kind of horsing around, trying to mimick certain jQuery functions (trying to write the vanilla javascript for the jQuery functions) I've made up this here
function ezWork(element) {
if (typeof element === 'string') {
document.getElementById(element);
console.log('Got element');
}
}
ezWork.prototype.on = function(event, callback) {
if (typeof event === 'string') {
if (event === 'click') {
if(window.addEventListener) {
element.addEventListener('mousedown', callback);
alert('addEventListener called');
} else if (window.attachEvent) {
element.attachEvent('onmousedown', callback);
} else {
element.onmousedown = callback;
}
}
}
}
ezWork('click').on('click', function(e) {
e.preventDefault();
alert('Worked');
});
http://jsfiddle.net/aJmMa/
I'm just curious why I get .on is not defined (I'm doing this off how I think it should be done, and not whether or not if I know this is the proper way to do this, I'm just trying to learn, what is the correct way of doing what I'm trying to do to add functions to functions?)
Thanks a lot for the help!
The error I get now is, '.on' is not defined.
var ezWork = (function(win, doc) {
// Constructor
function EzWork(element) {
this.element = this._init(element);
}
EzWork.prototype = {
_init: function(element) {
return doc.getElementById(element);
},
on: function(event, callback) {
// simplified...
this.element.addEventListener(event, callback);
}
};
// Shortcut to create a new instance without using 'new'
return function(element) {
return new EzWork(element);
};
}(window, document));
ezWork('click').on('click', function(e) {
e.preventDefault();
alert('Worked');
});
Demo: http://jsbin.com/oquduf/2/edit
Because ezWork() does not return an instance of ezWork. In fact, it doesn't return anything. once you fix that, you'll find that element is undefined. You'll have to add it and access it as a property.
function ezWork(element) {
if (!(this instanceof ezWork)) {
return new ezWork(element);
}
if (typeof element === 'string') {
element = document.getElementById(element);
console.log('Got element');
}
this.element = element;
}
http://jsfiddle.net/aJmMa/1/
Overview
I am trying to find the jQuery function that matches a selection attribute value and run that function on the selection.
Example.
$('[data-store="' + key + '"]').each(function() {
var $callback = $(this).attr('data-filter');
if($callback != null) {
var fn = window['$.fn.nl2br()'];
if(jQuery.isFunction(fn)) {
$(this).fn();
}
}
$(this).setValue(value);
});
Problem 1
I'm not sure how to create a jQuery function call from string.
I know I can call the function like this, $(this)'onclick'; however I have no way to check if it exists before trying to call it.
Normally I could do this:
var strfun = 'onclick';
var fn = body[strfun];
if(typeof fn === 'function') {
fn();
}
This seems to fail:
var fn = window['$.fn.nl2br()'];
if(jQuery.isFunction(fn)) {
$(this).fn();
}
EDIT:
I seem to be having success doing this:
if($callback != null) {
var fn = $(this)[$callback]();
if( typeof fn === 'function') {
$(this)[$callback]();
}
}
Problem 2
Using jQuery.isFunction() how do you check if a methods exists? can you do this with jQuery.isFunction()?
Example
Declare function:
$.fn.nl2br = function() {
return this.each(function() {
$(this).val().replace(/(<br>)|(<br \/>)|(<p>)|(<\/p>)/g, "\r\n");
});
};
Test if function existe, these options fail:
jQuery.isFunction($.fn.nl2br); // = false
jQuery.isFunction($.fn['nl2br']()); //false
Functions in JavaScript are referenced through their name just like any other variables. If you define var window.foobar = function() { ... } you should be able to reference the function through window.foobar and window['foobar']. By adding (), you are executing the function.
In your second example, you should be able to reference the function through $.fn['nl2br']:
$.fn.nl2br = function() {
return this.each(function() {
$(this).val().replace(/(<br>)|(<br \/>)|(<p>)|(<\/p>)/g, "\r\n");
});
};
console.log(jQuery.isFunction($.fn['nl2br']));
See a working example - http://jsfiddle.net/jaredhoyt/hXkZK/1/
var fn = window['$.fn.nl2br']();
and
jQuery.isFunction($.fn['nl2br']);