framework7
Version:
Full featured mobile HTML framework for building iOS & Android apps
223 lines (187 loc) • 7.63 kB
JavaScript
import { getDocument } from 'ssr-window';
import $ from '../../shared/dom7';
import { extend } from '../../shared/utils';
function getElMinSize(dimension, $el) {
var 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) {
var 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;
}
var Grid = {
init: function init() {
var app = this;
var isTouched;
var isMoved;
var touchStartX;
var touchStartY;
var $resizeHandlerEl;
var $prevResizableEl;
var $nextResizableEl;
var prevElSize;
var prevElMinSize;
var prevElMaxSize;
var nextElSize;
var nextElMinSize;
var nextElMaxSize;
var parentSize;
var itemsInFlow;
var gapSize;
var 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;
var isRow = $resizeHandlerEl.parent('.row').length === 1;
var sizeProp = isRow ? 'height' : 'width';
var 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;
var touchCurrentX = e.type === 'touchmove' ? e.targetTouches[0].pageX : e.pageX;
var 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;
}
var isAbsolute = $prevResizableEl.hasClass('resizable-absolute') || $nextResizableEl.hasClass('resizable-absolute');
var resizeNextEl = !isRow || isRow && !isAbsolute;
if (resizeNextEl && !$nextResizableEl.length || !$prevResizableEl.length) {
isTouched = false;
isMoved = false;
return;
}
e.preventDefault();
var diff = isRow ? touchCurrentY - touchStartY : touchCurrentX - touchStartX;
var prevElNewSize;
var 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;
}
var gapAddSize = (itemsInFlow - 1) * gapSize / itemsInFlow;
var 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)';
var prevElNewSizeNormalized = prevElNewSize + gapAddSize;
var 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;
}
var 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: function create() {
var app = this;
extend(app, {
grid: {
init: Grid.init.bind(app)
}
});
},
on: {
init: function init() {
var app = this;
app.grid.init();
}
}
};