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.
Related
I am trying to detect, and fire a function if the user has clicked on any of my elements within 'myFormWrapper' (my form) a second time.
var timesClicked = 0;
document.querySelectorAll('myFormWrapper').addEventListener('click', false);
timesClicked++;
if (timesClicked>1) {
function() {
setInterval( jumpRate, 500);
});
function jumpRate(){
var top = document.getElementById("rate").offsetTop;
window.scrollTo(0, top);
}
}
});
You are using querySelectorAll. That function returns a NodeList. To add a listener to all elements in the list, you have to iterate over it. Thus the forEach.
The provided argument was not a correct selector. I changed it, assuming you are using the class myFormWrapper.
You are not providing a callback function correctly. You are passing false instead of a function.
You are also wrapping the timeout in a function. you are not calling.
Also, you want to trigger the scrolling only once. In that case you should use setTimeout instead of setInterval. setTimeout calls the callback only once after the given milliseconds passed, setTimeout will call the callback repeatedly.
The function jumpRate does not have to be a named function, you can pass it anonymously.
Try this:
var timesClicked = 0;
document.querySelector('.myFormWrapper').forEach(function (element) {
element.addEventListener('click', function () {
timesClicked++;
if (timesClicked > 1) {
setTimeout(function () {
var top = document.getElementById("rate").offsetTop;
window.scrollTo(0, top);
}, 500);
}
});
};
});
I am using the .on() function in jQuery to assign functions to events.
var someEvent = getEventName(someParams); // gets the event, like 'click'
var someFunctionReference = getFunctionNameBasedOnParams(someParams); // gets the function reference
$('.myElement').on(someEvent, someFunctionReference);
What I would like to do is wrap 'someFunctionReference' inside a timeout or delay its firing (by some time; lets say 250ms) without having to go and modify every single function that is returned by the method.
Is there a way to do this?
I'll assume you can't modify the code in getFunctionNameBasedOnParams, so all you need to do is create another function that returns a function wrapped in a timer.
function delayFunc(fn, ms) {
return function() {
var args = arguments;
setTimeout(function() {
fn.apply(this, args);
}, isNaN(ms) ? 100 : ms);
}
}
Then pass your function to it.
var someFunctionReference = delayFunc(getFunctionNameBasedOnParams(someParams), 250);
Be aware that your handler's return value is now meaningless, so if you return false, it'll have no effect.
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.
var some_name =
{
moving:false,
show : function ()
{
this.moving = true;
$('element').slideDown(5000, function ()
{
this.moving = false; //How to access to attribute "moving" of class some_name?
});
},
}
Question in code.
You can bind the callback function to the current context:
$('element').slideDown(5000, $.proxy(function() {
this.moving = false;
}), this); // "this" inside of the function will be this "this"
See jQuery.proxy
Alternatively you could do this:
this is the current context, it's value depends on how the function is called. You can assign this to a variable outside of the function, and use this variable instead:
var that = this;
$('element').slideDown(5000, function() {
that.moving = false; //use that instead of this here
});
Use moving instead of this.moving (in both occurences)
Variables are bound to the context when they are used, so even inside your event callback you can access the variables above.
In the event callbacks, this refers to event.target, or the element that captured the event.
You can take the advantage of closures in javascript and access the moving attribute like this:
show : function ()
{
var moving = true;
$('element').slideDown(5000, function ()
{
moving = false;
});
},
Note, though, that this moving will be different of the first moving that lives in some_name
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.