jquery.mobile swipe page navigation restrict to div element - javascript

I am working with this jquery.mobile example to use swipe to navigate pages.
jquery.mobile swipe-page example
Now I don´t want to have the swipe on the whole page. I want to bind it only to an div element.
I have a div element on my page
<div id="divSWIPE"></div>
I have looked at the source code of the example and I think I found the part that handles the swipe event.
// The same for the navigating to the previous page
$( document ).on( "swiperight", ".ui-page", function( event ) {
var prev = $( this ).jqmData( "prev" );
if ( prev && ( event.target === $( this )[ 0 ] ) ) {
navprev( prev );
}
});
I have tried to modify this but I can´t get this working only on the div element.
I have tried this
$( "#divSWIPE" ).on( "swiperight", ".ui-page", function( event ) {
and this
$( document ).on( "swiperight", "divSWIPE", function( event ) {
But this doesn´t work.
How can I bind this to my div element?

Attack swipe listeners on pagecreate. The below code will check if there is a page in DOM before the current page. Or retrieve value from custom attribute in page div data-prev.
$(document).on("pagecreate", function (e) {
var page = e.target;
$("#divSwipe", page).on("swiperight", function () {
var prev = $(this).closest(".ui-page").prev("[data-role=page]");
/* or read custom attribute */
var prev = $(this).closest(".ui-page").data("prev");
if ( prev.length > 0 || typeof prev != "undefined" ) {
/* navigate or do something else */
$.mobile.pageContainer.pagecontainer("change", prev);
}
});
});

Related

Scroll page to element on mobile is not working but on desktop yes, preventDefault is a problem?

I'm doing a website for desktop and mobile as well, the menu works perfect on desktop but not working on mobile, because I want the smothly scroll to id I use this code:
I found out that event.preventDefault() block a function I turn it off and it transfers me to id, but the animation is disabled at this point
$( 'a[href^="#"]' ).on( 'click', function ( event ) {
var target = $( $( this ).attr( 'href' ) );
var znacznik = $( $( this ).attr( 'a' ) );
if ( target.length ) {
event.preventDefault();
$( 'html, body' ).animate( {
scrollTop: target.offset().top - 80
}, 1000 );
}
} );
Is there any way to make it works on android? Maybe another function then event.preventDefault(); ?
I believe you may be overthinking this one, put an href on the button you want to scroll to, like so:
<button></button>
And for the smooth scrolling all I would do is set your CSS to the following:
html {
scroll-behavior: smooth;
}
Sets the entire page to have animations be smooth between elements.

Resize function events fire 2 times more each time the window was resized

On my site, I am trying to fix the navigation so that when the browser is getting resized from desktop to mobile size, the mobile menu works. I have the mobile menu working on initial load, and the desktop navigation working on initial load, but when I run the script in a $(window).on('resize', function() {} and click an item as depicted in my script, the event fires always +1 each time the window was rested after a resize.
What I mean is, if I load the page, scale it into mobile size, click the menu and a dropdown item, the click event will fire once. Resize the window out and then back in, the click event will fire now 2 times, then 3, and so on, depending on how many times the browser was resized.
I'm not sure exactly what is going on in my resize script that is screwing everything up and I'm at my wits end at trying to figure it out. Normally people aren't sitting there resizing their browser from desktop to mobile, but my boss does when he show's clients a beta of their site and wants this to never be an issue.
Here is my resize script:
(function( $ ) {
var id,
$body = $('body'),
$window = $( window ),
$navSlider = $('.nav-slider'),
$navMask = $( '.nav-mask' ),
$navToggler = $( '.navbar-toggler' ),
$parent = $( '.menu-item-has-children' ),
$parentLink = $( '.dropdown-toggle' ),
$childContainer = $( '.dropdown-menu' );
$window.on( 'resize', function( e ) {
clearTimeout(id);
id = setTimeout(function() {
close();
var width = $window.width();
if ( width < 992 ) {
setHeightToNav();
$navMask.on( 'click', function() { close() } );
$navToggler.on( 'click', function() { open() } );
$parentLink.on( 'click', function( e ) {
e.preventDefault();
var $this = $( this );
$this.data( 'clicked', true );
console.log( $this.parent() );
} )
}
if ( width >= 992 ) {
resetNavHeight();
console.clear();
}
}, 500 );
} );
function setHeightToNav() {
if ( $body.hasClass( 'logged-in' ) ) {
var $wpAdminBar = $( '#wpadminbar' ).outerHeight();
$navSlider.css( { top: $wpAdminBar + 'px' } );
}
var $navHeight = $( '#header-container' ).outerHeight();
$navSlider.css( { marginTop: $navHeight + 'px' } );
}
function resetNavHeight() {
if ( $body.hasClass( 'logged-in' ) ) {
$navSlider.css( { top: 0 + 'px' } );
}
$navSlider.css( { marginTop: 0 + 'px' } );
}
function close() {
$body.removeClass( 'has-active-menu' );
setTimeout( function() {
$navSlider.removeClass( 'toggling' );
$parent.removeClass( 'show' );
$parentLink.attr( 'aria-expanded', false );
$childContainer.removeClass( 'show' ).removeAttr( 'style' );
$parentLink.data('clicked', false);
}, 250 );
console.log('close()');
}
function open() {
$body.addClass( 'has-active-menu' );
$navSlider.addClass( 'toggling' );
}
})( jQuery );
I've tried my script both with AND without the setTimeout function and it happens exactly the same.
On the project, we are using Bootstrap 4, with the Bootstraps Dropdown._clearMenus(); function commented out in the right places as it was causing conflicts with the functionality I wanted with the navigation.
A link to a site where you can see this is here. It's a WordPress site as well if that matters for anything.
Any help is appreciated. I've been at this for several hours and am at my wits end.
.on( 'click', function ) does not set the event listener, it adds an event listener. Try doing off('click') before setting it if you really need to set this listener here.
But note that any other 'click' listener for this element will also be removed.
That's for the quick fix. You could do better, but that would require more work (track with a boolean if you just changed "display mode", and add or remove the event listeners only then, for example).

Hide menu when ESC clicked using Javascript

I am currently customising an off-screen navigation menu.
I'd like to use Javascript to close the menu when ESC is clicked or if the user clicks outside of the menu's focus. How do I achieve this?
Here's my example: http://jsfiddle.net/q55xtcw4/
I've tried using this code:
$( document ).on( 'click', function ( e ) {
if ( $( e.target ).closest( elem ).length === 0 ) {
$( elem ).hide();
}
});
$( document ).on( 'keydown', function ( e ) {
if ( e.keyCode === 27 ) { // ESC
$( elem ).hide();
}
});
but no success.
Many thanks for any guidance here.
Dirty but useful solution for you change your JS code into this
$(".nav-trigger").click(function(e){e.stopPropagation()})
$( document ).on( 'click', function ( e ) {
$( ".nav-trigger" ).prop("checked",false);
});
$( document ).on( 'keydown', function ( e ) {
if ( e.keyCode === 27 ) { // ESC
$( ".nav-trigger" ).prop("checked",false);
}
});
Here is the working fiddle
here is the updated fiddle
Here is a working JSFiddle: http://jsfiddle.net/e9wa0093/2/
Basically, elem wasn't defined in your example. Same with show() and hide() methods. The changes I made to your code merely updates the checked property of the hidden checkbox used to control the position (i.e., visibility) of the menu.
Edit:
Corrected JSFiddle, as commented below: http://jsfiddle.net/e9wa0093/4/
Use This :-
$(document).keyup(function(e) {
if (e.keyCode == 13) $('.save').click(); // enter
if (e.keyCode == 27) $('.cancel').click(); // esc
});
FOR more info click here
elem is not something on your DOM
$( elem ).hide();
you should change it into your class or id like:
$('#menu').hide();
Try using something like this:
<script>
$(document).ready(function(){
$(document).keypress(function (evt) {
//Determine where our character code is coming from within the event
var charCode = evt.charCode || evt.keyCode;
if (charCode == 27) { //Enter key's keycode
//do what ever you want
$('#someid').hide();
}
});
});
</script>
The solution you are using is based on a CSS hack using a hidden checkbox.
You can control the status of the menu by toggling the value of this checkbox, rather than using javascript to hide the menu. Hiding the menu using javascript will actually break the CSS hack, as the CSS depends on the menu being visible but just offset from the side of the screen.
So replace:
$( elem ).hide();
With:
$("#nav-trigger").click();
The below code will collapse the menu on pressing escape
$(document).keyup(function(e) {
if (e.keyCode == 27) { $("#nav-trigger").removeAttr("checked") }
});

How can I reuse this JQM function instead of copying it 5 times?

I saw this demo page and I build it in my page using JQM. However, to open the panel on swipe, the following function is needed:
$( document ).on( "pagecreate", "#demo-page", function() {
$( document ).on( "swipeleft swiperight", "#demo-page", function( e ) {
// We check if there is no open panel on the page because otherwise
// a swipe to close the left panel would also open the right panel (and v.v.).
// We do this by checking the data that the framework stores on the page element (panel: open).
if ( $( ".ui-page-active" ).jqmData( "panel" ) !== "open" ) {
if ( e.type === "swipeleft" ) {
$( "#right-panel" ).panel( "open" );
} else if ( e.type === "swiperight" ) {
$( "#left-panel" ).panel( "open" );
}
}
});
});
But I've got 4 other pages. How can I reuse the function for every page instead of copying it?
I'd recommend using an external panel that can be accessed from any page. An external panel should be placed outside any page, i.e. should be a sibling of all pages, a child of page container.
<!-- external panel -->
<div data-role="panel" id="myPanel">
<!-- content -->
</div>
<!-- pages -->
<div data-role="page" id="p1">
<!-- content -->
</div>
<div data-role="page" id="p1">
<!-- content -->
</div>
And then initialize it manually and enhance its' contents.
$(function () {
$("#myPanel").panel().enhanceWithin();
});
To add swipe listener, run the code once .one() on pagecreate.
$(document).one("pagecreate", function () {
$(document).on("swipeleft", function (e) {
if ($(".ui-page-active").jqmData("panel") !== "open") {
$("#myPanel").panel("open");
}
});
});
However, if you want to use a different panel for each page, then you need to run code whenever pagecreate triggers by utilizing event.target. Moreover, to target the panel in the page where swipe event was triggered, you need to use activePage method.
I forgot to mention that pagecreate event fires once per page, hence, the below code will be executed one time per page.
$(document).on("pagecreate", function (e) {
$(e.target).on("swipeleft", function (e) {
var activePage = $.mobile.pageContainer.pagecontainer("getActivePage");
if (activePage.jqmData("panel") !== "open") {
$("[data-role=panel]", activePage).panel("open");
}
});
});
Well it's a anonimouse function, just give it a name, save it in a *.js file and include that file in your four pages. Here the fuction with a name:
function withName( e ) {
// We check if there is no open panel on the page because otherwise
// a swipe to close the left panel would also open the right panel (and v.v.).
// We do this by checking the data that the framework stores on the page element (panel: open).
if ( $( ".ui-page-active" ).jqmData( "panel" ) !== "open" ) {
if ( e.type === "swipeleft" ) {
$( "#right-panel" ).panel( "open" );
} else if ( e.type === "swiperight" ) {
$( "#left-panel" ).panel( "open" );
}
}
}
function moreName() {
$( document ).on( "swipeleft swiperight", "#demo-page", withName);
}
$( document ).on( "pagecreate", "#demo-page", moreName);

Fixed Header Issue When Scrolling To Anchor From External Page

I recently repurposed a template for http://c42d.com, a portfolio website I'm building for a company called C42D. My issue concerns the scrolling functionality of the navigation system.
It works properly on the homepage. When you click any link in the nav at the top, it scrolls right to that section on the page perfectly, and it takes into consideration the height of the fixed header. The following Javascript is responsible for this functionality:
/** Hash Scroll */
/** Portfolio Filter */
$( '#navbar-spy' ).off( 'click' ).on( 'click', 'a', function( e ) {
if(!$( this ).attr( 'href' ).match(/^#/)) return;
e.preventDefault();
var elmHash = $( this ).attr( 'href' );
var elmOffsetTop = Math.ceil( $( this.hash ).offset().top );
var windowOffsetTop = Math.ceil( $(window).scrollTop() );
if( elmOffsetTop != 0 ) {
elmOffsetTop = elmOffsetTop - 84;
if( windowOffsetTop == 0 ) {
elmOffsetTop = elmOffsetTop - 0;
}
}
//console.log( $( this ).attr( 'href' ) );
$( 'html:not(:animated), body:not(:animated)' ).animate({ scrollTop: elmOffsetTop }, 1100 );
});
Unfortunately, when you navigate to any interior page on the site (http://c42d.com/termsandconditions, for example) and click a link in the nav, it brings you right to the proper anchor on the homepage, but doesn't take into consideration the height of the fixed header, and the title becomes partly obscured.
Any help would be greatly appreciated.
Thank you!
Zan
What I would do is on page load, detect the hash if any, and if there is, then run that same animation code to go to that.

Categories