sbis3-node-ws
Version:
Модуль позволяет использовать ядро интерфейсного фреймворка sbis3-ws(`core.js`) и модуль работы с данными (`Source.js`) в приложении на nodejs.
1,406 lines (1,158 loc) • 44.9 kB
JavaScript
/**
* DivTable layout engine.
* @author smirnovdm
*/
define('Core/dt_layout', function() {
(function ($){
'use strict';
$.dtLayoutEngine = true;
$.dtPostFilter = function (options){
if (!options)
options = {};
var filters = $.dtPostFilter.filters, i, ln;
if (filters === undefined){
dt_JS_VAlignFilter(options);
dt_JS_HAlignFilter(options);
} else {
for (i = 0, ln = filters.length; i < ln; i++) {
filters[i].apply(options);
}
}
};
var getClasses_rclass = /[\n\t\r]/g,
isHidden_rclass = /\bws-hidden\b/g;
function getClasses(element) {
return (" " + element.className + " ").replace(getClasses_rclass, " ");
}
function memoize0(obj, func, cachedFuncName) {
return function() {
var res = func.call(obj);
obj[cachedFuncName] = function() { return res; };
return res;
};
}
// вызывать только для auto-sized элементов
$.fn.getNativeWidth = function fn_getNativeWidth (){
var element = this[0],
classes = getClasses(element);
if (classes.indexOf(' ws-art-rectangle ') !== -1 ||
classes.indexOf(' ws-art-border ') !== -1) {
return 0;
}
var nativeWidth = 0;
if (classes.indexOf(' ws-labeled-control ') !== -1) {// отдельная обработка контрола с меткой
var ctrl = this.find('[wscontrol="true"]');
if (ctrl.length === 1) {
ctrl = ctrl.wsControl();
nativeWidth = ctrl._isContainerInsideParent() ? ctrl.getMinWidth() : 0;
}
} else if (element.getAttribute('HorizontalAlignment') !== 'Stretch') {
// TODO можно ли это сделать классами? Сперва накатить класс, потом снять
var oldStyles = {
'position': this.css('position'),
'float': 'none',
'white-space': this.css('white-space'),
'width': ''
};
var style = {
'float':'left',
'position':'static',
'width':'auto',
'white-space':'nowrap'
};
this.css(style);
nativeWidth = this.width();
this.css(oldStyles);
}
var margins = element.getAttribute('alignmargin');
if (margins !== null) {
margins = margins.split(',');
nativeWidth += ((parseInt(margins[3], 10) + parseInt(margins[1], 10)) || 0);
}
return nativeWidth;
};
// вызывать только для auto-sized элементов
$.fn.getNativeHeight = function fn_getNativeHeight (){
var element = this[0],
classes = getClasses(element);
if (classes.indexOf(' ws-art-rectangle ') !== -1 ||
classes.indexOf(' ws-art-border ') !== -1) {
return 0;
}
var nativeHeight = 0;
if (classes.indexOf(' ws-labeled-control ') !== -1) {// отдельная обработка контрола с меткой
var ctrl = this.find('[wscontrol="true"]');
if (ctrl.length === 1) {
ctrl = ctrl.wsControl();
nativeHeight = ctrl._isContainerInsideParent() ? ctrl.getMinHeight() : 0;
}
} else if (element.getAttribute('VerticalAlignment') !== 'Stretch') {
var oldStyles = {
'position': this.css('position'),
'float': 'none',
'white-space': this.css('white-space'),
'width': ''
};
var style = {
'float':'left',
'position':'static',
'width':'auto',
'white-space':'nowrap'
};
this.css(style);
nativeHeight = this.height();
this.css(oldStyles);
}
var margins = element.getAttribute('alignmargin');
if (margins !== null) {
margins = margins.split(',');
nativeHeight += ((parseInt(margins[0], 10) + parseInt(margins[2], 10)) || 0);
}
return nativeHeight;
};
function dt_JS_VAlignFilter(options) {
var selector = '.dt_verticalCenter,.dt_grid[verticalalignment="Stretch"],.dt_layout[verticalalignment="Stretch"]',
elements = options.dom !== undefined ? $(options.dom).find(selector) : $(selector),
i, ln = elements.length;
for (i = 0; i < ln; i++ ) {
var element = elements[i],
jqElement,
classes = getClasses(element),
margin, isAbsolute;
if (element.getAttribute('wscontrol') !== 'true' &&
(classes.indexOf(' dt_grid ') !== -1 || classes.indexOf(' dt_layout ') !== -1))
{
jqElement = $(element);
var maxSize = parseInt(jqElement.css('max-height'), 10);
if (!isNaN(maxSize)) {
isAbsolute = jqElement.css('position') === 'absolute';
var parentHeight = jqElement.parent().outerHeight(),
tPos = '', tbMargin,
cssParam = isAbsolute ? 'margin-top' : 'padding-top';
margin = element.getAttribute('alignMargin');
if (margin !== null) {
margin = margin.split(',');
tbMargin = (parseInt(margin[0], 10) + parseInt(margin[2], 10)) || 0;
}
else
tbMargin = 0;
if ((parentHeight - tbMargin) > maxSize)
tPos = Math.round((parentHeight - tbMargin - jqElement.outerHeight()) / 2);
jqElement.css(cssParam, tPos);
}
} else if (classes.indexOf(' dt_verticalCenter ') !== -1) {
jqElement = $(element);
jqElement.css('bottom', 'auto');
isAbsolute = jqElement.css('position') === 'absolute';
var cssData = { 'top': '50%'},
cssProperty = isAbsolute ? 'margin-top' : 'padding-top',
containerHeight = jqElement.outerHeight();
margin = element.getAttribute('alignMargin');
if (margin !== null) {
margin = margin.split(',');
containerHeight -= Math.round(parseInt(margin[0], 10) || 0); // top
containerHeight += Math.round(parseInt(margin[2], 10) || 0); // bottom
}
cssData[cssProperty] = -Math.round((containerHeight) / 2);
jqElement.css(cssData);
}
}
}
function dt_JS_HAlignFilter(options){
var selector = '.dt_horizontalCenter,.dt_grid[horizontalalignment="Stretch"],.dt_layout[horizontalalignment="Stretch"]',
elements = options.dom !== undefined ? $(options.dom).find(selector) : $(selector),
i, ln = elements.length;
for (i = 0; i < ln; i++ ) {
var element = elements[i],
jqElement, classes = getClasses(element),
margin,
isAbsolute;
if (element.getAttribute('wscontrol') !== 'true' &&
(classes.indexOf(' dt_grid ') !== -1 || classes.indexOf(' dt_layout ') !== -1))
{
jqElement = $(element);
var maxSize = parseInt(jqElement.css('max-width'), 10);
if (!isNaN(maxSize))
{
isAbsolute = jqElement.css('position') === 'absolute';
var parentWidth = jqElement.parent().outerWidth(),
tPos = '', cssParam = isAbsolute ? 'margin-left' : 'padding-left', lrMargin;
margin = element.getAttribute('alignMargin');
if (margin !== null) {
margin = margin.split(',');
lrMargin = (parseInt(margin[1], 10) + parseInt(margin[3], 10)) || 0;
}
else
lrMargin = 0;
if ((parentWidth - lrMargin) > maxSize)
tPos = Math.round((parentWidth - lrMargin - jqElement.outerWidth()) / 2);
jqElement.css(cssParam, tPos);
}
} else if (classes.indexOf(' dt_horizontalCenter ') !== -1) {
jqElement = $(element);
isAbsolute = jqElement.css('position') === 'absolute';
if (isAbsolute) {
jqElement.css('right', 'auto');
var nativeWidth = jqElement.outerWidth();
margin = element.getAttribute('alignMargin');
if (margin !== null) {
margin = margin.split(',');
nativeWidth -= (parseInt(margin[3], 10) || 0); // left
nativeWidth += (parseInt(margin[1], 10) || 0); // right
}
var marginLeft = - Math.round((nativeWidth) / 2);
jqElement.css('margin-left', marginLeft);
jqElement.css('left', '50%');
}
}
}
}
/**
* @constructor
*/
function dt_Container(owner, config){
var dom, domEl, domElClassList, domStyle;
dom = owner.getContainer();
domEl = dom[0];
domElClassList = domEl.classList,
domStyle = domEl.style;
var isElHidden = domElClassList !== void(0) ?
function () { return domElClassList.contains('ws-hidden'); } :
function () { return isHidden_rclass.test(domEl.className); } ;
function getDomWidth() {
var offsetWidth = domEl.offsetWidth;
if (offsetWidth === 0) {
//Хак: иногда пересчёт глючит даже на видимом элементе, надо его заставить сработать...
if (!isElHidden()) {
var oldVis = domStyle.visibility;
domStyle.visibility = 'hidden';
offsetWidth = domEl.offsetWidth;
domStyle.visibility = oldVis;
}
}
return offsetWidth - this.getPaddingBorderWidth();
}
function getDomHeight() { return domEl.offsetHeight; } //offsetHeight - потому что там раньше был outerHeight() - а он такой же (кроме случая с невидимостью)
var result = {
getPaddingBorderWidth: null,
getMargin: function(name) {
var margins,
wsMargin = dom.attr('alignMargin');
if (wsMargin) {
wsMargin = wsMargin.split(',');
margins = {top: parseInt(wsMargin[0], 10) || 0,
right: parseInt(wsMargin[1], 10) || 0,
bottom: parseInt(wsMargin[2], 10) || 0,
left: parseInt(wsMargin[3], 10) || 0};
} else
margins = {top: 0, right: 0, bottom: 0, left: 0};
this.getMargin = function(name) { return margins[name]; };
return margins[name];
},
reset: function() {
this.getFixedWidth = memoize0(this, this._getFixedWidth, 'getFixedWidth');
this.getFixedHeight = memoize0(this, this._getFixedHeight, 'getFixedHeight');
this.getWidth = memoize0(this, this._getWidth, 'getWidth');
this.getHeight = memoize0(this, this._getHeight, 'getHeight');
this._getDomWidth = memoize0(this, getDomWidth, '_getDomWidth');
this._getDomHeight = memoize0(this, getDomHeight, '_getDomHeight');
this.isFixedWidth = memoize0(this, this._isFixedWidth, 'isFixedWidth');
this.isFixedHeight = memoize0(this, this._isFixedHeight, 'isFixedHeight');
},
resetResizer: function() {
this.getResizerHeight = memoize0(this, this._getResizerHeight, 'getResizerHeight');
},
_getDomWidth: null,
_getDomHeight: null,
getFixedWidth: null,
_getFixedWidth: function() {
var fixedWidth = null;
if (dom.hasClass('dt_fixedWidth')) {
if (owner) {
fixedWidth = owner._getFixedWidth();
}
else {
fixedWidth = this._getDomWidth();
}
}
return fixedWidth;
},
getFixedHeight: null,
_getFixedHeight: function() {
var fixedHeight = null;
if (dom.hasClass('dt_fixedHeight')) {
if (owner) {
fixedHeight = owner._getFixedHeight();
}
else {
fixedHeight = this._getDomHeight();
}
}
return fixedHeight;
},
Dom: dom,
getWidth: null,
_getWidth: function() {
var width = this.getFixedWidth();
if (width) {
return width;
}
if(!owner || owner.getAlignment().horizontalAlignment === "Stretch"){
// Ширина на полную
// При stretch по родителю можно сразу брать размер контейнера
return this._getDomWidth();
}
// Автоширина
// Возвращается 0, чтобы посчитать авторазмеры:
// fixedsize ячейки останутся fixed
// autosize - встанут по контенту
// starsize - схлопнется до 0
return 0;
},
getResizerHeight: null,
_getResizerHeight: function() {
var resizer = owner && owner.getResizer();
return resizer && $ws.helpers.getElementCachedDim(resizer, 'height');
},
getHeight: null,
_getHeight: function() {
var height = this.getFixedHeight();
if (height) {
return height;
}
if(!owner || owner.getAlignment().verticalAlignment === "Stretch"){
// Высота на полную
return this._getDomHeight();
}
return 0;
},
_isFixedHeight: function() {
return !!this.getFixedHeight();
},
isFixedHeight: null,
_isFixedWidth: function() {
return !!this.getFixedWidth();
},
isFixedWidth: null
};
result.getPaddingBorderWidth = memoize0(result, function() {
return (parseFloat( dom.css("paddingLeft") ) || 0) +
(parseFloat( dom.css("paddingRight") ) || 0) +
(parseFloat( dom.css("borderLeftWidth" ) ) || 0) +
(parseFloat( dom.css("borderRightWidth" ) ) || 0);
}, 'getPaddingBorderWidth');
return result;
}
/**
* @constructor
*/
function dt_Layout(config){
var
_rows,
_cellsNameHash,
layoutApi,
rowCache = {},
colCache = {},
rowCount = config.getRowCount(),
colCount = config.getColCount(),
container = config.getContainer(),
strategy = config.getStrategy(),
columnControlWidths = new Array(colCount),
rowControlHeights = new Array(rowCount);
var getCells = function() {
var configs = config.getCellsConfigs(),
i, ln, c, cfg, _cells;
_cells = []; _rows = {}; _cellsNameHash = {};
for (i = 0, ln = configs.length; i < ln; i++) {
cfg = configs[i];
c = new dt_Cell(cfg, layoutApi);
_cells.push(c);
if (_rows[cfg.top] === undefined)
_rows[cfg.top] = [];
_rows[cfg.top].push(c);
_cellsNameHash[cfg.name] = c;
}
getCells = function() { return _cells; };
return _cells;
};
var getRows = function() {
if (_rows === undefined)
getCells();
var i, cln, j, row, cell, found;
for (i in _rows) {
if (!_rows.hasOwnProperty(i))
continue;
row = _rows[i];
found = false;
for (j = 0, cln = row.length; j < cln; j++) {
cell = row[j];
row.haveControlsWithHeightDependsOnWidth = found = cell.haveControlsWithHeightDependsOnWidth();
if (found)
break;
}
}
getRows = function() { return _rows; };
return _rows;
};
function settingWidth(){
var rows = getRows(),
containerWidth = container.getWidth(),
realWidths = strategy.getWidthValues(layoutApi, columnControlWidths);
for (var rowNum = 0; rowNum < rowCount; rowNum++) {
var thisRow = rows[rowNum];
for (var i = 0, l = thisRow.length; i < l; i++) {
var cell = thisRow[i];
var cellConfig = cell.Config;
var realWidth = 0;
for (var left = cellConfig.left, l2 = cellConfig.right; left <= l2; left++) {
realWidth += realWidths[left];
}
cell.setWidth(realWidth);
var leftPosition = (cellConfig.left > 0 ) ? cell.getLeftSibling().RightPosition : 0;
cell.setLeftPosition(leftPosition);
}
}
return containerWidth;
}
function settingHeight(){
// Массив минимальных высот из конфига
var realHeights = strategy.getHeightValues(layoutApi, rowControlHeights),
cells = getCells();
var i, l;
for (i = 0, l = cells.length; i < l; i++) {
var cell = cells[i],
cellHeight = 0,
cellConfig = cell.Config,
t, l2;
for (t = cellConfig.top, l2 = cellConfig.bottom; t <= l2; t++){
cellHeight += realHeights[t];
}
cell.setHeight(cellHeight);
}
}
function settingTop() {
var rows = getRows();
// Пройдем по каждой строке
for (var rowNum = 0; rowNum < rowCount; rowNum++) {
var thisRow = rows[rowNum];
// Для каждой строки возьмем ее ячейки
for (var i = 0, l = thisRow.length; i < l; i++){
var aCell = thisRow[i];
// Получим ближайших соседей по вертикали вниз
var downSiblings = aCell.getDownSiblings();
if (downSiblings) {
var y = aCell.YCoordinate, // top текущей ячейки
cellHeight = aCell.Height; // высота текущей ячейки
// пройдем по всем соседям снизу
for (var j = 0, len = downSiblings.length; j < len; j++){
// отодвинем ее нужное расстояние
downSiblings[j].setYCoordinate(y + cellHeight);
}
}
if (aCell.YCoordinate === 0)
aCell.Dom.removeClass('dt_notopborder');
else
aCell.Dom.addClass('dt_notopborder');
if (aCell.LeftPosition === 0)
aCell.Dom.removeClass('dt_noleftborder');
else
aCell.Dom.addClass('dt_noleftborder');
}
}
}
function reset(options) {
layoutApi.getMaxHeight = memoize0(layoutApi, layoutApi._getMaxHeight, 'getMaxHeight');
if (!options || !options.resetDependentHeightsOnly)
layoutApi.getMaxWidth = memoize0(layoutApi, layoutApi._getMaxWidth, 'getMaxWidth');
}
function resetControls(options) {
var i, ln, rows, result;
if (options.resetDependentHeightsOnly) {
result = false;
rows = getRows();
for (i = 0, ln = rowCount; i < ln; i++) {
if (rows[i].haveControlsWithHeightDependsOnWidth) {
result = true;
rowControlHeights[i] = void(0);
}
}
} else {
for (i = 0, ln = colCount; i < ln; i++)
columnControlWidths[i] = void(0);
for (i = 0, ln = rowCount; i < ln; i++)
rowControlHeights[i] = void(0);
result = true;
}
return result;
}
function _reset(options) {
var res, result = false;
if (options === undefined)
options = {resetControls: true, resetContainer: true, resetResizer: true};
if (options.resetControls || options.resetContainer || options.resetResizer) {
reset(options);
if (options.resetContainer) {
result = true;
container.reset();
}
if (options.resetResizer) {
result = true;
container.resetResizer();
}
if (options.resetControls) {
res = resetControls(options);
result = res || result;
}
}
return result;
}
function _refresh(options) {
var cells, i, ln, changed = false;
_reset(options);
cells = getCells();
settingWidth();
for (i = 0, ln = cells.length; i < ln; i++) {
if (cells[i].draw({width: true, left: true}))
changed = true;
}
settingHeight();
settingTop();
for (i = 0, ln = cells.length; i < ln; i++) {
if (cells[i].draw({top: true, height: true}))
changed = true;
}
return changed;
}
layoutApi = {
getRowCells: function(rowNum) {
if (rowCache[rowNum] === undefined) {
var cells = getCells(),
i, ln, res = [], cfg;
for (i = 0, ln = cells.length; i < ln; i++) {
cfg = cells[i].Config;
if (cfg.top === rowNum && cfg.rowspan === 1)
res.push(cells[i]);
}
rowCache[rowNum] = res;
}
return rowCache[rowNum];
},
getColCells: function(colNum) {
if (colCache[colNum] === undefined) {
var cells = getCells(),
i, ln, res = [], cfg;
for (i = 0, ln = cells.length; i < ln; i++) {
cfg = cells[i].Config;
if (cfg.left === colNum && cfg.colspan === 1)
res.push(cells[i]);
}
colCache[colNum] = res;
}
return colCache[colNum];
},
getConfig: function() {
return config;
},
getCellByName: function(name) {
if (_cellsNameHash === undefined)
getCells();
this.getCellByName = function(name) { return _cellsNameHash[name]; };
return _cellsNameHash[name];
},
refresh: _refresh,
reset: _reset,
getContainer: function() {
return container;
},
applyFilters: function() { },
getMaxWidth: null,
_getMaxWidth: function() {
var width;
// fixed Width
if((width = container.getFixedWidth()) !== null){
return width;
}
// auto Width
var realWidths = strategy.getWidthValues(layoutApi, columnControlWidths, true), i, ln;
width = 0;
for(i = 0, ln = realWidths.length; i < ln; i++){
width += realWidths[i];
}
return width;
},
getMaxHeight: null,
_getMaxHeight: function () {
var height;
// fixed Height
if((height = container.getFixedHeight()) !== null){
return height;
}
// auto Height
var realHeights = strategy.getHeightValues(layoutApi, rowControlHeights, true);
height = 0;
for (var i = 0, ln = realHeights.length; i < ln; i++) {
height += realHeights[i];
}
return height;
}
};
container.Dom.data('divTable', layoutApi);
return layoutApi;
}
/**
* Получить высоту для ячеек
* @param {Array} elements массив объектов dt_cell
* @returns {Array} массив с вычисленными высотами ячеек
*/
dt_Layout.getElementsHeight = function (elements){
var maxSize = 0;
for(var i = 0, l = elements.length; i < l; i++){
var height = elements[i].getNativeHeight();
if(height > maxSize){
maxSize = height;
}
}
return maxSize;
};
/**
* Получить ширину для ячеек
* @param {Array} elements массив объектов dt_cell
* @returns array массив с вычисленными ширинами ячеек
*/
dt_Layout.getElementsWidth = function (elements){
var maxSize = 0;
for(var i = 0, l = elements.length; i < l; i++) {
var width = elements[i].getNativeWidth();
if(width > maxSize){
maxSize = width;
}
}
return maxSize;
};
/**
* @constructor
*/
function dt_Cell(config, parent) {
var _width = 0, _height = 0,
_leftPx = 0, _topPx = 0,
empty = config.empty,
controls = [],
parentConfig = parent.getConfig(),
parentRowCount = parentConfig.getRowCount(),
parentDisplay = parentConfig.getDisplay(),
currentDimen = { top: false, left: false, width: false, height: false },
nonControlsInCell = [],
borderDeltaX = 0, borderDeltaY = 0, dom, id;
if (!empty) {
dom = config.dom;
id = dom[0].id;
nonControlsInCell = dom.children($ws.helpers.NON_CTRL);
controls = parentConfig.getControls()[id] || controls;
}
if (config['addClass']) {
dom.addClass(config['addClass']);
}
return {
haveControlsWithHeightDependsOnWidth: function() {
return !!$ws.helpers.find(controls, function(control) {
return (control._horizontalAlignment === 'Stretch') &&
control._isHeightDependentOnWidth();
});
},
draw: function dt_Cell_Draw(params){
if (empty) {
this.draw = function() { return false; };
return false;
}
var val, changes = false, updateCss = {};
if (params['width'] === true) {
val = _width - borderDeltaX;
if (val < 0)
val = 0;
if (currentDimen['width'] !== val) {
currentDimen['width'] = val;
updateCss['width'] = val;
changes = true;
}
}
if (params['height'] === true) {
val = _height - borderDeltaY;
if (val < 0)
val = 0;
if (currentDimen['height'] !== val) {
currentDimen['height'] = val;
updateCss['height'] = val;
changes = true;
}
}
if (params['left'] === true) {
if (currentDimen['left'] !== _leftPx) {
currentDimen['left'] = _leftPx;
updateCss['left'] = _leftPx;
changes = true;
}
}
if (params['top'] === true) {
if (currentDimen['top'] !== _topPx) {
currentDimen['top'] = _topPx;
updateCss['top'] = _topPx;
changes = true;
}
}
if (changes) {
dom.css(updateCss);
}
return changes;
},
getNativeHeight: function (){
if (empty) {
this.getNativeHeight = function() { return undefined; };
return undefined;
}
// getting controls in the cell
var minHeight = 0, i, ln, h;
for (i = 0, ln = controls.length; i < ln; i++) {
h = controls[i]._isContainerInsideParent() ? controls[i].getMinHeight() : 0;
if (h > minHeight) {
minHeight = h;
}
}
h = $ws.helpers.getNonControlSize(nonControlsInCell, 'Height');
if (h > minHeight){
minHeight = h;
}
return minHeight;
},
getNativeWidth: function () {
if (empty) {
this.getNativeWidth = function() { return undefined; };
return undefined;
}
// getting controls in the cell
var minWidth = 0, i, ln, w;
for (i = 0, ln = controls.length; i < ln; i++) {
w = controls[i]._isContainerInsideParent() ? controls[i].getMinWidth() : 0;
if (w > minWidth) {
minWidth = w;
}
}
w = $ws.helpers.getNonControlSize(nonControlsInCell, 'Width');
if (w > minWidth) {
minWidth = w;
}
return minWidth;
},
Config: config,
setWidth: function (width){
_width = width;
this.RightPosition = _leftPx + _width;
},
Height: _height,
setHeight: function (height){
_height = height;
this.Height = height;
},
setLeftPosition: function (left){
_leftPx = left;
this.LeftPosition = left;
this.RightPosition = _leftPx + _width;
},
RightPosition: _leftPx,
getLeftSibling: function () {
if(config['left'] === 0){
this.getLeftSibling = function() { return null; };
return null;
}
var leftSiblingName = parent.getConfig().getDisplay()[config.top][config.left - 1],
myLeftSibling = parent.getCellByName(leftSiblingName);
this.getLeftSibling = function() { return myLeftSibling; };
return myLeftSibling;
},
getDownSiblings: function (){
var siblings = [],
cfgBottom = config.bottom;
for(var l = config.left, len = config.right; l <= len; l++) {
if(cfgBottom != parentRowCount - 1){
var offset = 1;
do {
var downSiblingName = parentDisplay[config.top + offset][l];
offset++;
} while(downSiblingName === config.name);
siblings.push(parent.getCellByName(downSiblingName));
}
}
this.getDownSiblings = function() { return siblings; };
return siblings;
},
setYCoordinate: function (y){
_topPx = y;
this.YCoordinate = y;
},
YCoordinate: _topPx,
Dom: dom
};
}
/**
* Обертка для конфига
* @constructor
* @param config
*/
function dt_Config(owner, config){
var display = config.display,
rowCount = display.length,
colCount = display[0].length,
innerConfig = config.config;
if (innerConfig === undefined)
innerConfig = config.config = {columns: [], minSizes: {}, strategy: 'general'};
else {
if (innerConfig.columns === undefined)
innerConfig.columns = [];
if (innerConfig.minSizes === undefined)
innerConfig.minSizes = {};
if (innerConfig.strategy === undefined)
innerConfig.strategy = 'general';
}
if (config.rows === undefined){
config.rows = [];
}
if (config.columns === undefined){
config.columns = [];
}
if (config.minSizes === undefined)
config.minSizes = {};
if (config.minSizes['rows'] === undefined){
config.minSizes['rows'] = [];
}
if (config.minSizes['columns'] === 'undefined'){
config.minSizes['columns'] = [];
}
var rows = config.rows,
columns = config.columns,
minSizes = config.minSizes,
minSizesRows = minSizes.rows,
minSizesCols = minSizes.columns,
strategy, i;
// Преобразуем строки в массив
for (i = 0; i < rowCount; i++){
if (rows[i] === undefined)
rows[i] = '1*';
if (minSizesRows[i] === undefined)
minSizesRows[i] = 0;
}
for (i = 0; i < colCount; i++){
if (columns[i] === undefined)
columns[i] = '1*';
if (minSizesCols[i] === undefined)
minSizesCols[i] = 0;
}
if (innerConfig.strategy === 'general') {
strategy = new GeneralStrategy();
} else {
throw "Strategy " + innerConfig.strategy + " is not supported now";
}
var container = new dt_Container(owner, config);
return {
getDisplay:function (){
return display;
},
getCellsConfigs: function dt_Config_getCellsConfigs(){
var parentDom = container.Dom,
cells = [],
alreadyThere = [],
cellConfig,
emptiesNum = -1,
rowNum, colNum, name;
for (rowNum = 0; rowNum < rowCount; rowNum++) {
for (colNum = 0; colNum < colCount; colNum++) {
name = display[rowNum][colNum];
if (name !== 0) {
if (alreadyThere[name] === undefined) {
alreadyThere[name] = true;
cellConfig = {
name: name,
left: colNum,
top: rowNum,
id: config.cells[name]['id'],
dom: $(config.cells[name]['id'], parentDom)
};
var right = colNum;
var bottom = rowNum;
var bLine = display[bottom];
while (bLine[right] !== undefined && bLine[right] === name) {
right++;
}
cellConfig.right = --right;
right = colNum;
while (display[bottom] !== undefined && display[bottom][right] === name) {
bottom++;
}
cellConfig.bottom = --bottom;
cellConfig.colspan = cellConfig.right - cellConfig.left + 1;
cellConfig.rowspan = cellConfig.bottom - cellConfig.top + 1;
var addClass = '';
if(cellConfig.left !== 0){
addClass += 'dt_noleftborder';
}
if(cellConfig.top !== 0){
addClass += ' dt_notopborder';
}
cellConfig.addClass = addClass;
cells.push(cellConfig);
}
} else{
cellConfig = { empty: true, name: emptiesNum + '', left: colNum, top: rowNum,
right: colNum, bottom: rowNum, colspan: 1, rowspan: 1 };
display[rowNum][colNum] = cellConfig.name;
emptiesNum--;
cells.push(cellConfig);
}
}
}
this.getCellsConfigs = function() { return cells };
return cells;
},
getStrategy: function (){
return strategy;
},
getContainer: function (){
return container;
},
getRowsConfig: function (){
return rows;
},
getColumnsConfig: function (){
return columns;
},
getRowCount: function (){
return rowCount;
},
getColCount: function (){
return colCount;
},
getControls: function dt_Config_getControls(){
var cellControls = {};
if(owner && owner.getImmediateChildControls){
var allControls = owner.getImmediateChildControls(),
controlsCount = allControls.length;
for(i = 0; i < controlsCount; i++){
var cell = allControls[i].getContainer().parent().closest('.dt_cell, .dt_layout');
if(cell.hasClass('dt_cell')) {
var cell_id = cell[0].id;
if(!cellControls[cell_id]){
cellControls[cell_id] = [];
}
cellControls[cell_id].push(allControls[i]);
}
}
}
this.getControls = function() { return cellControls; };
return cellControls;
},
getOwner: function (){
return owner;
},
getMinSizesConfig: function() {
return minSizes;
}
}
}
/**
* Класс GeneralNumber. Формат result = param * R + delta;
* @param param
* @param delta
*/
function GeneralNumber(param, delta){
var isFixed = param === 0;
return {
delta: delta,
param: param,
isLiquid: !isFixed,
isAuto: (isFixed && delta === 0),
toSimple: (isFixed ? delta : param * 100 + '%') };
}
/**
*
* @param ar массив. пример:
* '50',
* '40%',
* '60%',
* '100'
*/
GeneralNumber.arrayToGenerals = function (ar){
var params = [],
generalParams = [],
totalFixed = 0,
totalPercent = 0,
i, l1, param, val, isPercent,
genPercent, delta;
for (i = 0, l1 = ar.length; i < l1; i++) {
params[i] = {};
param = params[i];
val = ar[i];
if (typeof(val) === 'string') {
isPercent = (val.charAt(val.length - 1) === '%');
} else {
isPercent = false;
}
param.isPercent = isPercent;
if (isPercent) {
totalPercent += (param['value'] = parseFloat(val));
} else {
totalFixed += (param['value'] = val);
}
}
for (i = 0, l1 = params.length; i < l1; i++) {
param = params[i];
if (param.isPercent) {
// 100% totalPercent
// x
// percentValue param['value']
genPercent = param['value'] / totalPercent;
delta = -(totalFixed * genPercent);
generalParams.push(new GeneralNumber(genPercent, delta));
} else {
generalParams.push(new GeneralNumber(0, param['value']));
}
}
return generalParams;
};
GeneralNumber.parseGeneral = function (ar){
if(ar instanceof Array){
return new GeneralNumber(ar[0], ar[1]);
} else {
throw "GeneralNumber.parseGeneral: cannot parse!";
}
};
function GeneralStrategy() {
}
GeneralStrategy.prototype.getHeightValues = function GeneralStrategy_getHeightValues (dt_layout, rowControlHeights, calcMinSize){
var dtlConfig = dt_layout.getConfig(),
configArray = dtlConfig.getRowsConfig(),
values = [],
simples = [],
fixedSimples = [],
container = dt_layout.getContainer(),
totalSize = container.getHeight(),
minHeights = dtlConfig.getMinSizesConfig().rows,
dtlOwner = dtlConfig.getOwner(),
liquidAsElements = calcMinSize || (!container.isFixedHeight() &&
dtlOwner.getAlignment().verticalAlignment !== "Stretch"),
doJob, step, i, l1, gen, resizerHeight;
if (!container.isFixedHeight()) {
resizerHeight = container.getResizerHeight();
if (resizerHeight)
totalSize = Math.max(totalSize, resizerHeight);
}
var minHeight = dtlOwner._options.minHeight;
if (totalSize < minHeight) {
totalSize = minHeight;
}
function getRowHeight(i) {
var res = rowControlHeights[i];
if (res === void(0))
res = rowControlHeights[i] = dt_Layout.getElementsHeight(dt_layout.getRowCells(i));
return res;
}
doJob = true; step = 0;
while (doJob && step++ < 10) {
doJob = false;
// auto
for (i = 0, l1 = configArray.length; i < l1; i++) {
if (fixedSimples[i] !== undefined) {
simples[i] = fixedSimples[i];
} else {
gen = GeneralNumber.parseGeneral(configArray[i]);
if (gen.isAuto) {
// находим высоту строки с auto
simples[i] = getRowHeight(i);
} else { // Fixed or StarSize
if (gen.isLiquid && liquidAsElements) {
simples[i] = getRowHeight(i);
} else{
simples[i] = gen.toSimple;
}
}
}
}
var newGenerals = GeneralNumber.arrayToGenerals(simples);
for (i = 0, l1 = newGenerals.length; i < l1; i++) {
gen = newGenerals[i];
values[i] = gen.isLiquid ? Math.floor(totalSize * gen.param + gen.delta) : gen.delta;
var minHeight2 = minHeights[i];
if(values[i] < minHeight2){
fixedSimples[i] = minHeight2;
doJob = true;
}
}
}
return values;
};
GeneralStrategy.prototype.getWidthValues = function GeneralStrategy_getWidthValues (dt_layout, colControlWidths, calcMinSize){
var dtlConfig = dt_layout.getConfig(),
configArray = dtlConfig.getColumnsConfig(),
values = [],
simples = [],
fixedSimples = [],
container = dt_layout.getContainer(),
totalSize = container.getWidth(),
minWidths = dtlConfig.getMinSizesConfig()['columns'],
dtlOwner = dtlConfig.getOwner(),
minWidth = dtlOwner._options.minWidth,
liquidAsElements = calcMinSize || (!container.isFixedWidth() &&
dtlOwner.getAlignment().horizontalAlignment !== "Stretch"),
doJob, step, i, l1, gen, newGenerals;
// получить минимальную ширину
if (totalSize < minWidth) {
totalSize = minWidth;
}
function getColWidth(i) {
var res = colControlWidths[i];
if (res === void(0))
res = colControlWidths[i] = dt_Layout.getElementsWidth(dt_layout.getColCells(i));
return res;
}
doJob = true;
step = 0;
while (doJob && step++ < 10) {
doJob = false;
// auto
for (i = 0, l1 = configArray.length; i < l1; i++) {
if (fixedSimples[i] !== undefined){
simples[i] = fixedSimples[i];
} else {
gen = GeneralNumber.parseGeneral(configArray[i]);
if (gen.isAuto) {// AutoSize
simples[i] = getColWidth(i);
} else { // Fixed or StarSize
if (gen.isLiquid && liquidAsElements) {
simples[i] = getColWidth(i);
} else{
simples[i] = gen.toSimple;
}
}
}
}
newGenerals = GeneralNumber.arrayToGenerals(simples);
for (i = 0, l1 = newGenerals.length; i < l1; i++) {
gen = newGenerals[i];
values[i] = gen.isLiquid ? Math.floor(totalSize * gen.param + gen.delta) : gen.delta;
if (values[i] < minWidths[i]) {
fixedSimples[i] = minWidths[i];
doJob = true;
}
}
}
return values;
};
$.doTable = function DT_doTable (owner, config){
if (config.firstRender === undefined)
config.firstRender = true;
var dtConfig = new dt_Config(owner, config);
var dtLayout = new dt_Layout(dtConfig);
if (config.firstRender)
dtLayout.refresh();
else
dtLayout.reset();
};
})(jQuery);
});