/*
* Copyright 2024 Anyware Services
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* An automatic columns layout
*/
Ext.define('Ametys.plugins.cms.search.EnhancedColumnsLayout', {
extend: "Ext.layout.container.Anchor",
alias: 'layout.enhancedcolumns',
innerCtCls: /*Ext.layout.container.Auto.prototype.innerCtCls (firefox does not support the display: table-cell of this class with the columns-count property) +*/ ' enhanced-columns-layout',
/**
* @config {Number} minColWidth=100 The minimal column width
*/
minColWidth: 100,
/**
* @config {Function} ignoreItem A function to test if an item will not be displayed and should ignored. This is usefull since we do not use items heights but just count them.
* @config {Function} ignoreItem.item The item to test
* @config {Function} ignoreItem.returns true if the item should be ignored
*/
/**
* @private
* @property {Number} _nbColumns The number of columns
*/
_nbColumns: 1,
_computeColumns: function()
{
let width = this.owner.getWidth();
if (this._lastWidth != width
|| !this.owner.body.first().first().dom.style.columnCount)
{
this._lastWidth = width;
this._nbColumns = Math.max(1, Math.floor(width / this.minColWidth));
let colWidth = Math.floor(1000 / this._nbColumns) / 10;
this.owner.items.each(function(item) { item.anchor = colWidth + '%'; });
this.owner.items.each(function(item) { item.updateLayout(); }); // required otherwise at loading sometime we will stay on 1 column
this.owner.body.first().first().dom.style.columnCount = this._nbColumns;
}
},
calculateItems: function(ownerContext, containerSize) {
let v = this.callParent(arguments);
let target = this.getRenderTarget();
// Add missing columns
let startingCols = target.query(":scope > *.col");
for (let i = 0; i < this._nbColumns - startingCols.length; i++)
{
target.createChild({ tag: "div", cls: "col" });
}
let finalCols = target.query(":scope > *.col");
let items = this.getLayoutItems();
// Move items in the right column
let ignoredItems = 0;
let ignoreItem = this.getInitialConfig('ignoreItem');
let positions = [];
finalCols.forEach(c => positions.push(0));
for (let i = 0; i < items.length; i++)
{
let item = items[i];
if (ignoreItem && ignoreItem(item))
{
ignoredItems++;
continue;
}
let targetCol = finalCols[(i - ignoredItems) % this._nbColumns];
if (!this._isValidParent(item.getEl().parent().dom, targetCol, positions[targetCol]))
{
this.moveItem(item, targetCol, positions[targetCol]);
}
positions[targetCol]++;
}
// Remove unused (empty) columns
for (let i = finalCols.length; i > this._nbColumns; i--)
{
finalCols[i - 1].remove();
}
return v;
},
_isValidParent: function(item, target, position) {
if (item != target)
{
return false;
}
else if (position === undefined)
{
return true;
}
else
{
return target.childNodes[position] == item;
}
},
isValidParent: function(item, target, position) {
return true
},
calculateContentSize: function(ownerContext)
{
this._computeColumns();
this.callParent(arguments);
}
});