Disable 2 finger swipe back navigation in Chrome on OSX [duplicate] - macos

I want to disable the two finger swipe that causes Chrome going back or forward.
I have a website where the user might lose progress on his work if he doesn't specifically saves.
I have tried using window.onbeforeunload but that doesn't seem to work if I have hashes in the url (back forward would change between www.example.com/work/#step1#unsaved www.example.com/work/#step0) and the event doesn't seem to trigger.
I was about to switch to another solution but today I noticed that in Google Docs it's completely disabled. How did they achieve that?

Disable Chrome two fingers back/forward swipe
This worked for me. In your CSS file:
html {
overscroll-behavior-x: none;
}
body {
overscroll-behavior-x: none;
}

Make the specific page open in a new tab/window by default (by putting target="_blank"> in hyperlink). That way there'll be no previous page to go back to.
Or prevent Horizontal Scrolling by default. To do that, you can use jquery.mousewheel to do:
$(document).on("mousewheel",function(event,delta){
// prevent horizontal scrolling
if (event.originalEvent.wheelDeltaX !== 0) {
event.preventDefault();
}
});

Assuming you have a horizontal-scrolling element, adding overscroll-behavior-x: contain; is the easiest way prevent the scroll action from spilling out into the page and causing the navigation.
https://dev.to/danburzo/css-micro-tip-prevent-history-navigation-on-horizontally-scrolling-elements-3iil
https://caniuse.com/#feat=css-overscroll-behavior

Disable or replace swipe gestures for Google Chrome 61
The question that leads me here was marked "duplicate" and closed to answers. I believe this answer is better suited for the "duplicated" question, however, I feel this answer could possibly save time for someone landing on either question.
Better question:
Disable navigation swipe on Chrome browser in javascript
This Google developers article helped me to allow the e.preventDefault() to work and prevent swipe gestures as of Chrome 61.
https://developers.google.com/web/updates/2017/01/scrolling-intervention
givanse's answer to the following was the code that I used to write my own swipe event handlers:
Detect a finger swipe through JavaScript on the iPhone and Android
In summary, the following two events are used to implement the swipe gestures:
handleTouchStart (e) {
...
},
handleTouchMove (e) {
...
e.preventDefault()
}
As of Chrome 56, the default behavior is to make the event listeners passive and thus disable the ability to prevent Chrome's swipe gestures. To override this behavior, event listeners can be added as follows:
document.addEventListener(
'touchstart',
this.handleTouchStart,
{passive: false}
)
document.addEventListener(
'touchmove',
this.handleTouchMove,
{passive: false}
)
By passing the {passive: false} object as the third parameter to the addEventListener method, the listener is registered as active and can stop Chrome's default behavior with the e.preventDefault() event method.

Building on both the previous answers given by #roy riojas and #redgetan - I combined their answers to allow for this to be dynamic and prevent both forward and backwards - again - per #roy's comments - you must know the class of your element, and for this implementation - the class of the nested element that is actually being scrolled
(function ($) {
$(document).on('mousewheel', function(e) {
var $target = $(e.target).closest('.scrollable-h');
var scroll = $target.scrollLeft();
var maxScroll = $target.find('.scrollable-h-content').width() - $target.width();
if(scroll <= 0) {
if(scroll <= 0 && e.originalEvent.wheelDeltaX >= 0) {
e.preventDefault();
}
}
if(scroll >= maxScroll) {
if (scroll >1 && e.originalEvent.wheelDeltaX <= 0) {
e.preventDefault();
}
}
});}(jQuery));

I've been working on something similar where I want to override the forward/backward history swiping gesture. Depending on what your swipe area is you can tweak the selector as follows:
html { touch-action:none; }
This is the associated documentation that gives you all the properties to all touch actions like panning or zooming features built into the browser.
https://developer.mozilla.org/en-US/docs/Web/CSS/touch-action

I was able to disable it by typing chrome://flags in the address bar and heading down to "Overscroll history navigation" and setting it to "Disabled" from the dropdown.

You can disable back/forward with this code:
document.addEventListener("wheel", function(event) {
event.preventDefault();
}, { passive: false });
Note that adding { passive: false } is essential, at least in Chrome. If you only want to disable back/forward in certain areas you can use code like this (assuming you're using jquery and you add the class disable-back-forward to the sections where you want to disable back/forward):
document.addEventListener("wheel", function(event) {
if ($(event.target).closest('.disable-back-forward').length)
event.preventDefault();
}, { passive: false });

Hi this worked for me on chrome but not for the entire page, but for places where I have scrollable content.
In Google Docs (Spreadsheets) it seems to be working because they don't have a back page to go. If you navigate to another URL (manually) it will not prevent you from navigating back.
$(document).on('mousewheel', function(e) {
var $target = $(e.target).closest('.scrollable-h');
if ($target.scrollLeft () <= 4) {
$target.scrollLeft(5);
return false;
}
});
One thing to keep in mind is that the code above is making two assumptions:
your element with horizontal scrollable content has a class scrollable-h
If checks if the scrollLeft if bigger less than 4px and then just make it scroll to 5px
returning false effectively cancel the back gesture
Important:
- This only prevents the back swipe gesture, when is done fast, if you do it very slow it will still trigger sometimes.
Also this does not prevent the forward swipe gesture, but it could also be done by checking if the element has reached the maximum scrollLeft. If that is the case then move it 20px back and return false to prevent the event from happening... It is up to you to add this use case if it happens to make sense to you.
You can take a look to a proof of concept here. http://jsfiddle.net/royriojas/JVA6m/#base

You're looking at the problem at the wrong level. OnBeforeUnload is simply not triggered because there is nothing being unloaded from the browsers perspective. Therefore you have, quite bluntly, implemented the wrong mechanism for versioning - fragments are for page states, not document states as you are using it now.
If you insist on maintaining state through hash fragments you need to use another mechanism to guard against page state changing. Since all current browsers support LocalStorage I'd use that. And well, while at it, put all the document state data there instead of in the URL, since that is how Google Docs does it and that is why they don't have this issue.

Related

dc.js: cannot scroll past chart even after setting mouseZoomable to false

Background
I have created a chart and implemented a click-to-zoom/mouseout-to-reset-zoom feature as follows.
chart.on('pretransition', (c) => {
// click to enable zooming
c.select('svg').on('click.enablemousezoomable', () => {
c.focus();
c.mouseZoomable(true).render();
});
chart.on('postRedraw', (c) => {
// mouseleave to disable zooming
c.select('svg').on('mouseleave.disablemousezoomable', () => {
c.focus();
c.mouseZoomable(false).render();
});
});
Problem
While the feature works as intended, the problem is that after redrawing, page scrolling is impossible if the cursor remains on the chart.
The cursor needs to be moved off of the chart in order to get page scrolling to work.
Question
What might be causing this problem and what is the solution?
Thanks!
I made a block from the dc.js stock example, which uses mouseZoomable in the Monthly Index Abs Move & Volume/500,000 Chart, and applied your changes.
Indeed, it disables zoom but it still leaves the wheel disabled after mouseZoomable has been disabled.
As dc.js#991 discusses, the way dc.js removes zoom is incorrect. According to the d3-zoom documentation, this should be correct:
moveChart._nullZoom = function(sel) {
sel.on('.zoom', null);
};
Indeed, I tried it in this fork of the block, and it seems to work much better. I think it's the correct fix for the linked issue, too.
There are some artifacts due to the redraws for adding and removing zoom, but I think they are out of scope for this question.

CKEditor "overflow: scroll" on parent causes toolbar to freeze at initial position

When you add a CKEditor to a div inside a div with: "overflow: scroll" the toolbar won't move when scrolling the parent div...
<div id="wrapper" style="overflow: scroll;">
<div contenteditable="true">This is the ckedito</div>
</div>
An example can be found here: ​http://jsfiddle.net/W8Dt4/
Does anyone know a workaround around this problem?
I think the desired behaviour would be:
Keep the toolbar at the top of the editor div when there's enough room.
Move the toolbar to the bottom of the editor div when there's not enough room on top and there is enough room on the bottom.
Using version 4.4.3, I was able to solve this problem by fire the window scroll event in a similar way that it is done in other areas in CKEditor. Attach a scroll event to the parent container that has overflow:scroll; set on it and trigger the window scroll within. The positioning is a little clunky but still works.
$("#parent-with-scroll").on('scroll', function (evt) {
CKEDITOR.document.getWindow().fire('scroll');
});
Yup. CKEditor never considered such case and, most likely, editor will never deal with such edge case.
Still, what you need is a scroll listener for editor.element.getParent() in those lines of floatingspace plugin. Unfortunately, you have to wait for the ticket #9816 to be resolved, because it changes the way of re-positioning the toolbar, and makes your case possible to fix. Once the fix is released (in 4.2.1), you got to basically change the lines to look like this:
var elementParent = editor.element.getParent();
editor.on( 'focus', function( evt ) {
...
elementParent.on( 'scroll', uiBuffer.input );
} );
editor.on( 'blur', function() {
...
elementParent.removeListener( 'scroll', uiBuffer.input );
} );
editor.on( 'destroy', function() {
...
elementParent.removeListener( 'scroll', uiBuffer.input );
} );
If you want, you can give it a try with this ticket branch. Otherwise, you got to need to wait for the upcoming release to patch your code.
There's also one thing that you need to know: each floating toolbar is appended to <body>, so it will never belong to the same (overflowed) container enclosing your editor. Even though the toolbar will scroll along with the container, it will always float above it and there's not much you can do about it unless you also hack this line. Note that I haven't tested it.
I hope this helped you.

How to disable delay to detect single/double tap on List component to improve performance in Sencha Touch 2.2

I am using a list component and there seems to be a very noticeable delay when tapping a list item to open the next view. My understanding is that it is waiting to detect whether the tap is a single tap or a double tap. In the case of my app, all taps will always be single taps as there is no double tap action. Is there a way to disable this delay or prevent it so that the performance with which the app reacts to tap events is improved?
I use FastClick (Official Page) (GitHub). You end up having to add a block of about 500 lines of code to your app, which of course isn't ideal, but it works quite well and is super easy to implement.
If you don't use double taps in your app, then add this code to your app.js:
eventPublishers: {
touchGesture: {
recognizers: {
doubleTap: null,
}
}
},
This will prevent app/touch/src/event/recognizer/DoubleTap.js from loading. The maxDuration of 300 ms is set there.

Is there a way to disable mouseover on highcharts entirely?

I'm building a website that uses highcharts. When I view the site on a mobile device, touching within the graph area pops up the tooltip, which prevents scrolling. I have tried all of the following, as suggested in other SO questions, without success:
$('#graph-container').click(function() { return false; });
$('#graph-container').children().click(function() { return false; });
chart.container.onclick = null;
plotOptions: {
series: {
enableMouseTracking: false // (stops tooltip but still blocks scrolling)
}
}
For now I've added a second div that covers the graph on mobile devices, so the user touches the div instead of the graph, but that is more a workaround than a solution. I also tried removing all listeners from every element of the graph using things like $('svg').off() in Chrome's console, without any noticeable change in the graph's behaviour. Is there a way to do this that I'm missing?
Highcharts JS v2.3.5 (2012-12-19)
Little HACK:
edit Line: 9026: this.setDOMEvents();
into: // this.setDOMEvents();
or delete it.
I hope it helped!
Here you can find simple Gist for that.
Also, in upcoming Highcharts 3.0 touch events should be upgraded and fixed similar issues. See roadmap: http://www.highcharts.com/support/roadmap

How to make it so events cannot occur while an event is running in DOJO?

Is there some way I can disable all events until an event is completed in DOJO? For instance I am fading elements and the user can click the event again and it will not complete the last event.
If you control all events that need to be disabled, you could try using a global variable as a "lock" - set it on when you start the animation (and have all events abort if they find this flag triggered) and unset it when it ends.
Javascript is not concurrent (so you don't need to worry about timing issues and having an "actual" lock) but perhaps the fading uses setTimeout behind the scenes (allowing other events to trigger before it is done). If this is the case, just remember that you would need to use the onEnd callback to properly detect when the anim is over
var lock = false;
function my_event_handler(evt){
if(lock) return; //someone else is using the lock;
//perhaps cancel event propagation as well?
lock = true;
dojo.anim({
...
onEnd: function(){
lock = false;
}
});
}
caveat: this is pseudocode off the top of my head. I haven't used dojo animations in a while if you didn't notice already :P
I'm not sure I understand what you mean by events here, but if you want to prevent interaction with elements on a page, you can put up a modal shield... basically a transparent DIV element to capture events, positioned over your content with a high z-index

Resources