jquery delay function with IF statement - javascript

Can anyone tell me why my IF statement is firing before updating the UI with the each loop?
The code basically wants to delay adding css classes to the UI then once each one has been added, redirect the user. It currently just directs immediately?!
$("#logo").click(function() {
//define variables:
var eventDuration = 500;
var elementArray = ['ribbon', 'left-panel', 'wid-id-1', 'wid-id-2'];
var animationArray = ['slideOutRight', 'slideOutLeft', 'rotateOutUpRight', 'rotateOutUpRight'];
//Loop through elements and update UI with timer function:
$.each(elementArray, function(index, value) {
//Increments the delay of the element updates:
var delaytimer = index * eventDuration + eventDuration;
//Adds animation css classes to onpage elements:
$('#' + value).delay(delaytimer).queue(function() {
$(this).addClass('animated ' + animationArray[index]).dequeue();
});
//Once complete redirect to the home page:
if (index === 3) {
$(this).delay(delaytimer + 500).queue(function() {
window.location.replace('/').dequeue;
});
}
});
});

Your if statement is being executed immediately because it isn't inside the delay function. Try moving it in there.
$('#' + value).delay(delaytimer).queue(function() {
$(this).addClass('animated ' + animationArray[index]).dequeue();
//Once complete redirect to the home page:
if (index === 3) {
$(this).delay(delaytimer + 500).queue(function() {
window.location.replace('/').dequeue;
});
}
});

Related

how javascript excutes callback with parameters

i am in trouble with javascript‘s callback,my code seems simple:
var i =0;
for (; i < listSize+1; i++) {
var content = "content"+i;
$("#" + content).focus(function () {
$("#" + content).keydown(check(new Number(i)));
$("#" + content).keyup(check(new Number(i)));
});
}
where lisetSize=3 in my test case and content is the html element's id
and the callback function check(my_num) is:
function check(my_num) {
var content = "content"+my_num;
}
then i try to trigger this function through keyboard input.
however,i got the result that content=content4 all the time via my broswer's debugger,even though the listening element is content0
i have try anyway such as $.extend({},i) $.extend(true,{},i)
it make no difference
now i have no idea about this problem,how can i just pass a value but no reference to the callback function's parameter?
You're not declaring the handlers correctly.
Replace:
$("#" + content).keydown(check(new Number(i)));
$("#" + content).keyup(check(new Number(i)));
With:
$("#" + content).keydown(function(){check(new Number(i));});
$("#" + content).keyup(function(){check(new Number(i));});
What you need to pass to keyup and keydown, are functions that need to be called when keyboard events happen.
What you were passing to keyup and keydown, were the results of calling check(new Number(i)).
Also, since you're declaring these in a loop, you'll want to copy the number to a new variable, in order to reference the current loop iteration's value:
$("#" + content).focus(function () {
var currentNumber = i;
$("#" + content).keydown(function(){check(currentNumber);});
$("#" + content).keyup(function(){check(currentNumber);});
});
Thanks for Cerbrus,even though there is still problem.
Now I realize that the problem was caused by misunderstanding the real running order.
Even after the loop ends up, $("#" + content).focus will still be called once user click the element.And then,the program starts the code
function () {
$("#" + content).keydown(function(){check(currentNum);});
$("#" + content).keyup(function(){check(currentNum);});
}
As the loop has ended,currentNum=4,so everything got an error.
Here is my solution:
for (var i = 0; i < listSize + 1; i++) {
var content = "content" + i;
$("#" + content).focus(function () {
$(this).keydown(function () {
check($(this));
});
$(this).keyup(function () {
check($(this));
});
});
}
function check(trigger) {
var my_num = getContentNum(trigger);
}
function getContentNum(content) {
return (content.attr("id").charCodeAt(7))-48;
}
Not elegant but useful.

Jquery dropdown change value not working

I have a dropdown list i want to change the view on jquery change events
Html code is
<select id="pu_viewToLoad" class="select-dark" name="viewToLoad"></select>
Js code
$("#pu_viewToLoad").change(function(evt) {
evt.preventDefault();
var index = parseInt($("#pu_viewToLoad option:selected").val(), 10);
if (index >= 1000) {
index -= 1000;
console.log("Changing to 2D view: " + _views2D[index].name);
switchSheet();
loadView(_viewerSecondary, _views2D[index]);
}
else {
console.log("Changing to 3D view: " + _views3D[index].name);
switchSheet();
loadView(_viewerSecondary, _views3D[index]);
}
});
This function is not executing
You should either use:
var index = parseInt($("#pu_viewToLoad option:selected").attr("value"), 10);
Or
var index = parseInt($(this).val(), 10);
Please change accordingly. And make sure you are running the above function inside the $(document).ready() function.

jQuery stops listening for clicks after rendering elements

I am building a smartphone app using localStorage. Everything works well until I make an action. Here's the JS:
var ls = localStorage,
$input = $('#add-movie'),
$content = $('.content'),
$tools = $('.tools');
var movy = {
// returns the next id
// prev id is stored in ls
nextId: function() {
var i = ls.getItem('index') || 0;
i++;
ls.setItem('index', i);
return i;
},
getRelease: function(name, cb) {
cb('12/4'); // only temporary
},
// adds a new movie to the localStorage
new: function(name) {
var data = {
name: name
};
movy.getRelease(name, function(results) {
data.release = results;
});
ls.setItem(movy.nextId(), JSON.stringify(data));
},
// show all films
renderAll: function() {
$tools.hide();
var html = '';
for (var i = 1; i < ls.length; i++) {
var item = JSON.parse(ls.getItem(i));
if (!item) { }
else
html += '<tr data-index="' + i + '"><td class="name">' + item.name + '</td><td class="date">' + item.release + '</td></tr>';
}
$content.html(html);
},
remove: function(key) {
ls.removeItem(key);
for (var i = key + 1; i <= ls.length; i++) {
var item = ls.getItem(i);
ls.setItem(i - 1, item);
}
// decriment i
var index = ls.getItem('index');
index--;
ls.setItem('index', index);
}
}
$(function() {
movy.renderAll();
$('form').submit(function(e) {
e.preventDefault();
movy.new($input.val());
console.log($input.val());
movy.renderAll();
console.log('rendered');
});
$('.content tr').click(function() {
$(this).toggleClass('checked');
$tools.toggle();
$tools.find('#trash').attr('data-index', $(this).attr('data-index'));
});
$('#trash').click(function() {
var i = $(this).attr('data-index');
console.log(i);
movy.remove(i);
movy.renderAll();
// now nothing works until page is refreshed
});
});
Now, at the very first time when I refresh the page, it responds to clicks, shows the toolbar when needed and everything is great. However, after I click on trash, and it successfully deletes that item and re-renders all the elements, suddenly jQuery stops listening for clicks, and the whole thing becomes not responsive. That is, until I refresh the page.
Thanks!
Making my comment that solved the problem into an answer:
If you are rebuilding all the DOM elements (e.g. making new DOM elements), then your event handlers were bound to the old DOM elements and there are no event handlers on the new DOM elements.
You have to either use delegated event handling (attaching event handlers to static parent objects) or assign new event handlers to the newly create DOM elements. See this answer for how to do delegated event handling.

How do I combine two JQuery functions?

I am trying to combine these two functions into one. I know there has to be a really simple way to do it, but everything I have tried so far has not worked. Essentially there are two icons and two menus. When you click one icon a menu either drops down (or raises) depending on the state they are in. Everything after the variables is the same, so it seems to make sense to consolidate them into one shared function. Any help would be greatly appreciated. Thanks!
$(function(){
///Manage Icon 1
$('.ecGlobalNavStudentIcon').click(function(e){
var n = 'hideme'
var m = $('#ecGlobalNavStudentPanel')
var p = $('#ecGlobalNavStaffPanel')
e.preventDefault(); //just prevent the default behavior of the hyperlink
if(m.hasClass(n)) {
console.log($(m).attr('id') + " Has 'hideme' gonna open up");
$(m).show().removeClass(n);
$(m).animate({
height:'49px'
},
500, // Duration
function() { // Callback when the animation is finished
console.log($(m).attr('id') + " Opened!");
});
} else {
console.log($(m).attr('id') + " didn't have 'hideme' gonna try and
close. ");
$(m).animate({
height:'0px'
},
500, // Duration
function() { // Callback when the animation is finished
$(m).hide().addClass(n);
console.log($(m).attr('id') + " Closed!");
});
}
if(!$(p).hasClass(n)) {//open
console.log($(p).attr('id') + " panel open! Gonna close.");
$(p).animate({//close
height:'0px'
},//close
500, // Duration
function() { // Callback when the animation is finished /open
console.log($(p).attr('id') + " Closed by animation!");
$(p).hide().addClass(n);
});//close
}
});
///Manage Icon 2
$('.ecGlobalNavStaffIcon').click(function(e){
var n = 'hideme'
var m = $('#ecGlobalNavStaffPanel')
var p = $('#ecGlobalNavStudentPanel')
e.preventDefault(); //just prevent the default behavior of the hyperlink
if (m.hasClass(n)) {
console.log($(m).attr('id') + " Has 'hideme' gonna open up");
$(m).show().removeClass(n);
$(m).animate({
height: '49px'
},
500, // Duration
function () { // Callback when the animation is finished
console.log($(m).attr('id') + " Opened!");
});
} else {
console.log($(m).attr('id') + " didn't have 'hideme' gonna try and close. ");
$(m).animate({
height: '0px'
},
500, // Duration
function () { // Callback when the animation is finished
$(m).hide().addClass(n);
console.log($(m).attr('id') + " Closed!");
});
}
if (!$(p).hasClass(n)) {//open
console.log($(p).attr('id') + " panel open! Gonna close.");
$(p).animate({//close
height: '0px'
},//close
500, // Duration
function () { // Callback when the animation is finished /open
console.log($(p).attr('id') + " Closed by animation!");
$(p).hide().addClass(n);
});//close
}
});
});
If you want to handle same event for multiple selectors, use the selectors as comma separated.. In your case
$('.ecGlobalNavStudentIcon, .ecGlobalNavStaffIcon').click(function(){
//Your common event handler
});
Always remember, repeating code is evil, a sign of some mistake you've made. And you have done a great job finding it :) Happy coding
It is always good to separate DOM event handling and actual logic.
icon1 click and icon2 click triggers event A
on event A do action A'
consider this example:
$(body).on('togglePanels.my', function (e, activePanel ) {
var panels = $('.panels')
panels.removeClass(cssClass)
activePanel.addClass(cssClass)
})
$(body).on('click','.panelHeader' function(e) {
var $this= $(this)
, panel = $('#' + $this.data('target'))
$(body).trigger('togglePanels.my', [panel])
})
This is pretty much all code you need for accordion you are building, with exception of animation effects
Notice that it requires you to slightly change markup:
common .panel class added for panels
another one .panelHeader for icons
icon has data-target attribute with ID of panel to open.
instead of hide-me class to hide panel, cssClass should hold name of css class to open active one
example markup:
<div>
<i class="panelHeader ecGlobalNavStudentIcon"
data-target="ecGlobalNavStudentPanel">Student</i>
<i class="panelHeader ecGlobalNavStuffIcon"
data-target="ecGlobalNavStaffPanel">Stuff</i>
</div>
<div id='ecGlobalNavStudentPanel'
class="panel ecGlobalNavStudentPanel">...</div>
<div id='ecGlobalNavStaffPanel'
class="panel ecGlobalNavStaffPanel">...</div>
Something like this would work:
$('.ecGlobalNavStudentIcon, .ecGlobalNavStaffIcon').click(function(e){
var n = 'hideme'
var m = $(e.target).hasClass('ecGlobalNavStudentIcon') ? $('#ecGlobalNavStudentPanel') : $('#ecGlobalNavStaffPanel');
var p = $(e.target).hasClass('ecGlobalNavStudentIcon') ? $('#ecGlobalNavStaffPanel') : $('#ecGlobalNavStudentPanel');
$('.ecGlobalNavStaffIcon, ecGlobalNavStaffIcon').click(function(e){
var n = 'hideme';
if this.hasClass('ecGlobalNavStaffIcon'){
var m = $('#ecGlobalNavStudentPanel')
var p = $('#ecGlobalNavStaffPanel')
}
else {
var m = $('#ecGlobalNavStaffPanel')
var p = $('#ecGlobalNavStudentPanel')
}
...
}
if you need, just apply a param and then use the same code (example: $('#'+myParamToSelect).function()

How to cancel jquery execution upon action

I have a table displaying rows of records.
The goal is for the user to hover their mouse over any given row for 1 second, display a popup with a loading animation, and load the popup with various info about that record. If they mouse over another records, it will remove the original popup and start the process anew.
The problem I'm having is controlling when to stop the execution of these record detail calls. If I hover my mouse over various records before the previous one fully loads, when I finally do stop moving my mouse the popup cycles through all the records previously requested.
I ideally I need the execution to stop when the mouse leaves the record row. Also, execution should stop and the popup should hide upon clicking the record row, as clicking the row performs other actions.
My code so far:
var timeout;
$("#tblQueueItems tr").mouseenter(function (cRow) {
var cRowCopy = $(this);
cRowCopy.addClass('hover');
hideBox();
clearTimeout(timeout);
timeout = setTimeout(function () {
hideBox();
var orderId = cRowCopy.attr('oid');
showBox("<div id='divLoading'><img src='/images/AjaxLoader.gif' /></div>", RowCopy, cRow);
$.get('/api/WorkQueue/GetWQIOrderModal', { orderId: orderId }, function (data) {
showBox(data, cRowCopy, cRow);
});
}, 1000);
cRowCopy.mouseleave(function () {
clearTimeout(timeout);
cRowCopy.removeClass('hover');
});
cRowCopy.click(function () {
clearTimeout(timeout);
hideBox();
cRowCopy.removeClass('hover');
});
});
$("#divOrderPopup").mouseenter(function () {
var orderId = $("[id^=hf_]").attr('id').split("_").pop();
$("#tr_" + orderId).addClass('hover');
});
$("#divOrderPopupMoving").mouseleave(function () {
var orderId = $("[id^=hf_]").attr('id').split("_").pop();
$("#tr_" + wqiId).removeClass('hover');
hideBox();
});
}
function showBox(text, obj, e) {
var left = (e.pageX + 25) + 'px';
var top = (e.pageY - 200) + 'px';
var node = "<div style=\"z-index: 25;background: #ffffff;width: 715px;padding: 10px;border: 2px solid black;\" id=\"popBox\">";
node += text;
node += "</div>";
$("#divOrderPopup").css('position', 'absolute');
$("#divOrderPopup").css('top', top);
$("#divOrderPopup").css('left', left);
$("#divOrderPopup").html(node);
}
function hideBox() {
window.node = document.getElementById('popBox');
$("#divOrderPopupMoving").html('');
window.on = false;
}
You need to save your AJAX request to a variable, for example to a global one:
req = $.get('/api/WorkQueue/GetWQIOrderModal', { orderId: orderId }, function (data) {
showBox(data, cRowCopy, cRow);
});
and on mouseleave you can call req.abort() :
$("#divOrderPopupMoving").mouseleave(function () {
req.abort();
var orderId = $("[id^=hf_]").attr('id').split("_").pop();
$("#tr_" + wqiId).removeClass('hover');
hideBox();
});
I think this was your question/problem so far because you didn't told us where you stuck.

Categories