Files
Orchard/src/Orchard.Web/Modules/Orchard.Layouts/Scripts/Models/Row.js
2015-04-19 11:31:53 +02:00

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 = {}));