I want to create a responsive menu for my website, however, I have a problem : I have two devices (desktop & mpbile phone) with the same HTML but two different JS. I share my problem in few line of code.
eventDesktop = function() {
$('header').click(function() {
console.log('Desktop');
});
};
eventPhone = function() {
$('header').click(function() {
console.log('Phone');
});
};
eventWitch = function() {
if (window.innerWidth > 480) {
eventDesktop();
} else {
eventPhone();
}
};
eventWitch();
$(window).resize(function() {
eventWitch();
});
So, after loading that's ok because only one is load, but after resize there are 2 fonctions for the same element, and I want to have only witch one i need. So here, i want to see on the console only 'Desktop' or 'Phone' but not the 2 both, when i click.
Thanks for reading.
If you have question i can specify my ask.
Greet.
You are binding two events on same element on the resize of window. You could try this
$('header').click(function() {
if(window.innerWidth > 480)
console.log('Desktop');
else
console.log('Phone');
});
So, check everytime when user click on header.
It seems like you creating 2 different Event-Handlers, so he is using both in your case.
Try to .unbind() them:
$(window).resize(function() {
$( 'header' ).unbind( 'click' );
eventWitch();
});
So all Click events will be removed, keep that in mind.
There is another method I didn't tried, but maybe it helps: jQuery multiple click event
As andrea.spot wrote: "You need to make your handler function return false.. it prevents the event from bubbling."
Adding this to your code:
eventDesktop = function() {
$('header').click(function() {
console.log('Desktop');
return false;
});
};
eventPhone = function() {
$('header').click(function() {
console.log('Phone');
return false;
});
};
The last solution would be changing the way of thinking. This means do the Click-Handler and THAN check for the Windows Size. Currently you checking for the Window Size and than calling a Click-Handler, this will always lead to multible Click Handlers, but not if you create one handler and than do the statements.
My text to code:
eventWitch = function() {
$( 'header' ).click( function(){
if (window.innerWidth > 480) {
console.log( 'Desktop' );
} else {
console.log( 'Mobile' );
}
}
};
Does one of this solutions works for you?
try this
eventDesktop = function() {
$('header').unbind('click').click(function() {// here it will removes all old click events assigned to this element.
console.log('Desktop');
});
};
eventPhone = function() {
$('header').unbind('click').click(function() {// here it will removes all old click events assigned to this element.
console.log('Phone');
});
};
eventWitch = function() {
if (window.innerWidth > 480) {
eventDesktop();
} else {
eventPhone();
}
};
eventWitch();
$(window).resize(function() {
eventWitch();
});
Related
I have some code for a mega navigation and I need it to hover to drop the menu on desktop and click to the drop the menu on mobile.
Here is a snippet of code that I'm having problems with:
if( $('js-full-menu').hasClass('js-touch-menu') ) {
(function(megaNavTray){
menu.on('click', function(e){
e.preventDefault();
var wasOpen = megaNavTray.hasClass('is-active');
megaNavTrays.find('.js-mega-nav-tray').removeClass('is-active');
if(!wasOpen) {
megaNavTray.addClass('is-active');
megaNavTrays.addClass('is-active');
} else {
megaNavTrays.removeClass('is-active');
}
});
})(megaNavTray);
} else {
(function(megaNavTray){
menu.hoverIntent( function(){
megaNavTray.addClass('is-active');
megaNavTrays.addClass('is-active');
var wasOpen = megaNavTray.hasClass('is-active');
megaNavTrays.find('.js-mega-nav-tray').removeClass('is-active');
if(wasOpen) {
megaNavTray.addClass('is-active');
megaNavTrays.addClass('is-active');
} else {
megaNavTray.removeClass('is-active');
}
});
})(megaNavTray);
var fullNav = $('.js-full-menu');
fullNav.hoverIntent( function() {}, function() {
$('.js-mega-nav-tray').removeClass('is-active');
megaNavTrays.removeClass('is-active');
});
}
Basically the problem is that with the if else statement removed leaving only the following code, the preventdefault works fine. Using the full code above the links direct to their pages instead of dropping the meganav on click.
(function(megaNavTray){
menu.on('click', function(e){
e.preventDefault();
var wasOpen = megaNavTray.hasClass('is-active');
megaNavTrays.find('.js-mega-nav-tray').removeClass('is-active');
if(!wasOpen) {
megaNavTray.addClass('is-active');
megaNavTrays.addClass('is-active');
} else {
megaNavTrays.removeClass('is-active');
}
});
})(megaNavTray);
Any ideas why the if / else would be stopping the preventdefault from working?
Thanks in advance!
if( $('js-full-menu').hasClass('js-touch-menu') )
should be
if( $('.js-full-menu').hasClass('js-touch-menu') )
you forgot the . in the class selector.
I may be wrong, but try putting
function(event)
instead of
function(e)
Solved an issue for me in FF the other day.
I'm trying to prevent a click event from firing if the mouse is moved after the 'mousedown' event. Currently I'm doing everything manually via conditionals and booleans. I still don't have it working how I want, and I feel it's just a poor approach to accomplishing this.
var mousemove = false;
var mousedown = false;
var cancelClick = false;
$('.example').click( function() {
if (!cancelClick) {
if ( $(this).attr('id') === 'example-green') {
$(this).attr('id', 'example-blue');
} else {
$(this).attr('id', 'example-green');
}
}
cancelClick = false;
});
$('.example').mousedown( function() {
mousedown = true;
});
$('.example').mouseup( function() {
if (mousemove) {
cancelClick = true;
}
mousedown = false;
mousemove = false;
});
$('.example').mousemove( function() {
if (mousedown) {
mousemove = true;
}
});
http://jsfiddle.net/aGf6G/4/
Is there is a simpler way to achieve this? Preferably one that prevents the click events from being processed, or removes them from the pending event queue (I'm not sure if they are queued until after you release the mouse). That way the callbacks themselves aren't coupled with the implementation of this.
I would just store the x/y coordinates of the mouse on mousedown and compare it to the current coordinates in click.
$('.example')
.on('mousedown', function() {
$(this).data("initcoords", { x: event.clientX, y: event.clientY });
})
.on('click', function() {
var initCoords = $(this).data("initcoords") || { x: 0, y: 0 };
if (event.clientX === initCoords.x && event.clientY === initCoords.y) {
if ( $(this).attr('id') === 'example-green') {
$(this).attr('id', 'example-blue');
} else {
$(this).attr('id', 'example-green');
}
$(this).data('initcoords', {x:-1, y:-1});
}
});
http://jsfiddle.net/zp2y2/8/
You could also toggle the click event on and off. It is a little more concise but I wonder about the overhead of setting up event handlers compared to the method above.
$('.example')
.on('mousedown', function() { $(this).one("click", handleClick); })
.on('mousemove mouseout', function() { $(this).off('click'); });
function handleClick(){
var $el = $('.example');
if ( $el.attr('id') === 'example-green') {
$el.attr('id', 'example-blue');
} else {
$el.attr('id', 'example-green');
}
}
http://jsfiddle.net/du7ZX/
EDIT: http://api.jquery.com/event.stopimmediatepropagation/ Here is one that stops all events on one element from executing except the one you want.
If the differnt events are not all on the same element but rather spread among child/parent you could:
Event.stopPropagation() will stop all other events except the one you actually want.
I believe this here is your solution: http://api.jquery.com/event.stoppropagation/
Here is a jsfiddle to actually test with and without stopPropagation:
In this example I show how a div within a div inherits the event from his parent. Notice in the second example if you mouse over the inner div first, you will get two alerts. If you mouseover the inner div in the first example you will only get one alert.
http://jsfiddle.net/Grimbode/vsKM9/3/
/** test with stopprogation **/
$('#test').on('mouseover', function(event){
event.stopPropagation();
alert('mouseover 1');
});
$('#test2').on('mouseover', function(event){
event.stopPropagation();
alert('mouseover 2');
});
/*** test with no stoppropagation ***/
$('#test3').on('mouseover', function(event){
alert('mouseover 3');
});
$('#test4').on('mouseover', function(event){
alert('mouseover 4');
});
You could also use .off() method that removes events on a specific element.
Here's another option, I tested it and it works well:
$('.example')
.on('mousedown', function() {
$(this).data("couldBeClick", true );
})
.on('mousemove', function() {
$(this).data("couldBeClick", false );
})
.on('click', function() {
if($(this).data("couldBeClick")) {
alert('this is really a click !');
}
});
I have this script that makes a div become a link when resizing window. Problem is that when I zoom back out the div is still redirecting.
The code:
$(window).resize(function() {
if ($(this).width() <= 1400) {
$("#settings").click(function() {
window.location = "settings.php";
});
} else {
$("#settings").click(function() {
$("#settingsDropdown").toggle();
});
}
}).triggerHandler('resize');
I tried adding window.location = "#"; but it didn't work.
Both events are registered, you need to remove the first event handler for the click check the off event
you could do:
$(window).resize(function() {
if ($(this).width() <= 1400) {
$("#settings").off( 'click' ); // <------ Add this line
$("#settings").click(function() {
window.location = "settings.php";
});
} else {
$("#settings").off( 'click' ); // <------ Add this line
$("#settings").click(function() {
$("#settingsDropdown").toggle();
});
}
}).triggerHandler('resize');
You have to unbind event handlers which you don't want anymore
See unbind
use bind and unbind
$(window).resize(function() {
$("#settings").unbind('click.redirectOrToggle');
if ($(this).width() <= 1400) {
$("#settings").bind('click.redirectOrToggle', function() {
window.location = "settings.php";
});
} else {
$("#settings").bind('click.redirectOrToggle', function() {
$("#settingsDropdown").toggle();
});
}
}).triggerHandler('resize');
Instead of binding different handlers, change the logic within the click handler itself and you can remove the window.resize
/* called outside of window resize*/
$('#settings').click(function(){
if($(window).width() < 1400){
window.location = "settings.php";
}else{
$("#settingsDropdown").toggle();
}
})
Can someone explain me why this snippet can't work ?
I can't use specific features like window.location, submit(), (instead of trigger()), because this function is bound to elements that are very differents.
$('a, button').bind('click', function(oEvent, oData) {
var oButton = $(this);
var bSkip = (oData && oData.skip);
if(true === bSkip) {
return true;
} else {
oEvent.preventDefault();
//oEvent.stopPropagation();
if(confirm('This is a confirm box')) {
$(oButton).trigger('click', { skip: true });
}
}
});
Thanks in advance ! ;)
In your case even though the click event gets fired the default behavior of the links may not be triggered because of the constraints imposed by the browser
If I understand what you are trying to do correctly(if the action s not confirmed then cancel the default behavior), then you can achieve it by the below... there is no need to fire the event again
$('a, button').bind('click', function (oEvent, oData) {
if (confirm('This is a confirm box')) {
return true;
} else {
oEvent.preventDefault();
}
});
Demo: Fiddle
I am having trouble with jQuery and Safari on an iOS 5 and below devices...
I have a button that onClick toggles a menu, in Safari on iOS 5 and below the menu shows on the first click then closes on the second.. great.. However after that is requires 3 clicks to show the menu again. This does not happen on iOS 6 or on desktop browsers.
I have tried replacing the jQuery toggle() function with the following, but this has not helped.
pull.data('menuState','closed');
$(pull).on('click', function (e) {
if (pull.data('menuState') === 'closed') {
pull.data('menuState', 'open');
currentMenu.show();
} else {
pull.data('menuState', 'closed');
currentMenu.hide();
}
return false;
});
pull and currentMenu are defined higher in my code. The site is built on bootstrap if that is any help.
Turns out iOS 5 was triggering the window.resize function later in my code, not 100% its the best approach but I detected the version number to code around it.
function iOSversion() {
if (/iP(hone|od|ad)/.test(navigator.platform)) {
var v = (navigator.appVersion).match(/OS (\d+)_(\d+)_?(\d+)?/);
return [parseInt(v[1], 10), parseInt(v[2], 10), parseInt(v[3] || 0, 10)];
}
}
Here is what I made to replace toggle function, it seems to work well. just put your needs in function odd and even:
// place this before all of your code, outside of document ready.
$.fn.ToggleFix = function(odd, even) {
return this.each(function() {
var Toggled = false;
$(this).on("click", function() {
if (Toggled) {
Toggled = false;
return odd.apply(this, arguments);
}
Toggled = true;
return even.apply(this, arguments);
});
});
};
//what do you want each toggle to do
function odd() {
$(this).animate({"left": "+=50px"}, "slow");//EXAMPLE
}
function even() {
$(this).animate({"left": "-=50px"}, "slow");//EXAMPLE
}
//call your toggle method like this after creating the function you want above
$(function(){
$("YOUR ELEMENT").ToggleFix(even, odd);
});
jsFIDDLE