/** * EGroupware eTemplate2 - Functions which allow resizing of table headers * * @license http://opensource.org/licenses/gpl-license.php GPL - GNU General Public License * @package etemplate * @subpackage dataview * @link https://www.egroupware.org * @author Andreas Stöckel * @copyright EGroupware GmbH 2011-2021 */ import { egw } from "../jsapi/egw_global"; /** * This set of functions is currently only supporting resizing in ew-direction */ export class et2_dataview_view_resizable { // In resize region returns whether the mouse is currently in the // "resizeRegion" static inResizeRegion(_x, _elem) { var ol = _x - _elem.offset().left; return (ol > (_elem.outerWidth(true) - et2_dataview_view_resizable.RESIZE_BORDER)); } static startResize(_outerElem, _elem, _callback, _column) { if (this.overlay == null || this.helper == null) { // Prevent text selection // FireFox handles highlight prevention (text selection) different than other browsers if (typeof _elem[0].style.MozUserSelect != "undefined") { _elem[0].style.MozUserSelect = "none"; } else { _elem[0].onselectstart = function () { return false; }; } // Indicate resizing is in progress jQuery(_outerElem).addClass('egwResizing'); // Reset the "didResize" flag this.didResize = false; // Create the resize helper var left = _elem.offset().left; this.helper = jQuery(document.createElement("div")) .addClass("egwResizeHelper") .appendTo("body") .css("top", _elem.offset().top + "px") .css("left", left + "px") .css("height", _outerElem.outerHeight(true) + "px"); // Create the overlay which will be catching the mouse movements this.overlay = jQuery(document.createElement("div")) .addClass("egwResizeOverlay") .bind("mousemove", function (e) { this.didResize = true; this.resizeWidth = Math.max(e.pageX - left + et2_dataview_view_resizable.RESIZE_ADD, _column && _column.minWidth ? _column.minWidth : et2_dataview_view_resizable.RESIZE_MIN_WIDTH); this.helper.css("width", this.resizeWidth + "px"); }.bind(this)) .bind("mouseup", function () { this.stopResize(_outerElem); // Reset text selection _elem[0].onselectstart = null; // Call the callback if the user actually performed a resize if (this.didResize) { _callback(this.resizeWidth); } }.bind(this)) .appendTo("body"); } } static stopResize(_outerElem) { jQuery(_outerElem).removeClass('egwResizing'); if (this.helper != null) { this.helper.remove(); this.helper = null; } if (this.overlay != null) { this.overlay.remove(); this.overlay = null; } } } // Define some constants et2_dataview_view_resizable.RESIZE_BORDER = 12; et2_dataview_view_resizable.RESIZE_MIN_WIDTH = 25; et2_dataview_view_resizable.RESIZE_ADD = 2; // Used to ensure mouse is under the resize element after resizing has finished et2_dataview_view_resizable.helper = null; et2_dataview_view_resizable.overlay = null; et2_dataview_view_resizable.didResize = false; et2_dataview_view_resizable.resizeWidth = 0; et2_dataview_view_resizable.makeResizeable = function (_elem, _callback, _context) { // Get the table surrounding the given element - this element is used to // align the helper properly var outerTable = _elem.closest("table"); // Bind the "mousemove" event in the "resize" namespace _elem.bind("mousemove.resize", function (e) { var stopResize = false; // Stop switch to resize cursor if the mouse position // is more intended for scrollbar not the resize edge // 8pixel is an arbitary number for scrolbar area if (e.target.clientHeight < e.target.scrollHeight && e.target.offsetWidth - e.offsetX <= 8) { stopResize = true; } _elem.css("cursor", et2_dataview_view_resizable.inResizeRegion(e.pageX, _elem) && !stopResize ? "ew-resize" : "auto"); }); // Bind the "mousedown" event in the "resize" namespace _elem.bind("mousedown.resize", function (e) { var stopResize = false; // Stop resize if the mouse position is more intended // for scrollbar not the resize edge // 8pixel is an arbitary number for scrolbar area if (e.target.clientHeight < e.target.scrollHeight && e.target.offsetWidth - e.offsetX <= 8) { stopResize = true; } // Do not triger startResize if clicked element is select-tag, as it may causes conflict in some browsers if (et2_dataview_view_resizable.inResizeRegion(e.pageX, _elem) && e.target.tagName != 'SELECT' && !stopResize) { // Start the resizing et2_dataview_view_resizable.startResize(outerTable, _elem, function (_w) { _callback.call(_context, _w); }, _context); } }); // Bind double click for auto-size _elem.dblclick(function (e) { // Just show message for relative width columns if (_context && _context.relativeWidth) { return egw.message(egw.lang('You tried to automatically size a flex column, which always takes the rest of the space', 'info')); } // Find column class - it's usually the first one var col_class = ''; for (var i = 0; i < this.classList.length; i++) { if (this.classList[i].indexOf('gridCont') === 0) { col_class = this.classList[i]; break; } } // Find widest part, including header var column = jQuery(this); column.children().css('width', 'auto'); var max_width = column.children().children().innerWidth(); var padding = column.outerWidth(true) - max_width; var resize = jQuery(this).closest('.egwGridView_outer') .find('tbody td.' + col_class + '> div:first-child') .add(column.children()) // Set column width to auto to allow space for everything to flow .css('width', 'auto'); resize.children() .css({ 'white-space': 'nowrap' }) .each(function () { var col = jQuery(this); // Find visible (text) children and force them to not wrap var children = col.find('span:visible, time:visible, label:visible') .css({ 'white-space': 'nowrap' }); this.offsetWidth; children.each(function () { var child = jQuery(this); this.offsetWidth; if (child.outerWidth() > max_width) { max_width = child.outerWidth(); } window.getComputedStyle(this).width; }); this.offsetWidth; if (col.innerWidth() > max_width) { max_width = col.innerWidth(); } // Reset children children.css('white-space', ''); children.css('display', ''); }) .css({ 'white-space': '' }); // Reset column column.children().css('width', ''); resize.css('width', ''); _callback.call(_context, max_width + padding); }); }; et2_dataview_view_resizable.et2_dataview_resetResizeable = function (_elem) { // Remove all events in the ".resize" namespace from the element _elem.unbind(".resize"); }; //# sourceMappingURL=et2_dataview_view_resizeable.js.map