Refactor and test renderer#createLayout

* Make function dependencies explicit;
* Only pass data that's needed, no more.

Bug: T133022
Change-Id: Ia973bd9636a477a76db907a37e2a0689daf4e3fa
This commit is contained in:
Baha 2017-05-05 11:57:52 -04:00
parent da2e8c82b0
commit 6d95bbf630
4 changed files with 192 additions and 28 deletions

Binary file not shown.

Binary file not shown.

View file

@ -254,7 +254,27 @@ function renderExtract( extract, title ) {
* in
*/
function show( preview, event, behavior, token ) {
var layout = createLayout( preview, event );
var $link = $( event.target ),
layout = createLayout(
preview.isTall,
{
pageX: event.pageX,
pageY: event.pageY,
clientY: event.clientY
},
{
clientRects: $link.get( 0 ).getClientRects(),
offset: $link.offset(),
width: $link.width(),
height: $link.height()
},
{
scrollTop: $window.scrollTop(),
width: $window.width(),
height: $window.height()
},
SIZES.pokeySize
);
preview.el.appendTo( document.body );
@ -457,73 +477,85 @@ function createThumbnailElement( className, url, x, y, thumbnailWidth, thumbnail
*
* @typedef {Object} ext.popups.PreviewLayout
* @property {Object} offset
* @property {number} offset.top
* @property {number} offset.left
* @property {Boolean} flippedX
* @property {Boolean} flippedY
*/
/**
* Extracted from `mw.popups.renderer.article.getOffset`.
*
* @param {ext.popups.Preview} preview
* @param {Object} event
* @param {isPreviewTall} isPreviewTall
* @param {Object} eventData Data related to the event that triggered showing a popup
* @param {number} eventData.pageX
* @param {number} eventData.pageY
* @param {number} eventData.clientY
* @param {Object} linkData Data related to the link thats used for showing a popup
* @param {ClientRectList} linkData.clientRects list of rectangles defined by four edges
* @param {Object} linkData.offset
* @param {number} linkData.width
* @param {number} linkData.height
* @param {Object} windowData Data related to the window
* @param {number} windowData.scrollTop
* @param {number} windowData.width
* @param {number} windowData.height
* @param {number} pokeySize Space reserved for the pokey
* @return {ext.popups.PreviewLayout}
*/
function createLayout( preview, event ) {
function createLayout( isPreviewTall, eventData, linkData, windowData, pokeySize ) {
var flippedX = false,
flippedY = false,
link = $( event.target ),
offsetTop = ( event.pageY ) ? // If it was a mouse event
offsetTop = ( eventData.pageY ) ? // If it was a mouse event
// Position according to mouse
// Since client rectangles are relative to the viewport,
// take scroll position into account.
getClosestYPosition(
event.pageY - $window.scrollTop(),
link.get( 0 ).getClientRects(),
eventData.pageY - windowData.scrollTop,
linkData.clientRects,
false
) + $window.scrollTop() + SIZES.pokeySize :
) + windowData.scrollTop + pokeySize :
// Position according to link position or size
link.offset().top + link.height() + SIZES.pokeySize,
clientTop = ( event.clientY ) ?
event.clientY :
linkData.offset.top + linkData.height + pokeySize,
clientTop = ( eventData.clientY ) ?
eventData.clientY :
offsetTop,
offsetLeft = ( event.pageX ) ?
event.pageX :
link.offset().left;
offsetLeft = ( eventData.pageX ) ?
eventData.pageX :
linkData.offset.left;
// X Flip
if ( offsetLeft > ( $window.width() / 2 ) ) {
offsetLeft += ( !event.pageX ) ? link.width() : 0;
offsetLeft -= !preview.isTall ?
if ( offsetLeft > ( windowData.width / 2 ) ) {
offsetLeft += ( !eventData.pageX ) ? linkData.width : 0;
offsetLeft -= !isPreviewTall ?
SIZES.portraitPopupWidth :
SIZES.landscapePopupWidth;
flippedX = true;
}
if ( event.pageX ) {
if ( eventData.pageX ) {
offsetLeft += ( flippedX ) ? 20 : -20;
}
// Y Flip
if ( clientTop > ( $window.height() / 2 ) ) {
if ( clientTop > ( windowData.height / 2 ) ) {
flippedY = true;
// Mirror the positioning of the preview when there's no "Y flip": rest
// the pokey on the edge of the link's bounding rectangle. In this case
// the edge is the top-most.
offsetTop = link.offset().top;
offsetTop = linkData.offset.top;
// Change the Y position to the top of the link
if ( event.pageY ) {
if ( eventData.pageY ) {
// Since client rectangles are relative to the viewport,
// take scroll position into account.
offsetTop = getClosestYPosition(
event.pageY - $window.scrollTop(),
link.get( 0 ).getClientRects(),
eventData.pageY - windowData.scrollTop,
linkData.clientRects,
true
) + $window.scrollTop();
) + windowData.scrollTop;
}
offsetTop -= SIZES.pokeySize;
offsetTop -= pokeySize;
}
return {
@ -697,6 +729,7 @@ module.exports = {
createThumbnail: createThumbnail,
createThumbnailElement: createThumbnailElement,
renderExtract: renderExtract,
createLayout: createLayout,
getClasses: getClasses,
getClosestYPosition: getClosestYPosition
};

View file

@ -602,6 +602,137 @@ QUnit.test( 'getProcessedElements', function ( assert ) {
} );
} );
QUnit.test( '#createLayout - portrait preview, mouse event, link is on the top left of the page', function ( assert ) {
var isPreviewTall = false,
eventData = {
pageX: 252,
pageY: 1146,
clientY: 36
},
linkData = {
clientRects: [ {
bottom: 37,
height: 13,
left: 201,
right: 357,
top: 24,
width: 156
} ],
offset: {
top: 1134,
left: 201
},
width: 156,
height: 13
},
windowData = {
scrollTop: 1109,
width: 1239,
height: 827
},
pokeySize = 8,
layout = renderer.createLayout( isPreviewTall, eventData, linkData, windowData, pokeySize );
assert.deepEqual(
layout,
{
offset: {
top: 1154,
left: 232
},
flippedX: false,
flippedY: false
},
'Layout is correct.'
);
} );
QUnit.test( '#createLayout - tall preview, mouse event, link is on the bottom center of the page', function ( assert ) {
var isPreviewTall = true,
eventData = {
pageX: 176,
pageY: 1252,
clientY: 628
},
linkData = {
clientRects: [ {
bottom: 640,
height: 13,
left: 177,
right: 209,
top: 627,
width: 32
} ],
offset: {
top: 1250,
left: 177
},
width: 32,
height: 13
},
windowData = {
scrollTop: 623,
width: 587,
height: 827
},
pokeySize = 8,
layout = renderer.createLayout( isPreviewTall, eventData, linkData, windowData, pokeySize );
assert.deepEqual(
layout,
{
offset: {
top: 1242,
left: 156
},
flippedX: false,
flippedY: true
},
'Layout is correct. Y is flipped.'
);
} );
QUnit.test( '#createLayout - empty preview, keyboard event, link is on the center right of the page', function ( assert ) {
var isPreviewTall = false,
eventData = {},
linkData = {
clientRects: [ {
bottom: 442,
height: 13,
left: 654,
right: 692,
top: 430,
width: 38
} ],
offset: {
top: 1118,
left: 654
},
width: 38,
height: 13
},
windowData = {
scrollTop: 689,
width: 801,
height: 827
},
pokeySize = 8,
layout = renderer.createLayout( isPreviewTall, eventData, linkData, windowData, pokeySize );
assert.deepEqual(
layout,
{
offset: {
top: 1110,
left: 392
},
flippedX: true,
flippedY: true
},
'Layout is correct. Both X and Y are flipped.'
);
} );
QUnit.test( '#getClasses when no thumbnail is available', function ( assert ) {
var cases = [
// [ previewOptions, layoutOptions, expected, message ]