having trouble with the slideUp method in jquery - javascript

I am using a show hide slider which works for the slide down but doesn't respond for the slide up, can anyone explain where Im going wrong with this:
var moreServicesList = $('#more-services-list').hide();
$('#more-services').on('click', function(e) {
var flag = 0;
if( flag === 0) {
flag = 1;
moreServicesList.slideDown('slow');
$(this).html('Hide');
} else {
moreServicesList.slideUp('slow');
$(this).html('Show');
flag = 0;
}
e.preventDefault();
});
Thanks in advance
Kyle

You have to move var flag = 0; outside of the event listener - http://jsfiddle.net/Nnhz8/
var moreServicesList = $('#more-services-list');
var flag = 0;
$('#more-services').on('click', function(e) {
if( flag == 0) {
moreServicesList.slideDown('slow');
flag = 1;
$(this).html('Hide');
} else {
moreServicesList.slideUp('slow');
$(this).html('Show');
flag = 0;
}
e.preventDefault();
});

You're resetting your flag each time the event handler is called:
$('#more-services').on('click', function(e) {
var flag = 0;
}
To fix this, move the flag declaration in front of the event handler:
var flag = 0;
$('#more-services').on('click', function(e) {}
Here's a working example: http://jsfiddle.net/wMNtT/

Because you define your flag inside the function. It resets to zero every time the function is called.

you can use the toggle method for this like
$('#more-services').on('toggle', function(e) {
$('#more-services-list').slideDown('slow');
$(this).html('Hide');
} function(){
$('#more-services-list').slideUp('slow');
$(this).html('Show');
}
});
var flag every time initializes to 0 in your case

Related

jQuery: Prevent multiple clicks?

I'm trying to prevent mutiple clicks on a link and I need to wait until the function's complete before allowing another click on the same link.
However, everything I do, the multiple clicks is always allowed.
This is my code:
var active = false;
$('#rotRight').live('click', function(){
if (active) {
return;
}
$(this).attr('id', 'rotRight1');
var curAngle = parseInt($(".selected").getRotateAngle()) || 0;
if($(".selected").rotate({
angle: curAngle,
animateTo: curAngle - 90
})){
active = true;
}
$(this).attr('id', 'rotRight');
active = false;
});
I know I'm in the right path. I just need someone to let me know what i'm missing or if I'm doing something wrong please.
Any help would be appreciated.
Thanks
The rotate plugin has a callback where you can reset the active flag value
var active = false;
$('#rotRight').live('click', function() {
if (active) {
return;
}
var curAngle = parseInt($(".selected").getRotateAngle()) || 0;
active = true;
$(".selected").rotate({
angle: curAngle,
animateTo: curAngle - 90,
callback: function() {
active = false;
}
})
});
Try preventing default behaviour first before returning
var active = false;
$('#rotRight').live('click', function(e){
if (active) {
e.preventDefault(); // prevent default behaviour before returning
return;
}
...
});
You could always create an overlay (loading screen), stopping the user doing anything till the process is completed via a full screen div with the following css:
#overlay {
background-color: rgba(0, 0, 0, 0.3);
z-index: 999;
position: absolute;
left: 0;
top: 0;
width: 100%;
height: 100%;
display: none;
}​
This will do the following: https://gyazo.com/aa833914eda1c39d3b8198db2b32dc41
Makes all content un-clickable until after the loading screen has finished.
You can try to use the Data attribute on your link. Like that, you can set the "active" property on the link itself and act in consequence. Jquery handle that system with $().data(string) method. I think it's cleaner than using a global "active" var.
$('#rotRight').live('click', function() {
if ($(this).data("active") != undefined && $(this).data("active") == true) {
return;
}
var curAngle = parseInt($(".selected").getRotateAngle()) || 0;
$(this).data("active") = true;
var self = $(this);
$(".selected").rotate({
angle: curAngle,
animateTo: curAngle - 90,
callback: function() {
self.data("active") = false;
}
})
});
$('#rotRight').live('click', function(e) {
if (e.handled!=true) {
e.preventDefault(); // prevent default behaviour before returning
return;
}
e.handled=true;
});

jQuery Waiting for Multiple Events to fire

Is it possible to "wait" for multiple events before executing a function? I know its possible with jQuery deferred obejcts to use $.when to wait for two promises to resolve but I wondered if its possible with just plain old events?
Lets say a click event and a custom event trigger an alert, for example:
$.when("click", "customEvent").then(function(){ alert("yay"); });
You could use deferred, you just have to create them yourself.
var clickDfd = $.Deferred();
var eventDfd = $.Deferred();
$("div").on("click", function(e) {
clickDfd.resolve();
});
$("div").on("some-event", function(e) {
eventDfd.resolve();
});
$.when(clickDfd, eventDfd).done(function(){
alert("yay");
});
var click = 0;
var hover = 0;
$("div").on("click mouseenter", function(e) {
if(e.type == 'click') {
click = 1;
bana();
}
else if(e.type == 'mouseenter') {
hover = 1;
bana();
}
});
function bana() {
if(click == 1 && hover == 1) {
alert(1);
click = 0;
hover = 0;
}
else {
return false;
}
}
Well, Checking event types and setting them in old way. Plain jQuery and JS.
Will alert 1 only when both events are done / fired.
Fiddle

Do something on key hold and on keyup

I need to call function:
Every second when key is hold (e.g. for five seconds of holding it should fire 5 times every second).
When user releases key (keyup) and if less then one second passed.
Events should be binded on document, not on text input.
If second statement "kinda" works, with first I have problems as keypress event isn't working on some browsers and keydown fires event all the time.
var interval;
$(document).on('keypress', function(e) {
console.log('keypress');
interval = setInterval(function() {
doSomething(e.keyCode);
}, 1000);
}).on('keyup', function(e) {
console.log('keyup');
if(interval === 0) {
doSomething(e.keyCode);
}
clearInterval(interval);
interval = 0;
});
function doSomething(keyCode) {
console.log(keyCode);
}
jsFiddle: http://jsfiddle.net/kWFUA/
Thank you for help!
I've updated the fiddle http://jsfiddle.net/kWFUA/3/
var interval;
var called = false;
$(document).on('keydown', function(e) {
if(interval == null) {
console.log('keydown');
called = false;
interval = setInterval(function() {
doSomething(e.keyCode);
called = true;
}, 1000);
}
}).on('keyup', function(e) {
console.log('keyup');
clearInterval(interval);
interval = null;
if(!called)
doSomething(e.keyCode);
});
function doSomething(keyCode) {
console.log(keyCode);
}

How to write custom event which gets fired when user click three times

i am trying to write a custom event which should get fire when user click three times on any html node.
i know that i can create even using
var evt = document.createEvent("Event");
evt.initEvent("myEvent",true,true);
but i am not getting how i will capture that three times click event.
I will be appreciated if some one can suggest me the write approach for this.
Thanks!!!
You can create a special event
Code and example - here is your problem solvation :)
Just create a variable that stores the number of clicks.
var clickTimes = 0;
element.addEventListener('click', function(event) {
clickTimes++;
if(clickTimes==3) {
clickTimes = 0;
/* do something like dispatch my custom event */
}
});
This will count the clicks for any specific element and trigger Event on every third click.
$('selector').on('click',function(e){
Event_threshold = 500;
var clicked_times = $(this).data('Event-clicked-times');
if(clicked_times == '')
clicked_times = 0;
if(clicked_times == 0)
$(this).data('Event-first-click-timestamp',e.timeStamp);
clicked_times++;
if(e.timeStamp-$(this).data('Event-first-click-timestamp')<Event_threshold)
{
if(clicked_times == 3)
{
$(this).data('Event-clicked-times',0);
$(this).trigger('Event');
}
else
$(this).data('Event-clicked-times',clicked_times);
}
else
$(this).data('Event-clicked-times',0);
});
EDIT:
Fixed and added threshold control.
You can create iteration variable and check if element was three times clicked.
For example:
var clickTimer = 0;
document.body.addEventListener('click', function() {
clickTimer++;
if(clickTimer == 3) {
clickTimer = 0;
// fire your event
}
}, true);
To make this behavior like dbclick you can compare timestamp with first click.
For example:
var clickTimes = 0;
var fisrtClickTime = 0;
element.addEventListener('click', function(event) {
clickTimes++;
if(clickTimes == 1) {
fisrtClickTime = +new Date();
}
if(clickTimes == 3) {
clickTimes = 0;
firstClickTime = 0;
if((+new Date() - fisrtClickTime) < 1000) {
/* do something like dispatch my custom event */
}
}
});
This works without using external variables, using the HTML5 "data-" attribute for storage, so you will work on multiple elements.
$('#yourLink').click(function() {
window.setTimeout(function() {$(this).data("count",1)},300)
if(typeof $(this).data("count")=='undefined') {
$(this).data("count",1)
}
else {
var myCount = parseInt($(this).data("count"))
myCount++
if(myCount==3) {
alert("3!")
$(this).data("count",0)
}
else {
$(this).data("count",myCount)
}
}
})

Cycle Focus to First Form Element from Last Element & Vice Versa

I have created a form with malsup's Form Plugin wherein it submits on change of the inputs. I have set up my jQuery script to index drop down menus and visible inputs, and uses that index to determine whether keydown of tab should move focus to the next element or the first element, and likewise with shift+tab keydown. However, instead of moving focus to the first element from the last element on tab keydown like I would like it to, it moves focus to the second element. How can I change it to cycle focus to the actual first and last elements? Here is a live link to my form: http://www.presspound.org/calculator/ajax/sample.php. Thanks to anyone that tries to help. Here is my script:
$(document).ready(function() {
var options = {
target: '#c_main',
success: setFocus
};
$('#calculator').live('submit', function() {
$(this).ajaxSubmit(options);
return false;
});
$(this).focusin(function(event) {
var shiftDown = false;
$('input, select').each(function (i) {
$(this).data('initial', $(this).val());
});
$('input, select').keyup(function(event) {
if (event.keyCode==16) {
shiftDown = false;
$('#shiftCatch').val(shiftDown);
}
});
$('input, select').keydown(function(event) {
if (event.keyCode==16) {
shiftDown = true;
$('#shiftCatch').val(shiftDown);
}
if (event.keyCode==13) {
$('#captured').val(event.target.id);
} else if (event.keyCode==9 && shiftDown==false) {
return $(event.target).each(function() {
var fields = $(this).parents('form:eq(0),calculator').find('select, input:visible');
var index = fields.index(this);
var nextEl = fields.eq(index+1).attr('id');
var firstEl = fields.eq(0).attr('id');
var focusEl = '#'+firstEl;
if (index>-1 && (index+1)<fields.length) {
$('#captured').val(nextEl);
} else if(index+1>=fields.length) {
if ($(this).val() != $(this).data('initial')) {
$('#captured').val(firstEl);
} else {
event.preventDefault();
$(focusEl).focus();
}
}
return false;
});
} else if (event.keyCode==9 && shiftDown==true) {
return $(event.target).each(function() {
var fields = $(this).parents('form:eq(0),calculator').find('select, input:visible');
var index = fields.index(this);
var prevEl = fields.eq(index-1).attr('id');
var lastEl = fields.eq(fields.length-1).attr('id');
var focusEl = '#'+lastEl;
if (index<fields.length && (index-1)>-1) {
$('#captured').val(prevEl);
} else if (index==0) {
if ($(this).val() != $(this).data('initial')) {
$('#captured').val(lastEl);
} else {
event.preventDefault();
$(focusEl).select();
}
}
return false;
});
}
});
});
});
function setFocus() {
with (document.calculator)
var recap = document.getElementById(recaptured.value);
if (recap!=null) {
setTimeout(function() {
if (recap.getAttribute('type')=='text') {
recap.select();
} else {
recap.focus();
}
}, 100 );
}
}
Edit #1: I made a few minor changes to the code, which has brought me a little closer to my intended functionality of the script. However, I only made one change to the code pertaining to the focus: I tried to to disable the tab keydown when pressed on the last element (and also the shift+tab keydown on the first element) in an attempt to force the focus on the element I want without skipping over it like it has been doing. This is the code I added:
$(this).one('keydown', function (event) {
return !(event.keyCode==9 && shiftDown==true);
});
This kind of works. After the page loads, If the user presses tab on the last element without making a change to its value, the focus will be set to the second element. However, the second time the user presses tab on the last element without making a change to its value, and every subsequent time thereafter, the focus will be set to the first element, just as I would like it to.
Edit #2: I replaced the code in Edit #1, with code utilizing event.preventDefault(), which works better. While if a user does a shift+tab keydown when in the first element, the focus moves to the last element as it should. However, if the user continues to hold down the shift key and presses tab again, focus will be set back to the first element. And if the user continues to hold the shift key down still yet and hits tab, the focus will move back to the last element. The focus will shift back and forth between the first and last element until the user lifts the shift key. This problem does not occur when only pressing tab. Here is the new code snippet:
event.preventDefault();
$(focusEl).focus();
You have a lot of code I didn't get full overview over, so I don't know if I missed some functionality you wanted integrated, but for the tabbing/shift-tabbing through form elements, this should do the work:
var elements = $("#container :input:visible");
var n = elements.length;
elements
.keydown(function(event){
if (event.keyCode == 9) { //if tab
var currentIndex = elements.index(this);
var newIndex = event.shiftKey ? (currentIndex - 1) % n : (currentIndex + 1) % n;
var el = elements.eq(newIndex);
if (el.attr("type") == "text")
elements.eq(newIndex).select();
else
elements.eq(newIndex).focus();
event.preventDefault();
}
});
elements will be the jQuery object containing all the input fields, in my example it's all the input fields inside the div #container
Here's a demo: http://jsfiddle.net/rA3L9/
Here is the solution, which I couldn't have reached it without Simen's help. Thanks again, Simen.
$(document).ready(function() {
var options = {
target: '#c_main',
success: setFocus
};
$('#calculator').live('submit', function() {
$(this).ajaxSubmit(options);
return false;
});
$(this).focusin(function(event) {
$('#calculator :input:visible').each(function (i) {
$(this).data('initial', $(this).val());
});
return $(event.target).each(function() {
$('#c_main :input:visible').live(($.browser.opera ? 'keypress' : 'keydown'), function(event){
var elements = $("#calculator :input:visible");
var n = elements.length;
var currentIndex = elements.index(this);
if (event.keyCode == 13) { //if enter
var focusElement = elements.eq(currentIndex).attr('id');
$('#captured').val(focusElement);
} else if (event.keyCode == 9) { //if tab
var newIndex = event.shiftKey ? (currentIndex - 1) % n : (currentIndex + 1) % n;
var el = elements.eq(newIndex);
var focusElement = el.attr('id');
if ($(this).val() != $(this).data('initial')) {
$('#captured').val(focusElement);
} else if ((currentIndex==0 && event.shiftKey) || (currentIndex==n-1 && !event.shiftKey)) {
event.preventDefault();
if (el.attr('type')=='text') {
$.browser.msie ? "" : $(window).scrollTop(5000);
el.select().delay(800);
} else {
$.browser.msie ? "" : $(window).scrollTop(-5000);
el.focus().delay(800);
}
} else if (el.is('select')) {
event.preventDefault();
if (el.attr('type')=='text') {
el.select();
} else {
el.focus();
}
}
}
});
});
});
});
function setFocus() {
with (document.calculator)
var recap = document.getElementById(recaptured.value);
if (recap!=null) {
setTimeout(function() {
if (recap.getAttribute('type')=='text') {
recap.select();
} else {
recap.focus();
}
}, 1 );
}
}
I put my files available to download in my live link: http://www.presspound.org/calculator/ajax/sample.php

Categories

Resources