uikit
Version:
UIkit is a lightweight and modular front-end framework for developing fast and powerful web interfaces.
130 lines (93 loc) • 2.87 kB
JavaScript
import {isRtl, isVisible, offsetPosition, toggleClass} from 'uikit-util';
export default {
props: {
margin: String,
firstColumn: Boolean
},
data: {
margin: 'uk-margin-small-top',
firstColumn: 'uk-first-column'
},
update: {
read() {
const rows = getRows(this.$el.children);
return {
rows,
columns: getColumns(rows)
};
},
write({columns, rows}) {
for (let i = 0; i < rows.length; i++) {
for (let j = 0; j < rows[i].length; j++) {
toggleClass(rows[i][j], this.margin, i !== 0);
toggleClass(rows[i][j], this.firstColumn, !!~columns[0].indexOf(rows[i][j]));
}
}
},
events: ['resize']
}
};
export function getRows(items) {
return sortBy(items, 'top', 'bottom');
}
function getColumns(rows) {
const columns = [];
for (let i = 0; i < rows.length; i++) {
const sorted = sortBy(rows[i], 'left', 'right');
for (let j = 0; j < sorted.length; j++) {
columns[j] = !columns[j] ? sorted[j] : columns[j].concat(sorted[j]);
}
}
return isRtl
? columns.reverse()
: columns;
}
function sortBy(items, startProp, endProp) {
const sorted = [[]];
for (let i = 0; i < items.length; i++) {
const el = items[i];
if (!isVisible(el)) {
continue;
}
let dim = getOffset(el);
for (let j = sorted.length - 1; j >= 0; j--) {
const current = sorted[j];
if (!current[0]) {
current.push(el);
break;
}
let startDim;
if (current[0].offsetParent === el.offsetParent) {
startDim = getOffset(current[0]);
} else {
dim = getOffset(el, true);
startDim = getOffset(current[0], true);
}
if (dim[startProp] >= startDim[endProp] - 1 && dim[startProp] !== startDim[startProp]) {
sorted.push([el]);
break;
}
if (dim[endProp] - 1 > startDim[startProp] || dim[startProp] === startDim[startProp]) {
current.push(el);
break;
}
if (j === 0) {
sorted.unshift([el]);
break;
}
}
}
return sorted;
}
function getOffset(element, offset = false) {
let {offsetTop, offsetLeft, offsetHeight, offsetWidth} = element;
if (offset) {
[offsetTop, offsetLeft] = offsetPosition(element);
}
return {
top: offsetTop,
left: offsetLeft,
bottom: offsetTop + offsetHeight,
right: offsetLeft + offsetWidth
};
}