Call the same instance of jQuery plugin - javascript

I have written a jQuery plugin below and would like to be able to call it again for the same instance on an element.
The plugin goes...
(function($) {
$.fn.myPlugin = function(options){
var settings = {
color: null
};
if (options) {
$.extend(settings, options);
}
return this.each(function(){
var self = this;
var pics = $('li', self);
function refresh() {
pics = $('li', self);
};
$('a', self).click(function(){
pics.filter(':last').remove();
alert(settings.color);
refresh();
return false;
});
});
}
})(jQuery);
In the page this is called...
$('#test').myPlugin({ color: 'blue' });
Now I want to call the same plugin for the same instance but pass the string refresh as the option whilst all the other variables are the same (so color would still be blue) e.g...
$('#test').myPlugin('refresh');
This would then execute the refresh() function.
How could I achieve that with the above?
Edit: To make it clearer I am thinking of how jQuery UI does their plugins. In the sortable plugin you can do $("#sortable").sortable(); and then $("#sortable").sortable('refresh'); on the same element. This is what I am trying to achieve.

You can store your instance with .data() and check for it when creating an instance.
Something like:
$.fn.doStuff = function () {
var ob = $(this);
var data = ob.data();
if (data.doStuff !== undefined) {
return data.doStuff;
}
doStuff;
});

(function($) {
$.fn.myPlugin = function(options){
var init = function($self, ops){
$self.find("a").click(function(){
pics.filter(':last').remove();
alert(settings.color);
refresh();
return false;
});
};
this.refresh = function(){
//your code here
};
return this.each(function(){
var self = this;
var pics = $('li', self);
var settings = {
color: null
};
var ops = $.extend(true, settings, options);
init($(this), ops);
});
}
})(jQuery);
try something like this. and you can call refresh() like $().myPlugin().refresh();

Related

test jQuery Plugin variable with QUnit

I have already seen this link:
jQuery Plugin: How do I test the configuration of my plugin with qunit?
But I haven't understand if is the same case or not so I ask again.
I have a simple plugin like this:
(function ($) {
$.fn.extend({
miPlugin: function (argumentOptions) {
var defaults = {
txt: 'txt'
}
var options = $.extend(defaults, argumentOptions);
return this.each(function () {
var o = options;
var obj = $(this);
var textSend = '';
obj.mouseup(function(e) {
textSend = 'test';
});
});
}
});
})(jQuery);
I would like to check the variable textSend is possible when mouseUp trigger?
This is my test with QUnit:
$(document).ready(function(){
var testfield = $('.txt');
$('.txt').myPlugin({});
module('Simple');
test("Simple", function(){
testfield.focus();
testfield.select();
var obj = testfield.trigger( $.Event( "mouseup") );
});
});
How can I test the var textSend on mouseUp event?
Thanks

Creating custom JQuery objects and functions

I have created a simple JQuery extension :
(function($) {
$.fn.extend({
GMselect: function(options){
var defaults = {
url: '',
onSelect: function(){},
loadData: function(url){
$.get(url || this.url).done(function(res){
var opts = '';
for (i in res){
opts += '<option value='+res[i].id+'>'+res[i].name + '</option>';
}
me.html(opts);
});
}
};
var options = $.extend(defaults, options);
options.loadData();
$(this).change( options.onSelect );
var me = $(this);
}
});
}(jQuery));
this way I can easly create select elements reading data from remote JSON source like this:
$('#mySelect').GMselect({
url: 'getData'
});
This part is clear, however I would like to know the way to dynamically reload the select, by invoking the method like
$('#mySelect').reload(url)
Any help and comments will be appreciate
Well I think this could work basically making defaults a private object of the plugin to be able to play with it in all the functions (reuse the loadData function).
(function($) {
var defaults = {
url: '',
onSelect: function(){},
loadData: function(me,url){
$.get(url || this.url).done(function(res){
var opts = '';
for (i in res){
opts += '<option value='+res[i].id+'>'+res[i].name + '</option>';
}
me.html(opts);
});
}
};
$.fn.extend({
GMselect: function(options){
var me = $(this);
var options = $.extend(defaults, options);
options.loadData(me);
$(this).change( options.onSelect );
},
reload:function(url){
var me = $(this);
defaults.loadData(me,url)
}
});
}(jQuery));
Call with GMSelect:
$("#mySelect").GMselect({url:"JSON.json"})
JSON.json file:
[{"id":10,"name":"Apple"},{"id":45,"name":"Melon"},{"id":12,"name":"Kiwi"}]
Result
Call with reload:
$("#mySelect").reload("JSON2.json")
JSON2.json file:
[{"id":10,"name":"RED"},{"id":45,"name":"PURPLE"},{"id":12,"name":"BLACK"}]
Result
Basically the changes made were to add the function reload and make defaults private inside the plugin to use it in all the functions available in this case the defaults.loadData(me,url) inside the function reload.

How to add values on Javascript?

I'm a very beginner on this and wondering is there anyway that I can add these two values
maxScreenWidth: 480,
menuTitle: 'Menu:'
into this script.
function DropDown(el) {
this.mainNav = el;
this.initEvents();
}
DropDown.prototype = {
initEvents: function () {
var obj = this;
obj.mainNav.on('click', function (event) {
$(this).toggleClass('active');
event.stopPropagation();
});
}
}
$(function () {
var mainNav = new DropDown($('#mainNav'));
$(document).click(function () {
// all dropdowns
$('.dropdown-menu').removeClass('active');
});
});
thanks in advance.
In addition, this is the dropdown menu that I'm applying to my website.
http://tympanus.net/Tutorials/CustomDropDownListStyling/index2.html
I'm trying to apply this menu only for phone layout but it maintains its form no matter what screen size is. It is supposed be disappeared when it's more 480px but it isn't.
Thank you so much for your help.
If you want to add those properties, just add them like below:
function DropDown(el, width, title) {
this.mainNav = el;
this.maxScreenWidth = width; //added
this.menuTitle = title; //added
this.initEvents();
}
Now they are part of your constructor as passable arguments
Then when you call you constructor, just pass what those values should be
$(function () {
var mainNav = new DropDown($('#mainNav'), 480, 'Menu'); //See, pass them here.
$(document).click(function () {
// all dropdowns
$('.dropdown-menu').removeClass('active');
});
});
You can add this values as DropDown parameters as Christoper wrote, also you can create global variables:
var maxScreenWidth = 480;
var menuTitle = 'Menu:';
function DropDown(el) {
this.mainNav = el;
this.initEvents();
}
//...
But then, if you write it in your js file, other code could access and change your global variables (they are global after all :) ), so this technique exists:
(function ($) {
var maxScreenWidth = 480;
var menuTitle = 'Menu:';
function DropDown(el) {
this.mainNav = el;
this.initEvents();
}
//...
}(jQuery));
In the last example you'r creating function with 'private scope', so your 'private' variables ain't accessible from other js code. Also you should note that you couldn't access DropDown from other code in you application, only within this function.

Click Function on jQuery plugin only allows for single click

I've created this simple plugin to add multiple animations on click but the problem is that once the object is clicked it can not repeat the animation by clicking again, i can't figure out why the added class is not removing itself after the click function is complete to allow it to be clicked again and repeat.. any suggestions?
(function($) {
$.fn.vivify = function(options) {
var defaults = {
animation: 'bounce',
};
var options = $.extend(defaults, options);
return this.each(function() {
var o = options;
var obj = $(this);
var animation = o.animation;
obj.bind("click", function() {
obj.addClass(o.animation);
obj.addClass('vivify');
}, function() {
obj.removeClass(o.animation);
});
})
}
})(jQuery);​
Here's a working example (I guess, because I don't know exactly what's the intended effect of your plugin):
http://jsfiddle.net/gabrieleromanato/Fmr9g/
obj.bind("click", function() {
obj.addClass(o.animation);
obj.addClass('vivify');
},
// this callback is not valid
function() {
obj.removeClass(o.animation);
});
because .bind() accept parameters like following:
.bind(eventName, [eventData], [callback])
Read about .bind()
To remove class you can do:
obj.bind("click", function() {
obj.addClass(o.animation);
obj.addClass('vivify');
// you can removeClass here
obj.removeClass(o.animation);
// but you need some delay
setTimeou(function() {
obj.removeClass(o.animation);
}, 5000);
});
To increase the timeout you can do following:
return this.each(function(index, val) {
var o = options;
var obj = $(this);
var animation = o.animation;
obj.bind("click", function() {
obj.addClass(o.animation);
obj.addClass('vivify');
}, index * 2000);
});

Building simple jQuery plugin, need assistance

I'm building my first ever jQuery plugin (it's just a simple experiment). Here's what I have so far:
(function($){
$.fn.extend({
auchieFader: function(options) {
var defaults = {
mask: '',
topImg : '',
}
var options = $.extend(defaults, options);
return this.each(function() {
var o = options;
var obj = $(this);
var masker = $(o.mask, obj);
masker.hover(function () {
$(o.topImg).stop().animate({
"opacity": "0"
}, "slow");
}, function () {
$(o.topImg).stop().animate({
"opacity": "1"
}, "slow");
});
});
}
});
})(jQuery);
I'm then calling the plugin using:
$('.fader').auchieFader({mask: ".mask", topImg: ".top"});
If I then add another request say:
$('.fader2').auchieFader({mask: ".mask", topImg: ".top"});
Then no matter what instance of my 2 faders I hover both of them will trigger. I know this is because my mask mask and topImg options have the same class - but how can I modify the plugin to allow for these items to have the same class? I know it's probably something really simple, but I'm still finding my way with jQuery and Javascript in general. Any other tips on improving my code would also be greatly appreciated!
Cheers,
Chris
You seem to already have the answer to your question in the code. For the masker you wrote this:
var masker = $(o.mask, obj);
Which scopes the class in o.mask inside of the dom element obj
I think you just need to do the same thing for o.topImg.
Try changing
masker.hover(function () {
$(o.topImg)
into
masker.hover(function () {
$(o.topImg, obj)
try this:
(function($){
$.fn.extend({
auchieFader: function(options) {
var
// defaults options
defaults = {
mask: null,
topImg: null
},
// extend options in defaults
o = $.extend(defaults, options);
if (!o.mask || !o.topImg) return this;
return this.each(function() {
var
masker = $(o.mask, this),
topImg = $(o.topImg, this);
if (masker.length == 0 || topImg.length == 0) return;
masker.hover(
function () { topImg.stop().animate({ "opacity": "0" }, "slow"); },
function () { topImg.stop().animate({ "opacity": "1" }, "slow"); }
);
});
};
});
})(jQuery);

Categories

Resources