JQuery plugin function calling - javascript

I want to call jquery plugin function from my page, but I fail:(. My code is:
var pstps=$('#psteps_simple_horiz_layout').psteps({
steps_width_percentage: true,
alter_width_at_viewport: '1300',
steps_height_equalize: true
});
step_num=2;
pstps.go_to_step(step_num);
The plugin is Pine Steps wizard. It's code is:
function($) {
$.fn.psteps = function(options) {
// Build main options before element iteration.
var opts = $.extend({}, $.fn.psteps.defaults, options);
// Iterate and transform each matched element.
var all_elements = this;
all_elements.each(function(){
var psteps = $(this);
psteps.psteps_version = "0.0.1alpha";
.......................................................
psteps.go_to_step = function(step_num){
var last_active_title = psteps.find('.step-title.last-active'),
.......................................................
};
.......................................................
this.pines_steps = psteps;
});
return all_elements;
};
When I run my code I get error:
Uncaught TypeError: undefined is not a function

It is failing on the following line because go_to_steps is not a jQuery extension (and the return value from psteps() is the original jQuery object:
pstps.go_to_step(step_num);
You need the instance of the actual plugin. Looking at the plugin code, it connects the instance as a property on the DOM element called pines_steps, so you need to get that property as your class instance:
var pstps=$('#psteps_simple_horiz_layout').psteps({
steps_width_percentage: true,
alter_width_at_viewport: '1300',
steps_height_equalize: true
})[0].pines_steps;
Then you can call
pstps.go_to_step(step_num);
Common pattern:
The usual way plugins are authored is to also accept a function name, as a string, in a first parameter, so they can call methods like this:
$('#psteps_simple_horiz_layout').psteps("go_to_step", step_num);
however this plugin is missing the code to do that

Related

Jquery Plugin: Object not accessible from same instance

I'm making my first Jquery Plugin and overcome many problems after I found one that I can not find solution.
The plugin convert a table in a tree-gridview doing a $(element).treeGD(); sentence, that part works ok. But i want to reload all data doing $(element).treeGD.reload();
The first sentence creates an object objTreeGD(obj):
$.fn.treeGD = function () {
var treeGD = new objTreeGD(this);
And adding the second method in the way i'll show you now and trying to use the same treeGD object created above gives me an error (undefined)
$.fn.treeGD.reload = function () {
var urlDatos = treeGD.attr("data-url");
Is there a way to access to that firs object i've created?
Thanks
May be you can use .data() method?
$.fn.treeGD = function () {
var treeGD = new objTreeGD(this);
this.data("myTree", treeGD );
And then, access using:
$.fn.treeGD.reload = function () {
var urlDatos = this.data("myTree").attr("data-url");

javascript codes are not responding properly

i am trying calculate the amount but having troble with jQuery .. can you guys please tell me whats wrong with my codes.
my Javascript and jQuery codes are:
i have change this as:
$(document).ready(function() {
$('.home_banner').cycle({
fx: 'fade'
});
$("#tabs").tabs();
});
and calculator codes as:
var u_rate = new Array();
u_rate[0] = new Array();
u_rate[0][0] = 1.022;
u_rate[0][1] = 0.75;
u_rate[1] = new Array();
u_rate[1][0] = 1.034;
u_rate[1][1] = 0.78;
calc();
function calc(){
var result = '';
var id = '';
id = 'u';
curr = u_rate;
var curin_id = jquery("#"+id+"currency_in").attr("selectedIndex");
var curout_id = jquery("#"+id+"currency_out").attr("selectedIndex");
var value_float = parseFloat(jquery("#"+id+"value").val());
if(value_float>0){
result=value_float*curr[curin_id][curout_id];
result=Math.round(result*100)/100;
}
jquery("#"+id+"result").val(result);
return true;
}
but still getting no response .. please check this and let me know
and the html is
please check on ukash2gold.com
please friends let me know how to resolve the issue ..
u will able to see the form under the tab of [Ukash to LR]
typeof jQuery yields "function" but typeof $ yields "undefined". Are you loading jQuery in noConflict mode?
Edit 1
Yes you are; your slideshow code starts off like this:
var $jnav=jQuery.noConflict();
See noConflict.
Edit 2
As far as I can tell, you're not using any other framework that uses the $ variable. In that case, you can safely remove noConflict from your slideshow:
<script type="text/javascript">
$(function() {
$('.home_banner').cycle({
fx: 'fade' // choose your transition type, ex: fade, scrollUp, shuffle, etc...
});
$("#tabs").tabs();
});
</script>
If you're using another framework somewhere else on the site, and need to stick to running jQuery in noConflict mode, you'll have to modify your jQuery code to use jQuery rather than the $ shorthand.
jQuery('#'+id+'result').val(result);
... etc.
Edit 3
Now you're seeing the error Uncaught TypeError: Cannot read property 'undefined' of undefined at this line:
result=value_float*curr[curin_id][curout_id];
What this means is, in your case, that curin_id and curout_id are both undefined. Therefore you're trying to access a property 'undefined' (curout_id) at the object 'undefined' (curr[curin_id] which will yield undefined since curin_id is in itself undefined).
The cause for this is the following code:
var curin_id = $("#"+id+"currency_in").attr("selectedIndex");
var curout_id = $("#"+id+"currency_out").attr("selectedIndex");
selectedIndex is not an attribute of the select but a property of it. Although properties are native JavaScript constructions, you can read about them in the jQuery documentation.
A simple fix in your case would be to change from attr() to prop():
var curin_id = $("#"+id+"currency_in").prop("selectedIndex");
var curout_id = $("#"+id+"currency_out").prop("selectedIndex");
Another solution would be to look at the index of the selected element, within its parent:
var curin_id = $('#'+id+'currency_in option:selected').index();

Mocking jQuery to test basic use

I'm having a very hard time understanding how to setup an object that allows me to test my jQuery calls. I don't need to mock any Async calls or anything, just basic use. So let me set out my function that I want to test (truncated for simplicity):
listGamesCallback : function(data) {
var gameList = $("#gameList select");
gameList.empty();
$.each(data, function() {
var newOption = $('<option>', {value : this.gameId });
newOption.text(string);
newOption.data("isJoinable", isJoinable);
// Add it to the list
gameList.append(newOption);
});
}
I need to mock the jQuery here to unit test this method, but I'm unable to figure out how to do this in javascript. Even without jsMockito, I don't know how to create an object with the properties that jQuery has in this situation. Any help with this would be appreciated.
I am using jsTestDriver, jsHamcrest, jsMockito and jQuery. However a generalized approach to create a $ object that has these properties would be awesome as well. Thank you!
For those that asked, here is what I came up with that seemed to kinda work..but I don't understand why.
var saved$ = $;
var mockContruct = mockFunction();
var mockedGamelist = mock(jQuery);
var mockedOption = mock(jQuery);
mocked$ = (function() {
var test = function(name) {
var args = jQuery.makeArray(arguments);
return mockContruct.call(test, args);
};
$.extend(test, $);
// This is what confuses me. This worked, but it's wierd
// It allows me to use the regular jQuery functions like
// $.each, while returning mocked objects when selectors are used.
test.prototype.constructor = test;
return test;
})();
$ = mocked$;
when(mockContruct).call(anything(), hasItem(containsString("#gameList")))
.thenReturn(mockedGamelist);
when(mockContruct).call(anything(), hasItems(containsString("<option>"), both(object()).and(hasMember("value"))))
.thenReturn(mockedOption);
headerFunctions.listGamesCallback([ {
gameId : 1,
isWhitesTurn : false,
isGameOver : false,
whiteUserName : "foobar",
blackUserName : "barfoo"
} ]);
JsMockito.verify(mockedGamelist).empty();
JsMockito.verify(mockedGamelist).append(mockedOption);
$ = saved$;
Ok, here what I came up with that does the job with minimal setup. The .extend is completely necessary here so that the jQuery object is setup correctly. This allows you to mock the constructor to return mocked jQuery objects that you can use to run your tests on. As a spy, jQuery will work as expected in all situations except when you want it to do something else. Here it is:
TestCase("HeaderTest", {
testListGamesCallback : function () {
var saved$ = $;
$ = $.prototype.construct = jQuery.extend(spy(jQuery), jQuery);
var mockGameList = mock(jQuery);
when($)(containsString("#gameList")).thenReturn(mockGameList);
headerFunctions.listGamesCallback([ {
gameId : 1,
isWhitesTurn : false,
isGameOver : false,
whiteUserName : "foobar",
blackUserName : "barfoo"
} ]);
verify(mockGameList).empty();
verify(mockGameList).append(object());
$ = saved$;
}
});
The caveat to this solution is that mocking anything other than the constructor is a bit tricky. You will have to set each individual function that you want to mock, then program the behavior. So:
$.each = mockFunction();
when($.each)(...matchers...).thenReturn(...);
But it still allows for testing what you need to.
As an extension to alpian's answer, you can create DOM elements without having to add them to the page. Make your JS functions take the relevant elements as parameters:
listGamesCallback : function(data, gameListSelectElem) {
var gameList = $(gameListSelectElem);
...
and test them like so:
var fakeSelect = $('<select>'),
data = ...;
listGamesCallback(data, fakeSelect[0]);
equal(fakeSelect.find('option').length, 1, 'must have exactly 1 option');
...
The last line of code above is for qUnit. Take whatever you need, the point is to say you can pass a DOM element that was never added to the page and afterwards investigate that DOM element using jQuery to find whether it was manipulated right.
No sure if i understand what you mean but if you want to create 'data' for you example , this is the method i know:
var data = [ { id : 1 , name : 'foo' } , { id : 2, name : 'bar' ] ​
but - if you wanted to create a list of options, than you code needs a couple of fixes:
see http://jsfiddle.net/7MMap/
var data = [ { gameId : 1 , name : 'foo' ,isJoinable:true} , { gameId : 2, name : 'bar' ,isJoinable:false}]
listGamesCallback = function(data) {
var gameList = $("#gameList select")
.empty();
$.each(data, function(i,d) {
var newOption = $('<option>', {value : d.gameId })
.text(d.name)
.data("isJoinable", d.isJoinable);
// Add it to the list
gameList.append(newOption);
})
};
listGamesCallback(data);
Mocking jQuery is not what mocking is for. You should only ever be mocking your object's collaborators. jQuery is providing you with some utilities - it's not a collaborator and hence should not be mocked.
What you are collaborating with here is the DOM, or some intermediate object between your code and the DOM. data is a value object and can simply be created in your test as Avi suggests.
In my JS tests, i don't mock the DOM, i use the real DOM and am sure to tear down anything i created between tests and this seems to work pretty well.

How can I provide a public function in a jQuery plugin?

I have written a small jQuery plugin with the following structure:
(function($) {
// Private vars
// Default settings
$.PLUGINNAME = {
id: 'PLUGINNAME',
version: '1.0',
defaults: {
min: 0,
max: 10
}
};
// extend jQuery
$.fn.extend({
PLUGINNAME: function(_settings) {
init = function() {
}
prepare = function() {
}
...
return this.each(function() {
_this = this;
init();
});
}
});
})(jQuery);
I am calling this as follows:
$("#update-panel").PLUGINNAME({
min: 1,
max: 20
});
I am trying to provide an additional public method where some data inside the function can be updated after the above function call to the plugin and am not sure how to go about doing this. What I am looking for is something like this:
_PluginInstance = $("#update-panel").PLUGINNAME({
min: 1,
max: 20
});
...
...
_PluginInstance.setMin(2); //should change the minimum to 2
setMin will probably use some of the plugin's internal variables so I am not understanding how to do this. I know I am not returning an instance of the plugin to do the above but can someone please tell me how to go about doing this by keeping the same plugin structure?
Just make the function a property of this within the PLUGINNAME object:
(function($) {
$.PLUGINNAME = {
// Default settings
};
// extend jQuery
$.fn.extend({
PLUGINNAME: function(_settings) {
// private methods
var init = function() {};
var prepare = function() {};
// public methods
this.setMin = function ( val ) {
_settings.min = val;
};
this.getMin = function () {
return _settings.min;
};
return this.each(function() {
_this = this;
init();
});
}
});
})(jQuery);
Then you could do:
_PluginInstance = $("#update-panel").PLUGINNAME({
min: 1,
max: 20
});
_PluginInstance.getMin(); // 1
_PluginInstance.setMin(2);
_PluginInstance.getMin(); // 2
EDIT: Oh god I can't believe I forgot the var keywords, why didn't y'all tell me my fly was down?
You could use the jQuery-UI method calling style:
$("#update-panel").PLUGINNAME('method', arguments...);
And then in your plugin:
PLUGINNAME: function(_settings, args) {
if(!$.isPlainObject(_settings)) {
// _settings (should) be the method name so
// do what needs to be done to execute the method.
return;
}
// Proceed as before.
You might want to use the arguments pseudo-array instead of the extra args parameter. You can store extra things in $(this).data('PLUGINNAME') inside your PLUGINNAME function if you need to attach internal data to your individual objects.
Not a jQuery guy myself, and mu is too short's answer seems to be the right one. But I'd imagine you could also do like it says on jQuery's own docs and use the .data() method to store the min/max values.
In other words, make your code look for existing data on the elements, so the first time you call $('#update_panel').plugin({min:1, max:20}), it won't find any existing data, so it'll place those min/max values in an object and "save" them using .data().
Then, when you later call $('#update_panel').plugin({min:2}) your code finds the existing data, and updates the values.
Just an idea
You can define a variable just like you've defined a plugin.
$.fn.PLUGINNAME.someVariable = 4;
or if you prefer, just declare an empty variable outside the plugin and then add to it from inside the plugin
var someVariable;
(function($) {
... the plugin code
})(jQuery);

call function inside a nested jquery plugin

There are many topics related to my question and i have been through most of them, but i haven't got it right. The closest post to my question is the following:
How to call functions that are nested inside a JQuery Plugin?
Below is the jquery plugin i am using. On resize, the element sizes are recalculated. I am now trying to call the function resizeBind() from outside of the jquery plugin and it gives me error
I tried the following combinations to call the function
$.fn.splitter().resizeBind()
$.fn.splitter.resizeBind()
Any ideas, where i am getting wrong?
;(function($){
$.fn.splitter = function(args){
//Other functions ......
$(window).bind("resize", function(){
resizeBind();
});
function resizeBind(){
var top = splitter.offset().top;
var wh = $(window).height();
var ww = $(window).width();
var sh = 0; // scrollbar height
if (ww <0 && !jQuery.browser.msie )
sh = 17;
var footer = parseInt($("#footer").css("height")) || 26;
splitter.css("height", wh-top-footer-sh+"px");
$("#tabsRight").css("height", splitter.height()-30+"px");
$(".contentTabs").css("height", splitter.height()-70+"px");
}
return this.each(function() {
});
};
})(jQuery);
I had the same problem. Those answers on related posts didn't work for my case either. I solved it in a round about way using events.
The example below demonstrates calling a function that multiplies three internal data values by a given multiplier, and returns the result. To call the function, you trigger an event. The handler in turn triggers another event that contains the result. You need to set up a listener for the result event.
Here's the plugin - mostly standard jQuery plugin architecture created by an online wizard:
(function($){
$.foo = function(el, options){
// To avoid scope issues, use 'base' instead of 'this'
var base = this;
// Access to jQuery and DOM versions of element
base.$el = $(el);
base.el = el;
// Add a reverse reference to the DOM object
base.$el.data("foo", base);
base.init = function(){
base.options = $.extend({},$.foo.defaultOptions, options);
// create private data and copy in the options hash
base.private_obj = {};
base.private_obj.value1 = (base.options.opt1);
base.private_obj.value2 = (base.options.opt2);
base.private_obj.value3 = (base.options.opt3);
// make a little element to dump the results into
var ui_element = $('<p>').attr("id","my_paragraph").html(base.private_obj.value1 +" "+ base.private_obj.value2+" " +base.private_obj.value3);
base.$el.append(ui_element);
// this is the handler for the 'get_multiplied_data_please' event.
base.$el.bind('get_multiplied_data_please', function(e,mult) {
bar = {};
bar.v1 = base.private_obj.value1 *mult;
bar.v2 = base.private_obj.value2 *mult;
bar.v3 = base.private_obj.value3 *mult;
base.$el.trigger("here_is_the_multiplied_data", bar);
});
};
base.init();
}
$.foo.defaultOptions = {
opt1: 150,
opt2: 30,
opt3: 100
};
$.fn.foo = function(options){
return this.each(function(){
(new $.foo(this, options));
});
};
})(jQuery);
So, you can attach the object to an element as usual when the document is ready. And at the same time set up a handler for the result event.
$(document).ready(function(){
$('body').foo();
$('body').live('here_is_the_multiplied_data', function(e, data){
console.log("val1:" +data.v1);
console.log("val2:" +data.v2);
console.log("val3:" +data.v3);
$("#my_paragraph").html(data.v1 +" "+ data.v2+" " +data.v3);
});
})
All that's left is to trigger the event and pass it a multiplier value
You could type this into the console - or trigger it from a button that picks out the multiplier from another UI element
$('body').trigger('get_multiplied_data_please', 7);
Disclaimer ;) - I'm quite new to jQuery - sorry if this is using a hammer to crack a nut.
resizeBind function is defined as private so you cannot access it from outside of it's scope. If you want to use it in other scopes you need to define it like that
$.fn.resizeBind = function() { ... }
Then you would call it like that $(selector').resizeBind()
You have defined the resizeBind function in a scope that is different from the global scope. If you dont'use another javascript framework or anything else that uses the $ function (to prevent conflict) you can delete the
(function($){
...
})(jQuery);
statement and in this way the function will be callable everywhere without errors
I didn't test it:
this.resizeBind = function() { .... }

Categories

Resources