-
-
Notifications
You must be signed in to change notification settings - Fork 3.2k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(grid): rework Grid module to use actual CSS grid, remove resizab…
…le grid
- Loading branch information
1 parent
78ee711
commit 8381a75
Showing
11 changed files
with
56 additions
and
895 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,10 +1,3 @@ | ||
:root { | ||
--f7-grid-gap: 16px; | ||
--f7-grid-row-gap: 0px; | ||
.light-vars({ | ||
--f7-grid-resize-handler-bg-color: rgba(0, 0, 0, 0.35); | ||
}); | ||
.dark-vars({ | ||
--f7-grid-resize-handler-bg-color: rgba(255, 255, 255, 0.35); | ||
}); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,235 +1,3 @@ | ||
import { getDocument } from 'ssr-window'; | ||
import $ from '../../shared/dom7.js'; | ||
import { extend } from '../../shared/utils.js'; | ||
|
||
function getElMinSize(dimension, $el) { | ||
let minSize = $el.css(`min-${dimension}`); | ||
if (minSize === 'auto' || minSize === 'none') { | ||
minSize = 0; | ||
} else if (minSize.indexOf('px') >= 0) { | ||
minSize = parseFloat(minSize); | ||
} else if (minSize.indexOf('%') >= 0) { | ||
minSize = | ||
($el.parent()[0][dimension === 'height' ? 'offsetHeight' : 'offsetWidth'] * | ||
parseFloat(minSize)) / | ||
100; | ||
} | ||
return minSize; | ||
} | ||
function getElMaxSize(dimension, $el) { | ||
let maxSize = $el.css(`max-${dimension}`); | ||
if (maxSize === 'auto' || maxSize === 'none') { | ||
maxSize = null; | ||
} else if (maxSize.indexOf('px') >= 0) { | ||
maxSize = parseFloat(maxSize); | ||
} else if (maxSize.indexOf('%') >= 0) { | ||
maxSize = | ||
($el.parent()[0][dimension === 'height' ? 'offsetHeight' : 'offsetWidth'] * | ||
parseFloat(maxSize)) / | ||
100; | ||
} | ||
return maxSize; | ||
} | ||
|
||
const Grid = { | ||
init() { | ||
const app = this; | ||
let isTouched; | ||
let isMoved; | ||
let touchStartX; | ||
let touchStartY; | ||
let $resizeHandlerEl; | ||
let $prevResizableEl; | ||
let $nextResizableEl; | ||
let prevElSize; | ||
let prevElMinSize; | ||
let prevElMaxSize; | ||
let nextElSize; | ||
let nextElMinSize; | ||
let nextElMaxSize; | ||
let parentSize; | ||
let itemsInFlow; | ||
let gapSize; | ||
let isScrolling; | ||
|
||
function handleTouchStart(e) { | ||
if (isTouched || isMoved) return; | ||
$resizeHandlerEl = $(e.target).closest('.resize-handler'); | ||
touchStartX = e.type === 'touchstart' ? e.targetTouches[0].pageX : e.pageX; | ||
touchStartY = e.type === 'touchstart' ? e.targetTouches[0].pageY : e.pageY; | ||
isTouched = true; | ||
$prevResizableEl = undefined; | ||
$nextResizableEl = undefined; | ||
isScrolling = undefined; | ||
} | ||
|
||
function handleTouchMove(e) { | ||
if (!isTouched) return; | ||
const isRow = $resizeHandlerEl.parent('.row').length === 1; | ||
const sizeProp = isRow ? 'height' : 'width'; | ||
const getSizeProp = isRow ? 'offsetHeight' : 'offsetWidth'; | ||
if (!isMoved) { | ||
$prevResizableEl = $resizeHandlerEl.parent(isRow ? '.row' : '.col'); | ||
if ( | ||
$prevResizableEl.length && | ||
(!$prevResizableEl.hasClass('resizable') || $prevResizableEl.hasClass('resizable-fixed')) | ||
) { | ||
$prevResizableEl = $prevResizableEl.prevAll('.resizable:not(.resizable-fixed)').eq(0); | ||
} | ||
$nextResizableEl = $prevResizableEl.next(isRow ? '.row' : '.col'); | ||
if ( | ||
$nextResizableEl.length && | ||
(!$nextResizableEl.hasClass('resizable') || $nextResizableEl.hasClass('resizable-fixed')) | ||
) { | ||
$nextResizableEl = $nextResizableEl.nextAll('.resizable:not(.resizable-fixed)').eq(0); | ||
} | ||
|
||
if ($prevResizableEl.length) { | ||
prevElSize = $prevResizableEl[0][getSizeProp]; | ||
prevElMinSize = getElMinSize(sizeProp, $prevResizableEl); | ||
prevElMaxSize = getElMaxSize(sizeProp, $prevResizableEl); | ||
parentSize = $prevResizableEl.parent()[0][getSizeProp]; | ||
itemsInFlow = $prevResizableEl | ||
.parent() | ||
.children(isRow ? '.row' : '[class*="col-"], .col').length; | ||
gapSize = parseFloat($prevResizableEl.css(isRow ? '--f7-grid-row-gap' : '--f7-grid-gap')); | ||
} | ||
if ($nextResizableEl.length) { | ||
nextElSize = $nextResizableEl[0][getSizeProp]; | ||
nextElMinSize = getElMinSize(sizeProp, $nextResizableEl); | ||
nextElMaxSize = getElMaxSize(sizeProp, $nextResizableEl); | ||
if (!$prevResizableEl.length) { | ||
parentSize = $nextResizableEl.parent()[0][getSizeProp]; | ||
itemsInFlow = $nextResizableEl | ||
.parent() | ||
.children(isRow ? '.row' : '[class*="col-"], .col').length; | ||
gapSize = parseFloat( | ||
$nextResizableEl.css(isRow ? '--f7-grid-row-gap' : '--f7-grid-gap'), | ||
); | ||
} | ||
} | ||
} | ||
|
||
isMoved = true; | ||
const touchCurrentX = e.type === 'touchmove' ? e.targetTouches[0].pageX : e.pageX; | ||
const touchCurrentY = e.type === 'touchmove' ? e.targetTouches[0].pageY : e.pageY; | ||
if (typeof isScrolling === 'undefined' && !isRow) { | ||
isScrolling = !!( | ||
isScrolling || | ||
Math.abs(touchCurrentY - touchStartY) > Math.abs(touchCurrentX - touchStartX) | ||
); | ||
} | ||
if (isScrolling) { | ||
isTouched = false; | ||
isMoved = false; | ||
return; | ||
} | ||
|
||
const isAbsolute = | ||
$prevResizableEl.hasClass('resizable-absolute') || | ||
$nextResizableEl.hasClass('resizable-absolute'); | ||
const resizeNextEl = !isRow || (isRow && !isAbsolute); | ||
|
||
if ((resizeNextEl && !$nextResizableEl.length) || !$prevResizableEl.length) { | ||
isTouched = false; | ||
isMoved = false; | ||
return; | ||
} | ||
|
||
e.preventDefault(); | ||
|
||
let diff = isRow ? touchCurrentY - touchStartY : touchCurrentX - touchStartX; | ||
|
||
let prevElNewSize; | ||
let nextElNewSize; | ||
if ($prevResizableEl.length) { | ||
prevElNewSize = prevElSize + diff; | ||
if (prevElNewSize < prevElMinSize) { | ||
prevElNewSize = prevElMinSize; | ||
diff = prevElNewSize - prevElSize; | ||
} | ||
if (prevElMaxSize && prevElNewSize > prevElMaxSize) { | ||
prevElNewSize = prevElMaxSize; | ||
diff = prevElNewSize - prevElSize; | ||
} | ||
} | ||
if ($nextResizableEl.length && resizeNextEl) { | ||
nextElNewSize = nextElSize - diff; | ||
if (nextElNewSize < nextElMinSize) { | ||
nextElNewSize = nextElMinSize; | ||
diff = nextElSize - nextElNewSize; | ||
prevElNewSize = prevElSize + diff; | ||
} | ||
if (nextElMaxSize && nextElNewSize > nextElMaxSize) { | ||
nextElNewSize = nextElMaxSize; | ||
diff = nextElSize - nextElNewSize; | ||
prevElNewSize = prevElSize + diff; | ||
} | ||
} | ||
|
||
if (isAbsolute) { | ||
$prevResizableEl[0].style[sizeProp] = `${prevElNewSize}px`; | ||
if (resizeNextEl) { | ||
$nextResizableEl[0].style[sizeProp] = `${nextElNewSize}px`; | ||
} | ||
$prevResizableEl.trigger('grid:resize'); | ||
$nextResizableEl.trigger('grid:resize'); | ||
app.emit('gridResize', $prevResizableEl[0]); | ||
app.emit('gridResize', $nextResizableEl[0]); | ||
return; | ||
} | ||
|
||
const gapAddSize = ((itemsInFlow - 1) * gapSize) / itemsInFlow; | ||
const gapAddSizeCSS = isRow | ||
? `${itemsInFlow - 1} * var(--f7-grid-row-gap) / ${itemsInFlow}` | ||
: '(var(--f7-cols-per-row) - 1) * var(--f7-grid-gap) / var(--f7-cols-per-row)'; | ||
const prevElNewSizeNormalized = prevElNewSize + gapAddSize; | ||
const nextElNewSizeNormalized = nextElNewSize + gapAddSize; | ||
$prevResizableEl[0].style[sizeProp] = `calc(${ | ||
(prevElNewSizeNormalized / parentSize) * 100 | ||
}% - ${gapAddSizeCSS})`; | ||
$nextResizableEl[0].style[sizeProp] = `calc(${ | ||
(nextElNewSizeNormalized / parentSize) * 100 | ||
}% - ${gapAddSizeCSS})`; | ||
$prevResizableEl.trigger('grid:resize'); | ||
$nextResizableEl.trigger('grid:resize'); | ||
app.emit('gridResize', $prevResizableEl[0]); | ||
app.emit('gridResize', $nextResizableEl[0]); | ||
} | ||
|
||
function handleTouchEnd() { | ||
if (!isTouched) return; | ||
if (!isMoved) { | ||
isTouched = false; | ||
} | ||
isTouched = false; | ||
isMoved = false; | ||
} | ||
const document = getDocument(); | ||
$(document).on( | ||
app.touchEvents.start, | ||
'.col > .resize-handler, .row > .resize-handler', | ||
handleTouchStart, | ||
); | ||
app.on('touchmove', handleTouchMove); | ||
app.on('touchend', handleTouchEnd); | ||
}, | ||
}; | ||
|
||
export default { | ||
name: 'grid', | ||
create() { | ||
const app = this; | ||
extend(app, { | ||
grid: { | ||
init: Grid.init.bind(app), | ||
}, | ||
}); | ||
}, | ||
on: { | ||
init() { | ||
const app = this; | ||
app.grid.init(); | ||
}, | ||
}, | ||
}; |
Oops, something went wrong.