I have a jquery mouseover event which succesfully calls a javascript function
$(document).ready(function() {
$('.nw').mouseover(run_nw);
});
function run_nw() {
...
}
However, when I try to pass parameters, the js fails.
$(document).ready(function() {
$('.nw').mouseover(run_nw(1));
});
var a;
function run_nw(a) {
...
}
Tried looking through SO and through jQ documentation but I'm still stumped. I'm assuming this is a simple formatting issue.
Thanks
(Here is the full code if it helps)
<script>
var $ = jQuery.noConflict();
var incr = 650;
function run_nw() {
//move x and y
var topAdjust = -incr;
var leftAdjust = -incr;
var top = parseInt($(this).css('top'))+topAdjust;
var left = parseInt($(this).parent().css('left'))+leftAdjust;
//rotate
var randomnumber = Math.floor(Math.random()*11);
var rotate = -randomnumber*10;
$(this).animate({
top:top,
left:left,
'rotate':rotate
}, 700, 'swing');
}
$(document).ready(function() {
$('.nw').mouseover(run_nw);
});
</script>
Wrap the function call in an anonymous function:
$('.nw').mouseover(function() {
run_nw(1);
});
The way you have it currently will execute the function and pass the result of that as the callback to mouseover.
Update
The problem with your current code is that in the event handler function, this does not refer to what you're expecting (it refers to the Window, because you are calling the function from an anonymous callback to mouseover - this inside the anonymous callback is what you want it to be).
So, you need to pass this into the function and change any references to this to whatever you choose to name that argument:
$('.nw').mouseover(function() {
run_nw(1, this);
});
function run_nw(a, elem) {
//Now `elem` is what you expected `this` to be
}
Here's an updated fiddle.
Related
Take a look at the anonymous jQuery function from the jfiddle snippet below. There are other libraries as external references to this jfiddle, so I'm just guessing this is jQuery syntax.
http://jsfiddle.net/LEt4Q/12/
Code snippet:
$(function() {
var canvas = new draw2d.Canvas("gfx_holder");
var x = 20,
y = 20;
addArrowToConnection();
injectSetPosition();
var previousRec, newRec;
for (var i = 1; i <= 64; i++) {
newRec = addRec(canvas, i, x, y);
if (i / 8 == Math.floor(i / 8)) {
y = y + 80;
x = 20;
} else {
x = x + 80;
}
if (previousRec != null && newRec != null) {
var conn = new draw2d.Connection();
conn.sourcePort = previousRec.port;
conn.targetPort = newRec.port;
var label = new draw2d.shape.basic.Label({
text: "Label"
});
label.setColor("#0d0d0d");
label.setFontColor("#0d0d0d");
label.setStroke(0);
var arrow = new draw2d.decoration.connection.ArrowDecorator(10, 6);
conn.setTargetDecorator(arrow);
conn.setRouter(new draw2d.layout.connection.DirectRouter());
conn.add(label, new draw2d.layout.locator.ParallelMidpointLocator());
canvas.add(conn);
}
previousRec = newRec;
}
});
All of the other functions within this jfiddle are using one of the JavaScript standard function notations (var functionName = function() {} vs function functionName() {}) except the one above. If you try replacing the syntax with the other three notations, the code doesn't work. What is significant about this notation? Why does only the last syntax work?
var fun = function() { ... } // doesn't work
function fun() { ... } // doesn't work
(function() { ... })(); // doesn't work
$(function() { .. }); // works!!!!!!!!!!!!!!!
Because they are not the same thing. You are confusing the shorthand for the ready event in jQuery, and an IIFE:
$(document).ready(function(){})
Is the same as:
$(function(){})
But it is not the same as:
(function(){}())
The latter is an immediately invoked function expression; it has no relation to the ready event. It is simply a function that executes itself, for the purpose of creating a closure.
This is not a syntactic issue. If you call the global jQuery function ($) and pass it a function, it means exactly the same thing as
$(document).ready(function() { ... });
In other words, the setup you posted makes that function invocation be delayed until the browser has finished assembling the DOM. The function is probably in the <head> of your page (or imported there), so it won't work unless it runs when the DOM is ready because it wouldn't otherwise be able to locate that "gfx_holder" element.
var fun = function() { ... } // doesn't work
This syntax defines variable to refer to function object, does not call the function.
function fun() { ... } // doesn't work
This sytax defines a function, does not call the function
(function() { ... })(); // doesn't work
This syntax defines an anonymous function and calls it immediately, before the DOM is ready
I am quite interested when I run this simple function
$(window).resize(function() {
var that = $(this);
var widthValue = that.width();
console.log(widthValue + 'px');
});
It works when I start resizing my browser window.
But when I do this
$(window).resize(function() {
var that = $(this);
var widthValue = that.width();
console.log(widthValue + 'px');
}).resize();
It acts like load();. I added resize() at the end.
What is this called? Not sure I understand why and how this works.
The technique is called Chaining.
It boils down to a function returning this at the end, so you can call another method of the same object by chaining the method calls one after the other.
var foo = {
count: 0,
up: function () { this.count++; return this; },
show: function () { alert(this.count); return this; }
}
foo.show().up().show().up().up().show();
In this particular example, the resize method is overloaded. If you give it a function argument then it will bind that function as an event handler. If you call it without arguments, then it will trigger that event instead.
With the 2nd case, you are invoking or triggering the resize event.
I am trying to pass "this" from:
myVar = setInterval("displayDate(this )",1000);
and is passing "div.test" like it should when I step through it, but when receiving it in:
function displayDate(obj){
}
It says that it is "Window"??? Below is the JavaScript I am building. I am trying to build a foundation for classes that trigger events and eventually I am going to be changing the elements.src=".jpg" by a variable rate (now set to 100) through Sprite parsing. But I am currently stuck on this and I don't want to have to insert onmousemove attributes, etc. in the .html code to keep it clean. . . keep in mind this is only my third day writing .html/.css/.js so any help is appreciated!
// This helps create a static variable that isn't polluting the global namespace
var incr = (function () {
var i = 0;
return function(){ return i++; };
})();
// This perform all of the functions that we would like with some error handling
function displayDate(obj){
var counter = incr();
try{
obj.innerHTML=counter;
}catch(err){
var txt="There was an error on this page.\n\n";
txt+="Error description: " + err.message + "\n\n";
txt+="Click OK to continue.\n\n";
alert(txt);
}
}
// This is our trigger that sets an interval for our main Java function
$(function(){
var myVar;
$(".test").hover( function() {
// The mouse has entered the element, can reference the element via 'this'
myVar = setInterval("displayDate(this )",100);
},function () {
// The mouse has left the element, can reference the element via 'this'
clearInterval(myVar);
}
);
});
The time the displayDate function is called, your into another scope and this is your window object (not the div element anymore). To resolve, you can do like this:
$(".test").hover( function() {
var self = this;
myVar = setInterval(function() {
displayDate(self);
},1000);
}, function() {
clearInterval(myVar);
});
instead of setInterval("displayDate(this )",100);
$(".test").hover( function() {
var that = $(this);
setInterval(function () {
displayDate(that);
},100);
I have a function that listens for a click on the screen and fires a callback. It is part of a Helper object (which is why is preceded by the term Helper in my sample code. That is irrelevant however.
var Helper = {
bodyClickListener: function(fn) {
var window = document.getElementsByTagName('body')[0];
window.click();
CORE.dom.on(window, 'click', function(event) {
CORE.dom.off(window, 'click');
fn(event);
});
}
}
I need to be able to pass a function into this function with a parameter that has been previously set.
function someFunction() {
var popup = document.getElementById('tagResultsPopup');
Helper.bodyClickListener(function(popup) {
return function(event) {
event.stopPropagation();
removePopup(popup);
};
}(document.getElementById('tagResultsPopup')));
function removePopup(element) {
if(element) {
element.parentNode.removeChild(element);
}
};
}
The code above works, but you'll notice that I have to set the popup variable inside of the callback function. It has already been set above. How do I pass a reference to the earlier variable into the callback function.
If I understand your question correctly, you don't need to do much. You can just use the popup variable defined outside.
var popup = document.getElementById('tagResultsPopup');
Helper.bodyClickListener(function(event) {
event.stopPropagation();
//Don't set it
//var popup = document.getElementById('tagResultsPopup');
removePopup(popup);//popup will refer to the correct variable
});
The function that you are passing to bodyClickListener is a closure. You can simply reference 'popup' inside that function without any problem. You don't have to create a new variable.
The answer was to use closure in this way:
Helper.bodyClickListener(function(popup) {
return function(event) {
event.stopPropagation();
removePopup(popup);
};
}(document.getElementById('tagResultsPopup')));
That way the callback function has access to the variable I pass into the parameter function. So here, the return is actually the function I am passing as the callback.
How can I call a function from inside the function, so it becomes recursive? Here is my code, I have added a comment where I would like to start the recursion:
$('a.previous-photos, a.next-photos').click(function() {
var id = $('#media-photo img').attr('id');
var href = $(this).attr('href');
href = href.split('/');
var p = href[href.length - 1];
var url = '/view/album-photos/id/' + id + '/p/' + p;
$.get(url, function(data) {
$('.box-content2').replaceWith('<div class="box-content2"' + data + '</div>');
});
// here I want to call the function again
return false;
});
You can make a recursive call to an anonymous function by doing
arguments.callee( .... );
See here for more info.
The top answer is out of date. Currently (Aug 2012) callee is deprecated at least in Firefox.Using callee is out of date. Currently (Aug 2012) callee is "... deprecated by ECMA-262."(see discussion)
There are two problems you are running into:
the function handler will only be passed the event object.
the function is not named, so you can't refer to it for recursion
Solution for 2:
This is the easier of the two. Typically the reason for using anonymous functions is to keep a namespace clean. Parentheses define a local namespace, so after giving the function a name it will not be accessible outside the parentheses. The following will work for you:
$('.someclass').onClick( function dosomething(){
... your code ...
dosomething() //again
});
dosomething() // will cause scope error, function not defined
Solution for 1:
This is a little more difficult. Since the only thing passed to the function is the event object you will need to extend that to pass in values. Fortunately, it turns out that jQuery has a system just for this!
$('.someclass').on( 'click', {myvar: 0}, function dosomething(event){
... your code ...
event.data.myvar = event.data.myvar + 1;
dosomething(event) //again
});
Note: this is especially useful for when you must attach and detach a handler to prevent inifinite loops like with DOMSubtreeModified.
$('.someclass').on( 'DOMSubtreeModified.mynamespace', {myvar: 0}, function myfunc( event ){
$(this).off( 'DOMSubtreeModified.mynamespace' );
... Some Code that changes .someclass subtree ...
event.data.myvar = event.data.myvar + 1;
$(this).on( 'DOMSubtreeModified.mynamespace', {myvar: event.data.myvar}, myfunc );
});
Something of this sort should do the trick, but there ought to be a nicer way to set it up:
function myfunc() {
var id = $('#media-photo img').attr('id');
var href = $(this).attr('href');
href = href.split('/');
var p = href[href.length - 1];
var url = '/view/album-photos/id/' + id + '/p/' + p;
$.get(url, function(data) {
$('.box-content2').replaceWith('<div class="box-content2"' + data + '</div>');
});
if(!cond){//you need a condition, or it'll recurse indefinitely.
myfunc();
}
return false;
}
$('a.previous-photos, a.next-photos').click(function(){myfunc();});
From Javascript 1.2 onwards you can use arguments.callee(...) to effect a recursive call to an anonymous function
// here I want to call the function again
arguments.callee();
Put your code in a jQuery plugin format and call itself for example...
(function($) {
$.fn.togglethis = function () {
$(this).animate({opacity:"1.0"}, 1000, function() {
/* Code Here */
return $(this);
});
}
})(jQuery);
$(document).ready(function() {
$("#togglethis").togglethis();
});
Insert your desired code where the comment is.