1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
|
/**
* Internal dependencies
*/
import { GUTTER_WIDTH } from '../../constants';
/**
* Distribute a difference across ns so that their sum matches the target
*
* @param {Array<number>} parts Array of numbers to fit
* @param {number} target Number that sum should match
* @return {Array<number>} Adjusted parts
*/
function adjustFit( parts, target ) {
const diff = target - parts.reduce( ( sum, n ) => sum + n, 0 );
const partialDiff = diff / parts.length;
return parts.map( p => p + partialDiff );
}
export function handleRowResize( row, width ) {
applyRowRatio( row, getRowRatio( row ), width );
}
function getRowRatio( row ) {
const result = getRowCols( row )
.map( getColumnRatio )
.reduce(
( [ ratioA, weightedRatioA ], [ ratioB, weightedRatioB ] ) => {
return [ ratioA + ratioB, weightedRatioA + weightedRatioB ];
},
[ 0, 0 ]
);
return result;
}
export function getGalleryRows( gallery ) {
return Array.from( gallery.querySelectorAll( '.tiled-gallery__row' ) );
}
function getRowCols( row ) {
return Array.from( row.querySelectorAll( '.tiled-gallery__col' ) );
}
function getColImgs( col ) {
return Array.from(
col.querySelectorAll( '.tiled-gallery__item > img, .tiled-gallery__item > a > img' )
);
}
function getColumnRatio( col ) {
const imgs = getColImgs( col );
const imgCount = imgs.length;
const ratio =
1 /
imgs.map( getImageRatio ).reduce( ( partialColRatio, imgRatio ) => {
return partialColRatio + 1 / imgRatio;
}, 0 );
const result = [ ratio, ratio * imgCount || 1 ];
return result;
}
function getImageRatio( img ) {
const w = parseInt( img.dataset.width, 10 );
const h = parseInt( img.dataset.height, 10 );
const result = w && ! Number.isNaN( w ) && h && ! Number.isNaN( h ) ? w / h : 1;
return result;
}
function applyRowRatio( row, [ ratio, weightedRatio ], width ) {
const rawHeight =
( 1 / ratio ) * ( width - GUTTER_WIDTH * ( row.childElementCount - 1 ) - weightedRatio );
applyColRatio( row, {
rawHeight,
rowWidth: width - GUTTER_WIDTH * ( row.childElementCount - 1 ),
} );
}
function applyColRatio( row, { rawHeight, rowWidth } ) {
const cols = getRowCols( row );
const colWidths = cols.map(
col => ( rawHeight - GUTTER_WIDTH * ( col.childElementCount - 1 ) ) * getColumnRatio( col )[ 0 ]
);
const adjustedWidths = adjustFit( colWidths, rowWidth );
cols.forEach( ( col, i ) => {
const rawWidth = colWidths[ i ];
const width = adjustedWidths[ i ];
applyImgRatio( col, {
colHeight: rawHeight - GUTTER_WIDTH * ( col.childElementCount - 1 ),
width,
rawWidth,
} );
} );
}
function applyImgRatio( col, { colHeight, width, rawWidth } ) {
const imgHeights = getColImgs( col ).map( img => rawWidth / getImageRatio( img ) );
const adjustedHeights = adjustFit( imgHeights, colHeight );
// Set size of col children, not the <img /> element
Array.from( col.children ).forEach( ( item, i ) => {
const height = adjustedHeights[ i ];
item.setAttribute( 'style', `height:${ height }px;width:${ width }px;` );
} );
}
|