how to handle click and focus events to toggle ? - javascript

I have requirements, when user clicks, I need to show or hide a section and on focus need to show then on blur need to hide.
I am trying to bind three events,
$(btn).on({click:toggle,focus:show,blur:hide});
var isOpen = false;
function toggle(){
if(!isOpen)show();
else hide();
}
function show(){
isOpen = true;
//my code to show
}
function hide(){
isOpen = false;
//my code to hide
}
but click and focus events conflicting..
how to make it work with the both events focus and click?

You can bind both 'click', 'focus', 'blur' events to button:
var btn = $("#btn");
btn.on('click', function() {
$("#testElement").toggle('slow');
});
btn.on('focus', function() {
$("#testElement").show('slow');
});
btn.on('blur', function() {
$("#testElement").hide('slow');
});
Here is working fiddle

Related

Issue with quiz and jQuery

I have written simple quiz with two cards. After user have clicked on the card, attribute clicked change status and answer is checked.
clicked = false;
$(document).on("click", "#card1", function() {
clicked = true;
check answer........
});
I have got antoher on click event, which should load next question when user click on body element.
This event should only work when the card is clicked and clicked status is true.
$(document).on("click", "body", function() {
if (clicked == true) {
quiz.nextQuestion();
clicked = false;
}
});
But these two onclick events start and execute simultaneously.
How can I prevent this?
stopPropagation(); can be used for this. Otherwise click on elements inside will also trigger the body click functions.
One more thing is that, we have to give click for <html> rather than <body>.
Description: Prevents the event from bubbling up the DOM tree, preventing any parent handlers from being notified of the event.
clicked = false;
$(document).on("click", "#card1", function(e) {
e.stopPropagation();
clicked = true;
console.log('click card');
});
$(document).on("click", "html", function(e) {
if (clicked == true) {
console.log('click body');
clicked = false;
}
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<body>
<div id="card1">
Card1
</div>
</body>
Simple...
clicked = false;
$(document).on("click", "#card1", function() {
clicked = true;
//check answer........
$(this).on("click", "body", function() {
if (clicked == true) {
quiz.nextQuestion();
clicked = false;
}
});
});
Hope this helps.....
You can do it by changing the status of clicked as true after you have checked the answer.
$(document).on("click", "#card1", function() {
check answer........
clicked = true;
});
This will make sure that clicked is not made true as soon as the click event is fired hence making the if statement in the second part of the code false
OR
You can even do it by
clicked = 0;
$(document).on("click", "#card1", function() {
clicked = 1;
check answer........
});
$(document).on("click", "body", function() {
if (clicked == 2) {
quiz.nextQuestion();
clicked = 0;
}else
{
clicked +=1;
}
});

Javascript - How can I differentiate a click and a double click on one element

I am trying to add a click function that triggers when a button is clicked. I am also trying to figure out how to add a double click function onto the same element, that triggers a different event.
var click = false;
onEvent("image2", "click", function(event) {
click = true;
});
if (click === true) {
setTimeout(function() {
onEvent("image2", "click", function(event) {
setScreen("safeScreen");
console.log("double click");
});
}, 200);
} else {
onEvent("image2", "dblclick", function(event) {
setScreen("safeScreen");
console.log("click");
});
}
This code is completely wrong, but I don't know where to start/correct. What am I doing wrong?
You should replace click with dblclick
Also check this link

Prevent bootstrap dropdown from closing on click event [duplicate]

This question already has answers here:
How do I prevent my dropdown from closing when clicking inside it?
(3 answers)
Closed 4 years ago.
My menu uses Bootstrap 3 and I can't prevent dropdown from closing on click. How can I do it?
JSFiddle
// Add open class if active
$('.sidebar-nav').find('li.dropdown.active').addClass('open');
// Open submenu if active
$('.sidebar-nav').find('li.dropdown.open ul').css("display","block");
// Change active menu
$(".sidebar-nav > li").click(function(){
$(".sidebar-nav > li").removeClass("active");
$(this).addClass("active");
});
// Add open animation
$('.dropdown').on('show.bs.dropdown', function(e){
$(this).find('.dropdown-menu').first().stop(true, true).slideDown();
});
// Add close animation
$('.dropdown').on('hide.bs.dropdown', function(e){
$(this).find('.dropdown-menu').first().stop(true, true).slideUp();
});
You need to stop event from bubbling up the DOM tree:
$('.dropdown-menu').click(function(e) {
e.stopPropagation();
});
event.stopPropagation prevents event from reaching the node where it's eventually handled by Bootstrap hiding menu.
Demo: http://jsfiddle.net/wkc5md23/3/
I believe this should be a more proper solution, as stopping propagation on the click event might sometimes cause issues later on in development. You may read more into it here: http://css-tricks.com/dangers-stopping-event-propagation/ Instead this solution stops propagation on the Bootstrap hide (hide.bs.dropdown) event, which stops it from continuing on to the hidden (hidden.bs.dropdown) event.
The following code has been taken and edited by myself to make it work on all Bootstrap dropdowns, as it has originally been taken from here: Preventing bootstrap dropdown from closing on click I personally prefer this way also because it uses the built in Bootstrap dropdown events, which could be found here: https://getbootstrap.com/docs/3.4/javascript/#dropdowns-events.
$(function () {
$('.dropdown').on({
'click': function (event) {
if ($(event.target).closest('.dropdown-toggle').length) {
$(this).data('closable', true);
} else {
$(this).data('closable', false);
}
},
'hide.bs.dropdown': function (event) {
hide = $(this).data('closable');
$(this).data('closable', true);
return hide;
}
});
});
You can disable the dropdown functionality temporarily. This is a workaround.
Example with input field inside the drop-down "menu":
//for dropdown field not closing when clicking on inputfield
$(document).on('focus', 'input', function (e) {
// this attribute can be anything except "dropdown", you can leave it blank
$('#yourDropdownID').attr('data-toggle', 'off');
});
//for dropdown field back to normal when not on inputfield
$(document).on('focusout', 'input', function (e) {
$('#yourDropdownID').attr('data-toggle', 'dropdown');
});
This can be used on anything that is clickable and you can define individually what items clicked can close or not close the drop-down menu.
Not close in click out side menu
$(function() {
var closeble = false;
$('body').on('click', function (e) {
if (!$(event.target).is('a.dropdown-toggle')) {
closeble = false;
}
});
$('.dropdown').on({
'click': function (event) {
if ($(event.target).closest('.dropdown-toggle').length) {
closeble = true;
} else {
closeble = false;
}
},
'hide.bs.dropdown': function () {
return closeble;
}
});
});

Prevent click event after drag in jQuery

I have a draggable <div> with a click event and without any event for drag,
but after I drag <div> the click event is apply to <div>.
How can prevent of click event after drag?
$(function(){
$('div').bind('click', function(){
$(this).toggleClass('orange');
});
$('div').draggable();
});
http://jsfiddle.net/prince4prodigy/aG72R/
FIRST attach the draggable event, THEN the click event:
$(function(){
$('div').draggable();
$('div').click(function(){
$(this).toggleClass('orange');
});
});
Try it here:
http://jsfiddle.net/aG72R/55/
With an ES6 class (No jQuery)
To achieve this in javascript without the help of jQuery you can add and remove an event handler.
First create functions that will be added and removed form event listeners
flagged () {
this.isScrolled = true;
}
and this to stop all events on an event
preventClick (event) {
event.preventDefault();
event.stopImmediatePropagation();
}
Then add the flag when the mousedown and mousemove events are triggered one after the other.
element.addEventListener('mousedown', () => {
element.addEventListener('mousemove', flagged);
});
Remember to remove this on a mouse up so we don't get a huge stack of events repeated on this element.
element.addEventListener('mouseup', () => {
element.removeEventListener('mousemove', flagged);
});
Finally inside the mouseup event on our element we can use the flag logic to add and remove the click.
element.addEventListener('mouseup', (e) => {
if (this.isScrolled) {
e.target.addEventListener('click', preventClick);
} else {
e.target.removeEventListener('click', preventClick);
}
this.isScrolled = false;
element.removeEventListener('mousemove', flagged);
});
In the above example above I am targeting the real target that is clicked, so if this were a slider I would be targeting the image and not the main gallery element. to target the main element just change the add/remove event listeners like this.
element.addEventListener('mouseup', (e) => {
if (this.isScrolled) {
element.addEventListener('click', preventClick);
} else {
element.removeEventListener('click', preventClick);
}
this.isScrolled = false;
element.removeEventListener('mousemove', flagged);
});
Conclusion
By setting anonymous functions to const we don't have to bind them. Also this way they kind of have a "handle" allowing s to remove the specific function from the event instead of the entire set of functions on the event.
I made a solution with data and setTimeout. Maybe better than helper classes.
<div id="dragbox"></div>
and
$(function(){
$('#dragbox').bind('click', function(){
if($(this).data('dragging')) return;
$(this).toggleClass('orange');
});
$('#dragbox').draggable({
start: function(event, ui){
$(this).data('dragging', true);
},
stop: function(event, ui){
setTimeout(function(){
$(event.target).data('dragging', false);
}, 1);
}
});
});
Check the fiddle.
This should work:
$(function(){
$('div').draggable({
start: function(event, ui) {
$(this).addClass('noclick');
}
});
$('div').click(function(event) {
if ($(this).hasClass('noclick')) {
$(this).removeClass('noclick');
}
else {
$(this).toggleClass('orange');
}
});
});
DEMO
You can do it without jQuery UI draggable. Just using common 'click' and 'dragstart' events:
$('div').on('dragstart', function (e) {
e.preventDefault();
$(this).data('dragging', true);
}).on('click', function (e) {
if ($(this).data('dragging')) {
e.preventDefault();
$(this).data('dragging', false);
}
});
You can just check for jQuery UI's ui-draggable-dragging class on the draggable. If it's there, don't continue the click event, else, do. jQuery UI handles the setting and removal of this class, so you don't have to. :)
Code:
$(function(){
$('div').bind('click', function(){
if( $(this).hasClass('ui-draggable-dragging') ) { return false; }
$(this).toggleClass('orange');
});
$('div').draggable();
});
With React
This code is for React users, checked the draggedRef when mouse up.
I didn`t use click event. The click event checked by the mouse up event.
const draggedRef = useRef(false);
...
<button
type="button"
onMouseDown={() => (draggedRef.current = false)}
onMouseMove={() => (draggedRef.current = true)}
onMouseUp={() => {
if (draggedRef.current) return;
setLayerOpened(!layerOpened);
}}
>
BTN
</button>
I had the same problem (tho with p5.js) and I solved it by having a global lastDraggedAt variable, which was updated when the drag event ran. In the click event, I just checked if the last drag was less than 0.1 seconds ago.
function mouseDragged() {
// other code
lastDraggedAt = Date.now();
}
function mouseClicked() {
if (Date.now() - lastDraggedAt < 100)
return; // its just firing due to a drag so ignore
// other code
}

How to combine Hover, Out, Click event together

var bar = $('.div_layer_Class');
$('a.second_line').click(function() {
$(this).unbind('mouseout');
}).mouseover(function() {
bar.css('display','inline');
}).mouseout(function() {
bar.css('display','none');
});
now the issue with 'onBodyclick' when i click anywhere on body again i want to invoke mouseoutevent something like this
$('body').click(function() {
bar.css('display','none');
event.preventDefault();
});
when I do this it overlaps $('a.second_line').click(function() event. any idea how I can Achieve this.
http://jsfiddle.net/qGJH4/56/
In addition to e.stopPropagation(),
you can do 2 things:
make a variable to reference the mouseout event handler so you can re-bind it whenever the user clicks elsewhere to the body.
or
A variable to store to whether a.second_line is focused or not. Something like
var focused = false;
You code now will be:
var bar = $('.div_layer_Class');
var focused = false;
$('a.second_line').click(function(e) {
focused = true;
e.stopPropagation();
}).mouseover(function() {
bar.css('display','inline');
}).mouseout(function() {
if (!focused)
bar.css('display','none');
});
$(document).click(function(e){
bar.css('display','none');
focused = false;
});
Example here
Try changing your code to this
var bar = $('.div_layer_Class');
$('a.second_line').click(function(e) {
bar.addClass('on');
e.stopPropagation();
}).mouseover(function() {
bar.css('display','inline');
}).mouseout(function() {
if(!bar.hasClass('on'))
bar.css('display','none');
});
$(document).on('click',function(){
bar.removeClass('on');
bar.css('display','none');
//return false;
});
Two lines to look at, first, the e in function(e)
$('a.second_line').click(function(e) {
and the stop e.stopPropagation();
That basically stops any parent handlers being notified. Read here

Categories