Close an Element on Touch Device Using jQuery - javascript

I have the following code which opens a div element on a touch screen device when the main nav menu link (.nav-landing > li) has been tapped. If the nav menu link is tapped for the second time the link becomes active and loads the page link. This all works fine but I can't figure out how to close the div element (.touch-device) if the user stays on the page and no longer needs to see the content within the div element.
(function ($) {
var landingLink = '.nav-landing > li';
// BROWSER WITH EITHER TOUCH EVENTS OR POINTER EVENTS RUNNING ON TOUCH-CAPABLE DEVICE
if (('ontouchstart' in window) || (navigator.maxTouchPoints > 0) || (navigator.msMaxTouchPoints > 0)) {
// DISPLAY LANDING PAGE MEGA NAV ON TOUCH
$(landingLink).live('touchstart', function (e) {
'use strict';
var link = $(this);
var megaDiv = $(this).find('div');
// REMOVE touch-device CLASS IF NAV LINK HASN'T BEEN TAPPED
if (!megaDiv.hasClass('touch-device')) {
$('.touch-device').removeClass('touch-device');
}
if (link.hasClass('hover')) {
// SECOND TOUCH
return true;
} else {
// FIRST TOUCH
link.addClass('hover');
megaDiv.addClass('touch-device');
$(landingLink).not(this).removeClass('hover');
e.preventDefault();
return false;
}
});
$('.close-div').click(function () {
//alert('clicked');
});
} else { // STANDARD DESKTOP BROWSERS WITH MOUSE HOVER
// DISPLAY LANDING PAGE MEGA NAV ON HOVER
$(landingLink).has('div').hover(function () {
$(this).addClass('hover').find('div').show();
}, function () {
$(this).removeClass('hover').find('div').hide();
});
}
})(jQuery);
I've also setup a JSFiddle to show the full example:
JSFiddle

Related

Close drop down menu when clicking outside menu

I have the following
function subNavToggle() {
var subNav = document.getElementById("subnav-section");
if (subNav.className === "navigation-subnav") {
subNav.className += " responsive";
} else {
subNav.className = "navigation-subnav";
}
}
I am trying to get the expanded menu to close when clicking outside of menu.
I have this, which will close the menu, but it also closes the hamburger menu - preventing the user to be able to open again.
$(document).click(function(event) {
var $target = $(event.target);
if(!$target.closest('.sub_nav_links').length &&
$('.sub_nav_links').is(":visible")) {
$('.sub_nav_links').hide();
}
});
Also thought I could get away with the following, but it actually does the opposite. Opening outside menu item.
window.onclick = subNav;
$('html').on('click, touchend', function (e) {
// Close hamburger menu when tapping outside
if ($(e.target).closest('#subnav-section').length == 0) {
var opened = $('.navigation-subnav').hasClass('responsive');
if (opened === true) {
$('.navigation-subnav').collapse('hide');
}
}
});
// to hide
$(document).click(function(){
$("#submenu").hide();
});
// you could possibly prevent to hide menu while using navigation
$("#menu").click(function(e){
e.stopPropagation();
});

Hide/Show Overlay on Click

I currently have an Overlay on my page which fades in when I click certain Navigation elements such as search/dropdown.
My problem is that if I click the dropdown, then click the Search menu item it fades out the overlay and breaks by showing the overlay and no search bar.
If the overlay is already open, you don't need to fade
it in, just fade it out when you click something else.
I've added a Variable to check if it's already open, but obviously this gets troublesome with 'FadeToggle'. I've tried a lot of combinations with this but can't seem to get it to the above.
var overlay = false;
$('#myDropdown').on('show.bs.dropdown', function () {
if(overlay == false) {
$(".overlay").fadeIn(150);
overlay = true;
}
})
$('#myDropdown').on('hide.bs.dropdown', function () {
if(overlay == true) {
$(".overlay").fadeOut(150);
overlay = false;
}
})
$( "#searchToggle, #mobileSearchToggle" ).click(function() {
$('.search-bar').toggleClass( "open" );
$('body').toggleClass("noScroll");
$('.dropdown-menu').removeClass('show');
if(overlay == false) {
$(".overlay").fadeToggle(150);
}
});

Scrolling menu on iPhone

I have problem with my dropdown menu on iPhone. Whenever I have more than 6 links on my menu the list is too long and whenever I want to scroll it little bit down with finger I can't because I press on link and its instantly fire to another url. How I can avoid that and recognize that I want to scroll menu little bit down and how to recognize if I tapped a menu li to go into another url?
$(".content-bar--content").on("click", function() {
window.location.href = link;
});
This is what my code looks like.
Based on https://www.falise.com/blog/prevent-click-event-scrolling-ipad/ without jquery
First we check if the device is iOS or not
var iOS = agent.indexOf('iphone') >= 0 || agent.indexOf('ipad') >= 0;
We also need a variable which will tell us if the screen is being touched and moved.
var touchMoving = false;
Then for iOS only add event listeners that listen for touchmove and touchend that will set touchMoving to the appropriate value.
if (iOS)
{
document.addEventListener("touchmove", function(e)
{
touchMoving = true;
});
document.addEventListener("touchend", function(e)
{
touchMoving = false;
});
}
Now when a link with a class content-bar--content is clicked while scrolling it will prevent the click event because touchMoving is true.
document.querySelectorAll('.content-bar--content').forEach(elem => {
elem.addEventListener('click', function(e) {
if (touchMoving) {
e.preventDefault();
}
}
});

disable click link on touch devices not working as expected

what I'm trying to do
I have dropdown-menus that open on hover and the parent menus have their own landing page link. we're not willing to sacrifice this behavior, but if obviously creates problem for large touch enabled devices. So, I'm detecting touch devices with jquery, and disabling the parent menu click on devices larger than 990px wide. devices below 990px is considered as mobile view and it switches to toggle. This switch between the toggle and the desktop view is expected to continue on screen rotation too.
what is happening
the menu link is disabled on first load and works as expected. Then I rotate the screen (from landscape to portrait) and see the mobile menu as expected and navigate to another page. once the page loads, I rotate it again (from portrait to landscape) and the desktop view is visible, but the parent links are clickable now!
I want to prevent this click event on second rotation too. HTML is standard bootstrap 3 navigation code and my js is like this:
function isTouchDevice() {
return true == ("ontouchstart" in window || window.DocumentTouch && document instanceof DocumentTouch);
}
$(document).ready(function () {
$(window).resize(function () {
var o = $(window).innerWidth();
function isTouchDevice() {
return true == ("ontouchstart" in window || window.DocumentTouch && document instanceof DocumentTouch);
}
if ((isTouchDevice() === true) && (o >= 990)) {
$('.navbar .dropdown > a ').each(function () {
$(this).on("click", function(){
return false
})
})
alert('oi!!')
}
else {
$('.navbar .dropdown > a ').each(function () {
$(this).on("click", function(){
location.href = this.href;
})
});
alert ("bad!") //for debugging purpose, not really needed
}
}).resize();
//the mobile menu clicks events
$('#menu .dropdown > a ').click(function () {
location.href = this.href;
});
});
PS this is a website, not an android app. I have found answers that answer this type of questions for android apps.
Update the jsfiddle for my code
I solved it myself. Turns out, the condition for width checking was creating the problem and in my case, unnecessary, because bootstrap is already hiding the menu in smaller screens and I was targeting touch enabled desktop devices anyway. so I took off && (o >= 990) from the if condition and it is working as expected.
full js is below (in case anyone needs it). I used the timer to prevent the event from firing before the resize, but it will probably work without the timer too. :
$(document).ready(function () {
var resizeTimer;
$(window).on('resize', function(e){
clearTimeout(resizeTimer);
resizeTimer = setTimeout(function () {
function isTouchDevice() {
return true == ("ontouchstart" in window || window.DocumentTouch && document instanceof DocumentTouch);
}
if (isTouchDevice() === true) {
$('.navbar .dropdown > a ').click(function () {
return false
});
console.log("landscape")
}
else {
$('.navbar .dropdown > a ').each(function () {
$(this).on("click", function(){
location.href = this.href;
})
});
console.log("portrait")
}
}, 250)
}).trigger('resize');
});
I think this is a problem with the way you are recognizing the mobile device. For checking device sizes I would not suggest using $(window).innerWidth(). What you are doing now does not check the screen size, rather it checks the window size, which fluctuates when switching orientation.
I would like to suggest that instead of checking for only >900px, that you check for the entire area of the device (width x height) so landscape and portrait would act the same way. And I would like to suggest using screen.availHeight * screen.availWidth to determine this.
I really hope this helps you with your problem. Please let me know if not and I'll help you debug.

jquery angularjs how to know if mouse down event is trigger by scrollbar of browser

I have a small panel which i close if mouse down button is pressed anywhere else than that panel, basically it clears the data to display and just with the help of angularjs ng-show i hide it if there is no data...application is in angularjs and jquery
please find the code below
var closeSearchResultsIfClickedOutside = function (e) {
if ($(e.target).parents('.searchResults').length === 0) {
var scope = angular.element($("#searchContainer")).scope();
scope.$apply(function () {
/*Cancels any existing search*/
if ($scope.defer != undefined) {
$scope.defer.resolve();
}
$scope.showSearchResults = false;
reinitialize();
});
$("html").off("mousedown", closeSearchResultsIfClickedOutside);
reinitializePanelsWidth();
}
};
but i dont want to close this panel if mouse down is on scrollbar of browser window or any scrollbar..please tell me how to do that
to fix the above problem i am not capturing both event, mouse down and click, if the target element on both event matches then only i am closing the panel.
/*
If mouse down and click on the same control, then only close the panel,
Click event closing is added to avoid closing panel on scrollbar click.
*/
var closeSearchResultsIfClickedOutside = function (e) {
if (e.type === 'mousedown') { /* only if mouse down is outside of search panel then only close the panel. */
if($(e.target).parents('.searchResults').length === 0)
{
isMouseDownOnSearchPanel = true;
}
else {
isMouseDownOnSearchPanel = false;
}
}
else if (e.type === 'click' && isMouseDownOnSearchPanel) { /*click event is implemented to avoid closing when mouse down is on scrollbar. you dont get click get event for scrollbar*/
var scope = angular.element($("#searchContainer")).scope();
$("html").off("mousedown", closeSearchResultsIfClickedOutside);
$("html").off("click", closeSearchResultsIfClickedOutside);
isMouseDownOnSearchPanel = false;
reinitializePanelsWidth();
}
};

Categories