mirror of
https://gerrit.wikimedia.org/r/mediawiki/extensions/RevisionSlider
synced 2024-12-18 09:50:49 +00:00
346846f16c
This is closely related to Ied0b974 which fixed a similar, if not the same rounding issue. Note the following might be different depending on e.g. the operating system. My Ubuntu+Chromium shows the following behavior: * The RTL scroll type is correctly detected as "negative" with all zoom factors below and up to 100%. * When the zoom factor is 110%, 125%, or 150% the scrollLeft value is not 0 but something like 0.909090876 or 0.200000002. * It's 0 again at 175% and 200%. * Bad at 250%. Good at 300%. Bad at 400%. And so on. No rhyme or reason. The current Firefox version also ends in the "negative" branch, but doesn't have the same rounding errors. It's always a perfect 0 in Firefox. This makes it look like a bug in Chrome's engine. We don't know how old it is, but based on the information in T352169 it might be a relatively new bug that didn't exist when this code was originally written in 2016 (see I7c903c2). For reference, this is what's supposed to happen here: Browsers with the scroll type "negative" (which are apparently all current Chrome and Firefox versions) won't allow scrollLeft to be a positive number on an RTL page. When you scroll to the left in such browsers the numbers get negative. The detection code tries to set the number to +1 anyway. We expect the browser to ignore this invalid call and still report the previous 0. This mostly works in Chrome as well. For example, setting scrollLeft to +100 wont set it to +100 but to … some random number between >=0 and <1, depending on the current zoom factor? o_O? I suspect we can remove this detection code entirely, or at least change the default to "negative". But this needs more testing with more browsers. Let's start with this tiny fix. Bug: T352169 Change-Id: I22cbb8881578e96165097d4fcc812baadc22d7fa
115 lines
3 KiB
JavaScript
115 lines
3 KiB
JavaScript
// originally taken from https://stackoverflow.com/questions/1517924/javascript-mapping-touch-events-to-mouse-events
|
|
function touchEventConverter( event ) {
|
|
const first = event.changedTouches[ 0 ];
|
|
|
|
event.preventDefault();
|
|
|
|
const type = {
|
|
touchstart: 'mousedown',
|
|
touchmove: 'mousemove',
|
|
touchend: 'mouseup'
|
|
}[ event.type ];
|
|
if ( !type ) {
|
|
return;
|
|
}
|
|
|
|
let simulatedEvent;
|
|
if ( typeof MouseEvent !== 'undefined' ) {
|
|
simulatedEvent = new MouseEvent( type, {
|
|
bubbles: true,
|
|
cancelable: true,
|
|
view: window,
|
|
detail: 1,
|
|
screenX: first.screenX,
|
|
screenY: first.screenY,
|
|
clientX: first.clientX,
|
|
clientY: first.clientY,
|
|
button: 0,
|
|
relatedTarget: null
|
|
} );
|
|
} else {
|
|
simulatedEvent = document.createEvent( 'MouseEvent' );
|
|
simulatedEvent.initMouseEvent(
|
|
type, true, true, window, 1,
|
|
first.screenX, first.screenY,
|
|
first.clientX, first.clientY,
|
|
false, false, false, false,
|
|
0, null
|
|
);
|
|
}
|
|
|
|
first.target.dispatchEvent( simulatedEvent );
|
|
}
|
|
|
|
// fixes issues with zoomed Chrome on touch see https://github.com/jquery/jquery/issues/3187
|
|
function correctElementOffsets( offset ) {
|
|
const isChrome = /Chrom(e|ium)/i.test( navigator.userAgent );
|
|
|
|
// since this problem only seems to appear with Chrome just use this in Chrome
|
|
if ( !isChrome ) {
|
|
return offset;
|
|
}
|
|
|
|
// get document element width without scrollbar
|
|
const prevStyle = document.body.style.overflow || '';
|
|
document.body.style.overflow = 'hidden';
|
|
const docWidth = document.documentElement.clientWidth;
|
|
document.body.style.overflow = prevStyle;
|
|
|
|
// determine if the viewport has been scaled
|
|
if ( docWidth / window.innerWidth !== 1 ) {
|
|
const docRect = document.documentElement.getBoundingClientRect();
|
|
offset = {
|
|
top: offset.top - window.pageYOffset - docRect.top,
|
|
left: offset.left - window.pageXOffset - docRect.left
|
|
};
|
|
}
|
|
|
|
return offset;
|
|
}
|
|
|
|
/**
|
|
* Based on jQuery RTL Scroll Type Detector plugin by othree: https://github.com/othree/jquery.rtl-scroll-type
|
|
*
|
|
* @return {string} - 'default', 'negative' or 'reverse'
|
|
*/
|
|
function determineRtlScrollType() {
|
|
const $dummy = $( '<div>' )
|
|
.css( {
|
|
dir: 'rtl',
|
|
width: '4px',
|
|
height: '1px',
|
|
position: 'absolute',
|
|
top: '-1000px',
|
|
overflow: 'scroll'
|
|
} )
|
|
.text( 'ABCDE' )
|
|
.appendTo( 'body' );
|
|
const definer = $dummy[ 0 ];
|
|
let type = 'reverse';
|
|
|
|
if ( definer.scrollLeft > 0 ) {
|
|
type = 'default';
|
|
} else {
|
|
definer.scrollLeft = 1;
|
|
// T352169: While Chrome ignores the +1 above (as it should), there are strange rounding
|
|
// errors with many (not all) of the possible zoom factors >100%
|
|
if ( definer.scrollLeft < 1 ) {
|
|
type = 'negative';
|
|
}
|
|
}
|
|
$dummy.remove();
|
|
return type;
|
|
}
|
|
|
|
function calculateRevisionsPerWindow( margin, revisionWidth ) {
|
|
return Math.floor( ( $( '#mw-content-text' ).width() - margin ) / revisionWidth );
|
|
}
|
|
|
|
module.exports = {
|
|
calculateRevisionsPerWindow: calculateRevisionsPerWindow,
|
|
correctElementOffsets: correctElementOffsets,
|
|
determineRtlScrollType: determineRtlScrollType,
|
|
touchEventConverter: touchEventConverter
|
|
};
|