mirror of
https://github.com/OrchardCMS/Orchard.git
synced 2025-10-15 19:54:57 +08:00
286 lines
10 KiB
JavaScript
286 lines
10 KiB
JavaScript
var LayoutEditor;
|
|
(function (LayoutEditor) {
|
|
|
|
LayoutEditor.Row = function (data, htmlId, htmlClass, htmlStyle, isTemplated, rule, children) {
|
|
LayoutEditor.Element.call(this, "Row", data, htmlId, htmlClass, htmlStyle, isTemplated, rule);
|
|
LayoutEditor.Container.call(this, ["Column"], children);
|
|
|
|
var _self = this;
|
|
|
|
function _getTotalColumnsWidth() {
|
|
return _(_self.children).reduce(function (memo, child) {
|
|
return memo + child.offset + child.width;
|
|
}, 0);
|
|
}
|
|
|
|
// Implements a simple algorithm to distribute space (either positive or negative)
|
|
// between the child columns of the row. Negative space is distributed when making
|
|
// room for a new column (e.c. clipboard paste or dropping from the toolbox) while
|
|
// positive space is distributed when filling the grap of a removed column.
|
|
function _distributeSpace(space) {
|
|
if (space == 0)
|
|
return true;
|
|
|
|
var undistributedSpace = space;
|
|
|
|
if (undistributedSpace < 0) {
|
|
var vacantSpace = 12 - _getTotalColumnsWidth();
|
|
undistributedSpace += vacantSpace;
|
|
if (undistributedSpace > 0)
|
|
undistributedSpace = 0;
|
|
}
|
|
|
|
// If space is negative, try to decrease offsets first.
|
|
while (undistributedSpace < 0 && _(_self.children).any(function (column) { return column.offset > 0; })) { // While there is still offset left to remove.
|
|
for (i = 0; i < _self.children.length && undistributedSpace < 0; i++) {
|
|
var column = _self.children[i];
|
|
if (column.offset > 0) {
|
|
column.offset--;
|
|
undistributedSpace++;
|
|
}
|
|
}
|
|
}
|
|
|
|
function hasWidth(column) {
|
|
if (undistributedSpace > 0)
|
|
return column.width < 12;
|
|
else if (undistributedSpace < 0)
|
|
return column.width > 1;
|
|
return false;
|
|
}
|
|
|
|
// Try to distribute remaining space (could be negative or positive) using widths.
|
|
while (undistributedSpace != 0) {
|
|
// Any more column width available for distribution?
|
|
if (!_(_self.children).any(hasWidth))
|
|
break;
|
|
for (i = 0; i < _self.children.length && undistributedSpace != 0; i++) {
|
|
var column = _self.children[i % _self.children.length];
|
|
if (hasWidth(column)) {
|
|
var delta = undistributedSpace / Math.abs(undistributedSpace);
|
|
column.width += delta;
|
|
undistributedSpace -= delta;
|
|
}
|
|
}
|
|
}
|
|
|
|
return undistributedSpace == 0;
|
|
}
|
|
|
|
var _isAddingColumn = false;
|
|
|
|
this.canAddColumn = function () {
|
|
return this.children.length < 12;
|
|
};
|
|
|
|
this.beginAddColumn = function (newColumnWidth) {
|
|
if (!!_isAddingColumn)
|
|
throw new Error("Column add operation is already in progress.")
|
|
_(this.children).each(function (column) {
|
|
column.beginChange();
|
|
});
|
|
if (_distributeSpace(-newColumnWidth)) {
|
|
_isAddingColumn = true;
|
|
return true;
|
|
}
|
|
_(this.children).each(function (column) {
|
|
column.rollbackChange();
|
|
});
|
|
return false;
|
|
};
|
|
|
|
this.commitAddColumn = function () {
|
|
if (!_isAddingColumn)
|
|
throw new Error("No column add operation in progress.")
|
|
_(this.children).each(function (column) {
|
|
column.commitChange();
|
|
});
|
|
_isAddingColumn = false;
|
|
};
|
|
|
|
this.rollbackAddColumn = function () {
|
|
if (!_isAddingColumn)
|
|
throw new Error("No column add operation in progress.")
|
|
_(this.children).each(function (column) {
|
|
column.rollbackChange();
|
|
});
|
|
_isAddingColumn = false;
|
|
};
|
|
|
|
var _baseDeleteChild = this.deleteChild;
|
|
this.deleteChild = function (column) {
|
|
var width = column.width;
|
|
_baseDeleteChild.call(this, column);
|
|
_distributeSpace(width);
|
|
};
|
|
|
|
this.canContractColumnRight = function (column, connectAdjacent) {
|
|
var index = _(this.children).indexOf(column);
|
|
if (index >= 0)
|
|
return column.width > 1;
|
|
return false;
|
|
};
|
|
|
|
this.contractColumnRight = function (column, connectAdjacent) {
|
|
if (!this.canContractColumnRight(column, connectAdjacent))
|
|
return;
|
|
|
|
var index = _(this.children).indexOf(column);
|
|
if (index >= 0) {
|
|
if (column.width > 1) {
|
|
column.width--;
|
|
if (this.children.length > index + 1) {
|
|
var nextColumn = this.children[index + 1];
|
|
if (connectAdjacent && nextColumn.offset == 0)
|
|
nextColumn.width++;
|
|
else
|
|
nextColumn.offset++;
|
|
}
|
|
}
|
|
}
|
|
};
|
|
|
|
this.canExpandColumnRight = function (column, connectAdjacent) {
|
|
var index = _(this.children).indexOf(column);
|
|
if (index >= 0) {
|
|
if (column.width >= 12)
|
|
return false;
|
|
if (this.children.length > index + 1) {
|
|
var nextColumn = this.children[index + 1];
|
|
if (connectAdjacent && nextColumn.offset == 0)
|
|
return nextColumn.width > 1;
|
|
else
|
|
return nextColumn.offset > 0;
|
|
}
|
|
return _getTotalColumnsWidth() < 12;
|
|
}
|
|
return false;
|
|
};
|
|
|
|
this.expandColumnRight = function (column, connectAdjacent) {
|
|
if (!this.canExpandColumnRight(column, connectAdjacent))
|
|
return;
|
|
|
|
var index = _(this.children).indexOf(column);
|
|
if (index >= 0) {
|
|
if (this.children.length > index + 1) {
|
|
var nextColumn = this.children[index + 1];
|
|
if (connectAdjacent && nextColumn.offset == 0)
|
|
nextColumn.width--;
|
|
else
|
|
nextColumn.offset--;
|
|
}
|
|
column.width++;
|
|
}
|
|
};
|
|
|
|
this.canExpandColumnLeft = function (column, connectAdjacent) {
|
|
var index = _(this.children).indexOf(column);
|
|
if (index >= 0) {
|
|
if (column.width >= 12)
|
|
return false;
|
|
if (index > 0) {
|
|
var prevColumn = this.children[index - 1];
|
|
if (connectAdjacent && column.offset == 0)
|
|
return prevColumn.width > 1;
|
|
}
|
|
return column.offset > 0;
|
|
}
|
|
return false;
|
|
};
|
|
|
|
this.expandColumnLeft = function (column, connectAdjacent) {
|
|
if (!this.canExpandColumnLeft(column, connectAdjacent))
|
|
return;
|
|
|
|
var index = _(this.children).indexOf(column);
|
|
if (index >= 0) {
|
|
if (index > 0) {
|
|
var prevColumn = this.children[index - 1];
|
|
if (connectAdjacent && column.offset == 0)
|
|
prevColumn.width--;
|
|
else
|
|
column.offset--;
|
|
}
|
|
else
|
|
column.offset--;
|
|
column.width++;
|
|
}
|
|
};
|
|
|
|
this.canContractColumnLeft = function (column, connectAdjacent) {
|
|
var index = _(this.children).indexOf(column);
|
|
if (index >= 0)
|
|
return column.width > 1;
|
|
return false;
|
|
};
|
|
|
|
this.contractColumnLeft = function (column, connectAdjacent) {
|
|
if (!this.canContractColumnLeft(column, connectAdjacent))
|
|
return;
|
|
|
|
var index = _(this.children).indexOf(column);
|
|
if (index >= 0) {
|
|
if (index > 0) {
|
|
var prevColumn = this.children[index - 1];
|
|
if (connectAdjacent && column.offset == 0)
|
|
prevColumn.width++;
|
|
else
|
|
column.offset++;
|
|
}
|
|
else
|
|
column.offset++;
|
|
column.width--;
|
|
}
|
|
};
|
|
|
|
this.evenColumns = function () {
|
|
if (this.children.length == 0)
|
|
return;
|
|
|
|
var evenWidth = Math.floor(12 / this.children.length);
|
|
_(this.children).each(function (column) {
|
|
column.width = evenWidth;
|
|
column.offset = 0;
|
|
});
|
|
|
|
var rest = 12 % this.children.length;
|
|
if (rest > 0)
|
|
_distributeSpace(rest);
|
|
};
|
|
|
|
var _basePasteChild = this.pasteChild;
|
|
this.pasteChild = function (child) {
|
|
if (child.type == "Column") {
|
|
if (this.beginAddColumn(child.width)) {
|
|
this.commitAddColumn();
|
|
_basePasteChild.call(this, child)
|
|
}
|
|
}
|
|
else if (!!this.parent)
|
|
this.parent.pasteChild(child);
|
|
}
|
|
|
|
this.toObject = function () {
|
|
var result = this.elementToObject();
|
|
result.children = this.childrenToObject();
|
|
return result;
|
|
};
|
|
};
|
|
|
|
LayoutEditor.Row.from = function (value) {
|
|
var result = new LayoutEditor.Row(
|
|
value.data,
|
|
value.htmlId,
|
|
value.htmlClass,
|
|
value.htmlStyle,
|
|
value.isTemplated,
|
|
value.rule,
|
|
LayoutEditor.childrenFrom(value.children));
|
|
result.toolboxIcon = value.toolboxIcon;
|
|
result.toolboxLabel = value.toolboxLabel;
|
|
result.toolboxDescription = value.toolboxDescription;
|
|
return result;
|
|
};
|
|
|
|
})(LayoutEditor || (LayoutEditor = {})); |