JQuery/JavaScript : refactoring nested functions - javascript

I have this interesting jQuery function. It basically adds a click handler to link, and when that is clicked, it will load a form to allow the user to edit the content. and the form is submitted by AJAX, and will display a success message when it's done.
The outline is below; needless to say, this is messy. I could have each of the callback as a class method. What other ways are there to refactor nested functions? I am also interested to see if there are ways that variables declare in a parent function still retain its value down to the nested function after refactoring
$('a.edit').click( function() {
// ..snipped..
// get form
$.ajax({
success: function() {
// add form
// submit handler for form
$(new_form).submit(function() {
// submit via ajax
$.ajax({
success: function(data) {
// display message
}
})
})
}}
)
}

I guess the interesting part of your question is how to refactor without loosing access to the closure variables. Here is my suggestion:
Version one: nested, with closures and variable access:
var a;
$('a.edit').click( function() {
var b;
$.ajax({
success: function() {
var c;
$(new_form).submit(function() {
var d;
$.ajax({
success: function(data) {
// a,b,c,d are all visible here.
// note that a references the same object for all calls of the success function, whereas d is a different variable for each call of submit.
// this behaviour is called closure: the 'enclosed' function has access to the outer var
}
})
})
}
})
})
Version two: less nested, but without closures and without variable access:
var a;
$('a.edit').click(onEdit);
var onEdit = function() {
var b;
$.ajax({success: onEditSuccess});
};
var onEditSuccess = function() {
var c;
$(new_form).submit(onSubmit);
};
var onSubmit = function() {
var d;
$.ajax({success: onSubmitSuccess});
}
var onSubmitSuccess = function(data) {
// a is visible (global var)
// b,c,d NOT visible here.
};
Version three: less nested and with unnamed functions and parameters to get access to the closure variables:
var a;
$('a.edit').click(function(){onEdit(a)});
var onEdit = function(a) {
var b;
$.ajax({success: function(){onEditSuccess(a,b)}});
};
var onEditSuccess = function(a,b) {
var c;
$(new_form).submit(function(){onSubmit(a,b,c)});
};
var onSubmit = function(a,b,c) {
var d;
$.ajax({success: function(data){onSubmitSuccess(data,a,b,c,d)}});
}
var onSubmitSuccess = function(data,a,b,c,d) {
// a,b,c,d are visible again
// nice side effect: people not familiar with closures see that the vars are available as they are function parameters
};

You can easily refactor this to make it much more readable. The key concept to grasp is that you can refer to named functions in callbacks as well as anonymous ones. So, for instance:
function clickHandler() {
alert("Link clicked");
}
$('a').click(clickHandler);
My preference is always to give the functions names according to what they do (e.g. loadImage, rather than the event that you intend to trigger them (e.g. clickLink. This makes your code clearer and makes later changes much easier. In this case, I would structure my code like this:
$(document).ready(function(){
$('a.edit').click(loadFormStart);
function loadFormStart() { // get form
$.ajax({
success: loadFormEnd
});
}
function loadFormEnd(data) { // add form & handler
$('new_form').submit(handleFormStart);
}
function handleFormStart() { // submit form
$.ajax({
success: handleFormEnd
});
}
function handleFormEnd(data) { // receive form data
//display message
}
});
I'd also advise you to read Code Organization on jqfundamentals which gives a similar approach to this using an object literal.

Interesting question. Personally I don't mind the above. Commenting is key, so you could consider qualifying the closing braces with some:
} //success: function(data)
}) //$.ajax({
}) //$(new_form).submit(
...etc
I would also look at aligning the brackets correctly (at first clance, your }} is a little mystifying).
If it comes to 'generic' nesting strategies, the only other suggestion I have is to move code out other functions. The of course means that you have the function decalred in memory, but may make it more readable.
You could also consider a specific strategy that relates to this code. For example, rather than manually binding a submit to new_form can you use the live function in some way to ensure that it is done automatically?
On a completely unrelated note, you should probably add some ; at the end of each of the bracketed lines!

Related

Is it bad practice to instantiate variables inside of $(document).ready as opposed to globally declaring them?

I'm trying to avoid the use of global variables in my code, so I'm trying to use a work around by declaring them inside of $(document).ready and passing them as parameters to functions outside of $(document).ready, updating them, and then returning the updated value from those functions to manipulate the variables inside of $(document).ready.
Another way around this is to use hidden input fields to store variables but I also heard that was bad practice.
I'm wondering if I should just use global variables, do it the way I'm currently doing it, or use hidden input fields?
Below is a brief example of what I'm trying to accomplish. The variable validations is the variable I want to be able to use and update.
$(document).ready(function(){
var validations = [];
$('#inp').keypress(function(e){
if(e.which == 13){
e.preventDefault();
scanValidation(validations, function(valid){
validations = valid;
});
}
});
}):
function scanValidation(valid, cb){
var scanval = $('#inp').val();
if(valid.includes(scanval)){
//display error
}
else{
var validarr = valid.slice();
validarr.push(scanval);
var myData=JSON.stringify({ "name":"user1", "validations":validarr});
//Makes an ajax call to see if the sent array validarr is a valid request
apiCall(myData,'scanValidation',function(decoded) {
if (decoded.Status!="ERROR") {
valid = validarr;
}
else {
//display error
}
return(cb(valid));
});
}
}
Any variables declared within the immediately executed function below will NOT be in the global scope.
(function () {
var someVar = 'someValue';
$(document).ready(function() {
});
})();
Is it bad practice to instantiate variables inside of $(document).ready as opposed to globally declaring them?
No, not at all! Variables should always be declared in the scope they're needed in, nowhere else.
Another way around this is to use hidden input fields to store variables but I also heard that was bad practice.
I've never heard of that, but yes it definitely sounds like a bad practise. That's just the same as a global variable, but a global variable stored in the DOM for some odd reason.
I'm trying to avoid the use of global variables in my code, so I'm trying to use a work around by declaring them inside of $(document).ready and passing them as parameters to functions outside of $(document).ready, updating them, and then returning the updated value from those functions to manipulate the variables inside of $(document).ready.
That, admittedly, is a bit weird.
The easiest way to improve this is to move the function declaration inside the ready handler as well, and just access the variable there directly - with the additional bonus of not having a scanValidation global variable:
$(document).ready(function() {
var validations = [];
function scanValidation() {
var scanval = $('#inp').val();
if (validations.includes(scanval)) {
//display error
} else {
var validarr = validations.slice();
validarr.push(scanval);
var myData = JSON.stringify({"name": "user1", "validations": validarr});
// Makes an ajax call to see if the sent array validarr is a valid request
apiCall(myData, 'scanValidation', function(decoded) {
if (decoded.Status!="ERROR") {
validations = validarr;
} else {
//display error
}
});
}
}
$('#inp').keypress(function(e){
if(e.which == 13){
e.preventDefault();
scanValidation();
}
});
});
If you want to make scanValidation reusable, so that it could be called from other places as well with its own array, I would suggest to create a factory function that creates validators, each of which is a closure over its own array. That way, the array is declared where it belongs, so that the user of the function does not have to store the state for them:
function makeScanValidator(display) { // any other configuration
var validations = [];
// returns closure
return function scanValidation(scanval) { // take it as an argument
if (validations.includes(scanval)) {
display(/* error */);
} else {
var validarr = validations.concat([scanval]);
var myData = JSON.stringify({"name": "user1", "validations": validarr});
apiCall(myData, 'scanValidation', function(decoded) {
if (decoded.Status!="ERROR") {
validations = validarr;
} else {
display(/* error */);
}
});
}
}
$(document).ready(function() {
var validate = makeScanValidator(function display() { … });
$('#inp').keypress(function(e){
if(e.which == 13){
e.preventDefault();
validate(this.value);
}
});
});

JS Revealing Pattern event undefined issue

I am using the modular design pattern for JS and I keep running into issues when using arguments bound functions. I have a particular function that I would like to bind to different events to keep from having to write the function for each bound event. The only difference in the function, or the argument, is the table that will be updated. The problem is that when I build a function with the arguments I need and pass those arguments to bound events, I get an undefined error, in the console, on load. Keep in mind, I want to stick with this design pattern for the security it offers.
Here is my JS:
var Users = (function(){
var $addRoleForm = $('#addUserRole');
var $rolesTableBody = $('#table-roles tbody');
$addRoleForm.submit(ajaxUpdate(event, $rolesTableBody));
function ajaxUpdate(event, tableName) {
event.preventDefault();
event.stopPropagation();
var url = this.action;
var data = $(this).serialize();
var $this = $(this);
$.ajax({
type: 'POST',
url: url,
dataType: 'json',
data: data,
success: function(data) {
if(data.st === 0){
$messageContainer.html('<p class="alert alert-danger">' + data.msg + '</p>');
setTimeout(function(){
$messageContainer.hide();
}, 7000);
} else {
$messageContainer.html('<p class="alert alert-success">' + data.msg + '</p>');
tableName.fadeOut().html('').html(data.build).fadeIn();
$this.find('input').val('');
setTimeout(function(){
$messageContainer.hide();
}, 7000);
}
},
error: function(xhr, status, error){
console.log(xhr.responseText);
}
});
}
})();
Here is the error I get in the console, on load:
Uncaught TypeError: Cannot read property 'preventDefault' of undefined
I have tried to bind the event like this: $addRoleForm.on('submit', ajaxUpdate(event, $rolesTableBody)); and receive the same results.
Any ideas how to fix this?
You're seeing that issue, because the way you have it written now, ajaxUpdateexecutes, returns undefined and THEN passes undefined to the event listener, so you're basically doing this: $addRoleForm.submit(undefined).
2 Choices here:
1) You can wrap it in an anonymous function:
$addRoleForm.submit(function(event) {
//pass the value of "this" along using call
ajaxUpdate.call(this, event, someValue);
});
$someOtherForm.submit(function(event) {
//pass the value of "this" along using call
ajaxUpdate.call(this, event, someOtherValue);
});
2) You can set the first argument in-advance using bind:
$addRoleForm.submit(ajaxUpdate.bind($addRoleForm, someValue));
$someOtherForm.submit(ajaxUpdate.bind($someOtherForm, someOtherValue));
Using this way, you're binding the value of this to be $addRoleForm, setting the first argument to always be someValue, so it's the same as:
ajaxUpdate(someValue, event) {
//value of "this" will be $addRoleForm;
}
To pass the event, and the custom argument, you should be using an anonymous function call
$addRoleForm.submit(function(event) {
ajaxUpdate(event, $rolesTableBody));
});
This is by far the easiest and most readable way to do this.
What you're doing right now equates to this
var $addRoleForm = $('#addUserRole');
var $rolesTableBody = $('#table-roles tbody');
var resultFromCallingFunction = ajaxUpdate(event, $rolesTableBody); // undefined
$addRoleForm.submit(resultFromCallingFunction);
Where you're calling the ajaxUpdate function, as that's what the parentheses do, and pass the returned result back to the submit callback, which in your case is undefined, the default value a function returns when nothing else is specified.
You could reference the function, like this
$addRoleForm.submit(ajaxUpdate);
but then you can't pass the second argument
The question refers to the Revealing Module pattern. Benefit of using this design is readability. Going with the anon function may work, but defeats the overall purpose of the module pattern itself.
A good way to structure your module to help maintain your scope is to setup helper functions first, then call a return at the end.
Example use case with events:
var User = function() {
// local VARS available to User
var addRoleForm = document.querySelector('#addUserRole');
var rolesTableBody = document.querySelector('#table-roles tbody');
// Helper function 1
function ajaxUpdate(tableName) {
...
}
// Helper function 2
function someFunc() {
...
}
function bindEvents() {
addRoleForm.addEventListener('submit', ajaxUpdate, false);
addRoleForm.addEventListener('click', someFunc, false);
}
function init() {
bindEvents();
}
return {
runMe:init
}
}().runMe();
Helps to "modularize" your workflow. You are also writing your revealing pattern as an IIFE. This can cause debugging headaches in the future. Editing the IIFE to instead invoke via the return is easier to maintain and for other devs to work with and learn initially. Also, it allows you to extend outside of your IFFE into another Module, example:
var Clothes = function() {
function anotherFunc() {
...
}
init() {
User.runMe();
anotherFunc();
}
return {
addClothes: init
}
}().addClothes();
I hope this helps to give you a better understanding of how/when/why to use the JS revealing pattern. Quick note: You can make your modules into IIFE, that's not a problem. You just limit the context of the scope you can work with. Another way of doing things would be to wrap the var User and var Clothes into a main module, and then make that an IIFE. This helps in preventing polluting your global namespace.
Example with what I wrote above:
// MAIN APPLICATION
var GettinDressed = (function() {
// MODULE ONE
///////////////////////////
Var User = function() {
// local VARS available to User
var addRoleForm = document.querySelector('#addUserRole');
var rolesTableBody = document.querySelector('#table-roles tbody');
// Helper function 1
function ajaxUpdate(tableName) {
...
}
// Helper function 2
function someFunc() {
...
}
function bindEvents() {
addRoleForm.addEventListener('submit', ajaxUpdate, false);
addRoleForm.addEventListener('click', someFunc, false);
}
function init() {
bindEvents();
}
return {
runMe:init,
style: someFunc
}
}();
// MODULE TWO
//////////////////////////
var Clothes = function() {
function anotherFunc() {
...
}
init() {
User.style();
anotherFunc();
}
return {
dressUp: init
}
}();
// Define order of instantiation
User.runMe();
Clothes.dressUp();
}());

need help understanding closures usage in this code

Here is a simplified snippet from some code I wrote for managing tablet gestures on canvas elements
first a function that accepts an element and a dictionary of callbacks and register the events plus adding other features like 'hold' gestures:
function registerStageGestures(stage, callbacks, recieverArg) {
stage.inhold = false;
stage.timer = null;
var touchduration = 1000;
var reciever = recieverArg || window;
stage.onLongTouch = function(e) {
if (stage.timer) clearTimeout(stage.timer);
stage.inhold = true;
if (callbacks.touchholdstart) callbacks.touchholdstart.call(reciever, e);
};
stage.getContent().addEventListener('touchstart', function(e) {
e.preventDefault();
calcTouchEventData(e);
stage.timer = setTimeout(function() {
stage.onLongTouch(e);
}, touchduration);
if (callbacks.touchstart) callbacks.touchholdstart.call(reciever, e);
});
stage.getContent().addEventListener('touchmove', function(e) {
e.preventDefault();
if (stage.timer) clearTimeout(stage.timer);
if (stage.inhold) {
if (callbacks.touchholdmove) callbacks.touchholdmove.call(reciever, e);
} else {
if (callbacks.touchmove) callbacks.touchmove.call(reciever, e);
}
});
stage.getContent().addEventListener('touchend', function(e) {
e.preventDefault();
if (stage.timer) clearTimeout(stage.timer);
if (stage.inhold) {
if (callbacks.touchholdend) callbacks.touchholdend.call(reciever, e);
} else {
if (callbacks.touchend) callbacks.touchend.call(reciever, e);
}
stage.inhold = false;
});
}
later I call registerStageGestures on a few elements (represented by 'View' objects) in the same page. Something like:
function View() {
var self=this;
..
function InitView() {
...
registerStageGestures(kineticStage, {
touchstart: function(e) {
// do something
},
touchmove: function(e) {
// do something
},
touchendunction(e) {
// do something
},
touchholdstart: function(e) {
// do something
},
touchholdmove: function(e) {
// do something
},
touchholdend: function(e) {
// do something
},
}, self);
Everything works fine, however I'm left wondering about two things in the implementation of registerStageGestures:
First, is it necessary to make inhold, timer and onLongTouch members of the stage ? or will closures make everything works well if they are local vars in registerStageGestures ?
Second, is it necessary to call the callbacks with '.call(receiver,' syntax ? I'm doing this to make sure the callback code will run in the context of the View but I'm not sure if it's needed ?
any input is much appreciated
Thanks!
First, is it necessary to make inhold, timer and onLongTouch members
of the stage ? or will closures make everything works well if they are
local vars in registerStageGestures ?
As far as registerStageGestures() is concerned, var inhold, var timer and function onLongTouch(e) {...}. would suffice. The mechanism by which an inner function has automatic access to its outer function's members is known as "closure". You would only need to set stage.inhold, stage.timer and stage.onLongTouch if some other piece of code needs access to these settings as properties of stage.
Second, is it necessary to call the callbacks with '.call(receiver,'
syntax ? I'm doing this to make sure the callback code will run in the
context of the View but I'm not sure if it's needed ?
Possibly, depending on how those callbacks are written. .call() and .apply() are sometimes used when calling functions that use this internally. In both cases, the first parameter passed defines the object to be interpreted as this. Thus, javascript gives you the means of defining general purpose methods with no a priori assumption about the object to which those methods will apply when called. Similarly, you can call a method of an object in such a way that it acts on another object.
EDIT:
For completeness, please note that even in the absence of this in a function, .apply() can be very useful as it allows multiple parameters to be specified as elements of a single array, eg the ubiquitous jQuery.when.apply(null, arrayOfPromises)...
There are some simple answers, here.
First, closure:
Closure basically says that whatever is defined inside of a function, has access to the rest of that function's contents.
And all of those contents are guaranteed to stay alive (out of the trash), until there are no more objects left, which ere created inside.
A simple test:
var testClosure = function () {
var name = "Bob",
recallName = function () { return name; };
return { getName : recallName };
};
var test = testClosure();
console.log(test.getName()); // Bob
So anything that was created inside can be accessed by any function which was also created inside (or created inside of a function created in a function[, ...], inside).
var closure_2x = function () {
var name = "Bob",
innerScope = function () {
console.log(name);
return function () {
console.log("Still " + name);
}
};
return innerScope;
};
var inner_func = closure_2x();
var even_deeper = inner_func(); // "Bob"
even_deeper(); // "Still Bob"
This applies not only to variables/objects/functions created inside, but also to function arguments passed inside.
The arguments have no access to the inner-workings(unless passed to methods/callbacks), but the inner-workings will remember the arguments.
So as long as your functions are being created in the same scope as your values (or a child-scope), there's access.
.call is trickier.
You know what it does (replaces this inside of the function with the object you pass it)...
...but why and when, in this case are harder.
var Person = function (name, age) {
this.age = age;
this.getAge = function () {
return this.age;
};
};
var bob = new Person("Bob", 32);
This looks pretty normal.
Honestly, this could look a lot like Java or C# with a couple of tweaks.
bob.getAge(); // 32
Works like Java or C#, too.
doSomething.then(bob.getAge);
? Buh ?
We've now passed Bob's method into a function, as a function, all by itself.
var doug = { age : 28 };
doug.getAge = bob.getAge;
Now we've given doug a reference to directly use bobs methid -- not a copy, but a pointer to the actual method.
doug.getAge(); // 28
Well, that's odd.
What about what came out of passing it in as a callback?
var test = bob.getAge;
test(); // undefined
The reason for this, is, as you said, about context...
But the specific reason is because this inside of a function in JS isn't pre-compiled, or stored...
this is worked out on the fly, every time the function is called.
If you call
obj.method();
this === obj;
If you call
a.b.c.d();
this === a.b.c;
If you call
var test = bob.getAge;
test();
...?
this is equal to window.
In "strict mode" this doesn't happen (you get errors really quickly).
test.call(bob); //32
Balance restored!
Mostly...
There are still a few catches.
var outerScope = function () {
console.log(this.age);
var inner = function () {
console.log("Still " + this.age);
};
inner();
};
outerScope.call(bob);
// "32"
// "Still undefined"
This makes sense, when you think about it...
We know that if a function figures out this at the moment it's called -- scope has nothing to do with it...
...and we didn't add inner to an object...
this.inner = inner;
this.inner();
would have worked just fine (but now you just messed with an external object)...
So inner saw this as window.
The solution would either be to use .call, or .apply, or to use function-scoping and/or closure
var person = this,
inner = function () { console.log(person.age); };
The rabbit hole goes deeper, but my phone is dying...

How can I pass this specific variable I'm using jquery-ajax

I want to pass the "passedThisValue" to my "start_battle" function and use the "start_battle" function in my "Rematch". But the modal just hangs why is this happening? what could be wrong? Please help! :) Thank you.
CODE:
function start_battle(){
$.ajax({
data: {
receivePassedValue: passedThisValue
},
success: function(data){
}
});
}
$("#start_battle").click(function() {
$.ajax({
success: function(data){
var toAppend = '';
if(typeof data === "object"){
var passedThisValue = '';
for(var i=0;i<data.length;i++){
passedThisValue = data[i]['thisValue'];
}
start_battle(); // can I still get the passedThisValue?
}
}
});
$("#battle").dialog({
modal:true,
buttons: {
"Rematch": function(){
start_battle(); // can I still get the passedThisValue?
}
}
});
$("#battle").show(500);
});
When you call a function, you don't use function start_battle();, you just use start_battle();.
When you pass a value to a function, you need to use this syntax: start_battle(param1, param2);.
When you want to get a value from a function, you need to return it in the function, like so:
function start_battle(param1) {
// Do something
return param1;
}
When you want to store a returned value from a function, you do something like: var returned = start_battle(param1);
And the fact that you don't know why the modal just hangs, means that you didn't check the browser's error console, which can hold some pretty important information on what's wrong. Try checking that and posting here so we can see the current problem
Your function declaration seems a little off. I think you should leave off the $ from function. Just do this
function start_battle() {
Also, when you're calling a function, you don't say function before it. And if you want to pass a value to the function, you have to put it inside the parenthesis, both when defining the function and when calling it. Like this
function start_battle(someValue) {
// do some stuff with someValue
}
// inside your .click, call start_battle like this
start_battle(passedThisValue);
Pretty basic stuff. But either one of those problems could be causing the hang, which was likely a javascript error.

Confused by this - getting error "this.myfuntion() is not a function"

Background: I am trying to edit a zen cart horizontal pop out menu to make the popout open inline within the menu. The problem I am having is that I am struggling to get my head around the javascript/jquery that came with it.
Without posting the whole thing the structure of the code is something like this:
(declare some vars)
//some functions like this:
function funcname(obj) {
//do something
}
//then one big master function like this:
function bigfunc(arg1, arg2, arg3, arg4, arg5) {
//declare some vars based on this
this.varname1=varname1;
this.varname2=varname2;
//declare some functions inside the big function
this.innerfunc1= function() {
//do stuff
}
this.innerfunc2= function() {
//do stuff
}
}//end of big function
//then goes on to declare init function
function initfunc(){
//this creates new bigfunc(arg1 arg2 arg3...) for each main menu item
}
//finally calls init function with
window.onload = initfunc();
Now on to my confusion -
1) firstly for clarification, am I correct in thinking based on all the this's floating about in bigfunc() and the fact that it is called with new bigfunc() that this is creating an object?
2)My current problem is with one of the functions inside bigfunc() which looks like this:
this.slideChildMenu = function() {
var divref = this.children[0].div;
var ulref = this.children[0].ul;
var maxwidth = this.children[0].width;
var nextWidth;
if (this.isMouseOnMe || this.isMouseOnChild()) {
nextWidth = divref.offsetWidth + slideSpeed_out;
if (nextWidth >= maxwidth) {
this.finishOpeningChild(divref, ulref, maxwidth);
} else {
ulref.style.left = nextWidth - maxwidth + "px";
divref.style.width = nextWidth + "px";
setTimeout("slideChildMenu('" + this.getId() + "')", slideTimeout_out);
}
}
Now my plan is to alter this to use jquery show to open the element so I tried this:
this.slideChildMenu = function() {
var divref = this.children[0].div;
var ulref = this.children[0].ul;
if (this.isMouseOnMe || this.isMouseOnChild()) {
$(divref).show(function(){
this.finishOpeningChild(divref, ulref);
});
}
}
But I am getting this-> TypeError: this.finishOpeningChild is not a function
Now, there is a lot of other stuff going on in this js so I wouldnt dream of asking someone on here to do my work for me, but I am hoping that if someone can explain to me why this function is not a function I may be able to work the rest out.
NOTE: I thought this was to do with the scope of "this" but the value of this appears to be exactly the same in both versions of the code.
I know this is a long one but your help is greatly appreciated.
The value of this in a function is called the "context" in which the function runs. In general, whenever you pass a callback function as an argument (as you do with $(divref).show(function() {...})), the function can run the callback in whatever context it wants. In this case, the jQuery show function chooses to run its callback in the context of the element being animated.
However, you want access to the value of this at the time the anonymous callback function is defined, rather than when it is run. The solution here is to store the outer value of this in a variable (traditionally called self) which is included in the scope of the newly-defined function:
this.slideChildMenu = function() {
//...
var self = this;
$(divref).show(function(){
self.finishOpeningChild(divref, ulref);
});
}
I am thinking that the jQuery selector has changed the scope of this.
In your example $(this); would refer to object being animated per jQuery api docs:
If supplied, the callback is fired once the animation is complete. This can be useful for stringing different animations together in sequence. The callback is not sent any arguments, but this is set to the DOM element being animated. If multiple elements are animated, it is important to note that the callback is executed once per matched element, not once for the animation as a whole.
If the object in question is instantiated you can call it with dot notation without using this like bigFunc.finishOpeningChild(divref, ulref);
You're probably a little confused about scope, it's not always easy keeping track, but doing something more like this:
var site = {
init: function(elm) {
self=site;
self.master.funcname2(self.varname1, elm); //call function in master
},
funcname: function(obj) {
//do something
},
varname1: 'some string',
varname2: 3+4,
master: function() {
this.varname3 = sin(30);
this.funcname2 = function(stuff, element) {
site.funcname(element); //call function in 'site'
var sinus = site.master.varname3; //get variable
}
}
}
window.onload = function() {
var elm = document.getElementById('elementID');
site.init(elm); //call init function
}
usually makes it a little easier to keep track.

Categories

Resources