Why use next() to add and remove a class multiple times? - javascript

I really want to know why it's important to use function(next) and next() in the following code. Without next() you can only remove the class .open-sidebar one time after you added it by clicking the .header__menu__button--profile.
I thought next() is used to select the following sibling of an element!
Why do I need it to remove the class .open-sidebarevery time I click on .sidebar__top__button--close?
$('.header').on('click','.header__menu__button--profile',function(){
$('.sidebar').addClass('open-sidebar');
});
$('.sidebar').on('click','.sidebar__top__button--close',function() {
if($('.sidebar').hasClass('open-sidebar'))
{
$('.sidebar').delay(300).queue(function(next){
$('.sidebar').removeClass('open-sidebar');
next();
});
}
});

In this case, next is the parameter that was passed by jQuery to the .queue callback, which is a reference to the next function in the animation queue.
It's nothing whatsoever to do with .next(), the function that selects the next sibling elements from a jQuery collection.
It's used within .queue because you have to tell jQuery to process the remaining animation queue once you've done whatever it is you need to do, i.e.:
.queue(function(next) {
// do stuff
...
next();
})
or you can use .dequeue instead:
.queue(function() { // NB: no parameter
// do stuff
...
$(this).dequeue();
})
The latter is actually the older way of doing this - the next parameter was introduced in jQuery 1.4 and if using multiple queues avoids the need to repeat the queue name in both the .queue and .dequeue calls.

Related

Post processing elements after a remove() using a function is not working

I am removing a cloned element using remove()
I have some post removal processing to do on any remaining clones and I need to ensure that the element has left the dom before I do this. I have attempted the following:
$('#something').remove(function() {
... stuff to do after the remove is complete...
})
However the '... stuff to do after the remove is complete...' never fires.
Is this the best way to ensure an element is removed before post processing and if so what am I doing wrong?
According to the doc, the remove function don't take a callback as parameter.
This is a synchronous function, so, you only have to execute your code on a new line.
$('.selector').remove();
console.log( $('.selector').length );
https://api.jquery.com/remove/

Why does function only run once?Trying to run function multiple times,after previous invokation complete, using an counter function

I am currently working on a book with page turn effect in jQuery (no plugin). The page turn effect works fine so far, as long as you click through the pages one by one. But now I want to include a dropdown selection (i.e. a select element) so the user can directly jump to the selected content. I tried to make this work with loops and with the .each() method, so that the turnRightPage/ turnLeftPage function is called repeatedly, until the page with the selected content is shown. But after quite a bit of trial and error and a lot of research, I think loops iterate too fast for my turnRightPage /turnLeftPage()-function (which are the transform functions that turn the respective page), in that the loop is done, before the function has completed. I think, what I need to do, is find a way to pause the loop until the function has finished executing and then resume with the next iteration. I think the most promising approach would be using a function with an iteration counter, like it was suggested here:
Javascript: wait for function in loop to finish executing before next iteration (Thanks to jfriend00 at this point) I have also read
Invoking a jQuery function after .each() has completed and
wait for each jQuery
among others, where similar solutions were suggested.
Below is how I tried to implement jfriend00's callback. I added a return statement to break out of that "callback loop", once the number of page turns is completed.
//determine whether to flip pages forward or back - first forward
if(currentPagePos < foundPagePos){ // => turn right page
//determine how many times need to turn page
if (pageDifference > 1 && pageDifference % 2 !=0) {
var numPageTurns = (pageDifference-1)/2;
pageForward (numPageTurns);
} //else if ... rest omitted for brevity
}
function pageForward (numPageTurns){
var i = 0;
function next(){
i++;
if (i <= numPageTurns){
turnRightPage ();
} else {
return;
}
}
next();
};
The full code can be seen here: http://jsfiddle.net/snshjyxr/1/
It DOES turn the page, but only once! What am I missing?
I am still very new to javascript / jQuery so my apologies, if the problem seems all too obvious. Any pointers appreciated. Thx!
The thing is all the page turns are fired, but all at once. You have to wait until each transition is finished to start the next one.
Use a callback function in your turnRightPage and turnLeftPage functions. Example for turnRightPage :
function turnRightPage(callback) {
[...]
//change class AFTER transition (frm. treehouse-site)
$page.on('webkitTransitionEnd otransitionend oTransitionEnd msTransitionEnd transitionend', function () {
//need to double-set z-index or else secondtime turning page open setting z-index does not work (tried in Chrome 38.0.2125.111 m)
$page.css("z-index", turnedZindex + 1);
$(".turned").removeClass("turned");
$page.addClass("turned");
if(typeof callback == "function") {
callback();
}
});
};
And in your pageForward function, use turnRightPage recursively:
function pageForward(numPageTurns) {
console.log("number of FORWARD page turns: " + numPageTurns);
if(numPageTurns > 0) {
turnRightPage(function(){
pageForward(numPageTurns - 1);
});
}
};
Here is your updated jsfiddle. As you can see, there's a remaining bug when you make several page changes which is caused by the fact that you're adding listeners on the transition end every time a page is turned, and never removing them. So they're all executing every time.
EDIT: jsfiddle updated again without the annoying last bug. As you can see, all it took was to unbind the event listener as soon as it's fired.

jQuery Plugin - Public method - Data only targeting one element

I'm trying to write a plugin that will select multiple elements and then apply some private methods to them (see code below). Then I also want to give the user the ability to trigger the activation of the plugin's methods manually with a .activate() function.
Here is my code :
MARKUP : https://github.com/simonwalsh/jquery.imagepox/blob/master/demo/index.html
JS : https://github.com/simonwalsh/jquery.imagepox/blob/master/dist/jquery.imagepox.js
Basically, when I select multiple items and then try to use the manual activation like so :
$(".pox-wrapper").imagepox({ // NOTE: selects two elements
manualActivation: true
});
var manual = $(".pox-wrapper").data('imagepox');
setTimeout(function(){
manual.activate();
}, 5000);
It will only apply the activate() method to the first element in the query...
This is my first jQuery plugin and I've been able to handle everything so far but I'm not sure about this one or even if it is the right way to effectively call a public method. I also tried using a custom event with an event listener in the plugin but it still only applies the methods on the first element in the page.
Thanks in advance :)
its not your plugin's fault. data does not work like that, it doesnt know how to return data from a collection of elements. Because think about it, each element in the collection contains its own data object!
So when you call data on a collection, it returns the data from the first one. The quick solution would be to change the innards of the setTimeout into a loop over all the elements in the set and call activate on them.
setTimeout(function(){
$(".pox-wrapper").each(function(){
$(this).data('imagepox').activate();
})
}, 5000);
It seems to me that you want to add functions to collections of jquery objects. This is the usecase of a jquery plugin. You can create a lightweight one like this:
$.fn.imagepox.activate = function(){ //do this after you create your plugin!
return this.each(function(){
var $this = $(this);
var data = $this.data('imagepox');
if(data){
data.activate();
}
});
};
now you can call it like this:
$(".pox-wrapper").imagepox.activate()

jQuery toggle class with delay works only once

I am clearly missing something fundamental when it comes to jQuery, anonymous functions, and delays.
The following code works only ONCE per page load (it will add the class, then remove it after 1 second, and if i click again, it will add the class, but will NEVER remove the class for the duration of the page, unless I reload the page):
var jElement = $(currElem);
jElement.addClass("highlight")
.delay(1000)
.queue(function(){
$(this).removeClass("highlight");
});
HOWEVER,
if I add the (non-existant) function call as a parameter, AND I call it in my anonymous function, then the add/remove class combination will work indefinitely.
var jElement = $(currElem);
jElement.addClass("highlight")
.delay(1000)
.queue(function(randomFunction){
$(this).removeClass("highlight");
randomFunction(); //this makes it seemingly 'miraculously' work??
});
Side Note:
var jElement = $(currElem);
jElement.addClass("highlight")
.delay(1000)
.queue(function(randomFunction){
$(this).removeClass("highlight");
// this does NOT work; if I dont actually call the 'randomFunction'
// so that function, even though it does nothing; must somehow cause
// the implicit call of 'dequeue()' ??
});
There is no miracle there. This behavior it's written in the documentation of .queue().
Note that when adding a function with .queue(), we should ensure that .dequeue() is eventually called so that the next function in line executes.
$('#foo').slideUp().queue(function() {
alert('Animation complete.');
$(this).dequeue();
});
As of jQuery 1.4, the function that's called is passed another function as the first argument. When called, this automatically dequeues the next item and keeps the queue moving. We use it as follows:
$("#test").queue(function(next) {
// Do some stuff...
next();
});
the randomFunction is actually referred to as next and references the .dequeue method. Calling it causes the queue to continue on to the next item in the queue.
http://api.jquery.com/queue/

jQuery callback issues, it runs just once

I am having some issues with a piece of code, I use jQuery's ajax to load search results, because its a list I wanted to style the list, zerbra style, so I have included a callback function. The following works the first time but when I search again it doesn't work (styling).
When I put an alert in the callback function it fires every time, but the styling doesn't work.
ajax part
$.post('search.php',{value:val}.function(data){
// output list
}).error(function(){
// error output
}).success(function(){
// callback function.
if(typeof options.afterLoad == 'function'){
options.afterLoad.call(this);
}
});
the plugin options
$('#search').search({
afterLoad: function(){
$('#results').children('li:odd').addClass('odd');
}
});
This isn't the complete plugin, but just the parts that matter.
If the callback is executed then I can think on 3 options:
There is no control with id results
There is no children li for #results
Class odd doesn't exist or it doesn't containst the style rules you suppose it has (maybe a cache issue?)
Put a debugger instruction on the callback and check the length of $('#results') and $('#results').children('li:odd')

Categories

Resources