From c0db2e36a9ed9978cfe32ea6dc170e442fa094be Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20St=C3=B6ckel?= Date: Wed, 7 Mar 2012 15:33:21 +0000 Subject: [PATCH] Fixed a lot of problems regarding centralized JavaScript code; et2_dataview_view_resizeable is current WIP; now building etemplate2 DOM-Tree to a DocumentFragment first, which brings a significant performance gain --- etemplate/js/et2_core_common.js | 10 -- etemplate/js/et2_core_inheritance.js | 2 +- etemplate/js/et2_core_stylesheet.js | 95 ------------------- .../js/et2_dataview_view_gridContainer.js | 27 +++--- etemplate/js/et2_dataview_view_resizeable.js | 41 +++++--- etemplate/js/et2_extension_nextmatch.js | 2 +- etemplate/js/et2_widget_styles.js | 12 +-- etemplate/js/etemplate2.js | 8 +- 8 files changed, 54 insertions(+), 143 deletions(-) delete mode 100644 etemplate/js/et2_core_stylesheet.js diff --git a/etemplate/js/et2_core_common.js b/etemplate/js/et2_core_common.js index a3e3f7ca9e..1c03ec7193 100644 --- a/etemplate/js/et2_core_common.js +++ b/etemplate/js/et2_core_common.js @@ -584,16 +584,6 @@ function et2_hasChild(_nodes, _child) return false; } -/** - * Generates a localy unique id and returns it - */ -var _et2_uniqueId = 0; - -function et2_uniqueId() -{ - return _et2_uniqueId++; -} - /** * Functions to work with ranges and range intersection (used in the dataview) */ diff --git a/etemplate/js/et2_core_inheritance.js b/etemplate/js/et2_core_inheritance.js index 50129a2ffd..a1e8cf10fd 100644 --- a/etemplate/js/et2_core_inheritance.js +++ b/etemplate/js/et2_core_inheritance.js @@ -267,7 +267,7 @@ // Do some tracing of the getMem_freeMem_trace is activated if (getMem_freeMem_trace) { - this.__OBJ_UID = "obj_" + et2_uniqueId(); + this.__OBJ_UID = "obj_" + egw.uid(); var className = this.className(); tracedObjects[this.__OBJ_UID] = { "created": new Date().getTime(), diff --git a/etemplate/js/et2_core_stylesheet.js b/etemplate/js/et2_core_stylesheet.js deleted file mode 100644 index 6791af65e4..0000000000 --- a/etemplate/js/et2_core_stylesheet.js +++ /dev/null @@ -1,95 +0,0 @@ -/** - * eGroupWare eTemplate2 - Stylesheet class - * - * @license http://opensource.org/licenses/gpl-license.php GPL - GNU General Public License - * @package etemplate - * @subpackage api - * @link http://www.egroupware.org - * @author Andreas Stöckel - * @copyright Stylite 2011 - * @version $Id$ - */ - -"use strict" - -/** - * Contains the egwDynStyleSheet class which allows dynamic generation of stylesheet - * rules - updating a single stylesheet rule is way more efficient than updating - * the element style of many objects. - */ -var ET2_DYNAMIC_STYLESHEET = null; - -/** - * Main egwDynStyleSheet class - all egwDynStyleSheets share the same stylesheet - * which is dynamically inserted into the head section of the DOM-Tree. - * This stylesheet is created with the first egwDynStyleSheet class. - */ -function et2_dynStyleSheet() -{ - // Check whether the ET2_DYNAMIC_STYLESHEET has already be created - if (!ET2_DYNAMIC_STYLESHEET) - { - var style = document.createElement("style"); - document.getElementsByTagName("head")[0].appendChild(style); - - this.styleSheet = style.sheet ? style.sheet : style.styleSheet; - this.selectors = {}; - this.selectorCount = 0; - - ET2_DYNAMIC_STYLESHEET = this; - - return this; - } - else - { - return ET2_DYNAMIC_STYLESHEET; - } -} - -/** - * Creates/Updates the given stylesheet rule. Example call: - * - * styleSheet.updateRule("#container", "background-color: blue; font-family: sans;") - * - * @param string _selector is the css selector to which the given rule should apply - * @param string _rule is the rule which is bound to the selector. - */ -et2_dynStyleSheet.prototype.updateRule = function (_selector, _rule) -{ - var ruleObj = { - "index": this.selectorCount - } - - // Remove any existing rule first - if (typeof this.selectors[_selector] !== "undefined") - { - var ruleObj = this.selectors[_selector]; - if (typeof this.styleSheet.removeRule !== "undefined") - { - this.styleSheet.removeRule(ruleObj.index); - } - else - { - this.styleSheet.deleteRule(ruleObj.index); - } - - delete (this.selectors[_selector]); - } - else - { - this.selectorCount++; - } - - // Add the rule to the stylesheet - if (typeof this.styleSheet.addRule !== "undefined") - { - this.styleSheet.addRule(_selector, _rule, ruleObj.index); - } - else - { - this.styleSheet.insertRule(_selector + "{" + _rule + "}", ruleObj.index); - } - - this.selectors[_selector] = ruleObj; -} - diff --git a/etemplate/js/et2_dataview_view_gridContainer.js b/etemplate/js/et2_dataview_view_gridContainer.js index daa6882e2e..3609df8623 100644 --- a/etemplate/js/et2_dataview_view_gridContainer.js +++ b/etemplate/js/et2_dataview_view_gridContainer.js @@ -15,10 +15,9 @@ /*egw:uses jquery.jquery; et2_core_common; - et2_core_stylesheet; et2_dataview_view_grid; - et2_dataview_view_resizeable; +// et2_dataview_view_resizeable; */ /** @@ -50,11 +49,12 @@ var et2_dataview_gridContainer = Class.extend({ * Constructor for the grid container * @param object _parentNode is the DOM-Node into which the grid view will be inserted */ - init: function(_parentNode, _dataProvider) { + init: function(_parentNode, _dataProvider, _egw) { // Copy the arguments this.parentNode = $j(_parentNode); this.dataProvider = _dataProvider; + this.egw = _egw; // Initialize some variables this.columnNodes = []; // Array with the header containers @@ -67,7 +67,7 @@ var et2_dataview_gridContainer = Class.extend({ this.width = 0; this.height = 0; - this.uniqueId = "gridCont_" + et2_uniqueId(); + this.uniqueId = "gridCont_" + this.egw.uid(); // Build the base nodes this._createElements(); @@ -256,9 +256,6 @@ var et2_dataview_gridContainer = Class.extend({ * The columns will be updated. */ _updateColumns: function() { - // Get the stylesheet singleton - var styleSheet = new et2_dynStyleSheet(); - // Copy the columns data this.columns = this.columnMgr.getColumnData(); @@ -289,7 +286,7 @@ var et2_dataview_gridContainer = Class.extend({ this.visibleColumnCount++; // Update the visibility of the column - styleSheet.updateRule("." + col.tdClass, + this.egw.css("." + col.tdClass, "display: table-cell; " + ((vis_col == total_cnt) ? "border-right-width: 0 " : "border-right-width: 1px ") + "!important;"); @@ -327,12 +324,12 @@ var et2_dataview_gridContainer = Class.extend({ // Write the width of the header columns var headerWidth = Math.max(0, (col.width - this.headerBorderWidth - subHBorder)); - styleSheet.updateRule(".egwGridView_outer ." + col.divClass, + this.egw.css(".egwGridView_outer ." + col.divClass, "width: " + headerWidth + "px;"); // Write the width of the body-columns var columnWidth = Math.max(0, (col.width - this.columnBorderWidth - subBorder)); - styleSheet.updateRule(".egwGridView_grid ." + col.divClass, + this.egw.css(".egwGridView_grid ." + col.divClass, "width: " + columnWidth + "px;"); totalWidth += col.width; @@ -341,14 +338,14 @@ var et2_dataview_gridContainer = Class.extend({ } else { - styleSheet.updateRule("." + col.tdClass, "display: none;"); + this.egw.css("." + col.tdClass, "display: none;"); } } // Add the full row and spacer class - styleSheet.updateRule(".egwGridView_grid ." + this.uniqueId + "_div_fullRow", + this.egw.css(".egwGridView_grid ." + this.uniqueId + "_div_fullRow", "width: " + (totalWidth - this.columnBorderWidth - 1) + "px; border-right-width: 0 !important;"); - styleSheet.updateRule(".egwGridView_outer ." + this.uniqueId + "_spacer_fullRow", + this.egw.css(".egwGridView_outer ." + this.uniqueId + "_spacer_fullRow", "width: " + (totalWidth - 1) + "px; border-right-width: 0 !important;"); }, @@ -376,11 +373,11 @@ var et2_dataview_gridContainer = Class.extend({ // Every column but last can be resized // TODO: This won't work as the last column could be hidden if(i < this.columns.length-1) { var enc_column = self.columnMgr.getColumnById(col.id); - et2_dataview_makeResizeable(column, function(_w) { +/* et2_dataview_makeResizeable(column, function(_w) { this.set_width(_w + "px"); self.columnMgr.updated = true; self.updateColumns(); - }, enc_column); + }, enc_column);*/ } // Store both nodes in the columnNodes array diff --git a/etemplate/js/et2_dataview_view_resizeable.js b/etemplate/js/et2_dataview_view_resizeable.js index 55df199076..fcd66fd72b 100644 --- a/etemplate/js/et2_dataview_view_resizeable.js +++ b/etemplate/js/et2_dataview_view_resizeable.js @@ -16,7 +16,8 @@ * This set of functions is currently only supporting resizing in ew-direction */ -(function() { +(function () +{ // Define some constants var RESIZE_BORDER = 7; @@ -31,14 +32,9 @@ return (ol > (_elem.outerWidth(true) - RESIZE_BORDER)); } - var helper = null; - var overlay = null; - var didResize = false; - var resizeWidth = 0; - function startResize(_outerElem, _elem, _callback) { - if (overlay == null || helper == null) + if (this.overlay == null || this.helper == null) { // Prevent text selection _elem[0].onselectstart = function() { @@ -46,11 +42,11 @@ } // Reset the "didResize" flag - didResize = false; + this.didResize = false; // Create the resize helper var left = _elem.offset().left; - helper = $j(document.createElement("div")) + this.helper = $j(document.createElement("div")) .addClass("egwResizeHelper") .appendTo("body") .css("top", _elem.offset().top + "px") @@ -58,7 +54,7 @@ .css("height", _outerElem.outerHeight(true) + "px"); // Create the overlay which will be catching the mouse movements - overlay = $j(document.createElement("div")) + this.overlay = $j(document.createElement("div")) .addClass("egwResizeOverlay") .bind("mousemove", function(e) { @@ -69,7 +65,7 @@ }) .bind("mouseup", function() { - stopResize(); + stopResize.call(); // Reset text selection _elem[0].onselectstart = null; @@ -99,7 +95,19 @@ } } - this.et2_dataview_makeResizeable = function(_elem, _callback, _context) + /** + * Constructor of the et2_dataview_resizeable class. et2_dataview_resizeable + * is instanciated for each dataview grid. + */ + function et2_dataview_resizeable(_body) + { + var helper = null; + var overlay = null; + var didResize = false; + var resizeWidth = 0; + } + + et2_dataview_resizeable.prototype.makeResizeable = function(_elem, _callback, _context) { // Get the table surrounding the given element - this element is used to // align the helper properly @@ -115,7 +123,7 @@ if (inResizeRegion(e.clientX, _elem)) { // Start the resizing - startResize(outerTable, _elem, function(_w) { + startResize.call(this, outerTable, _elem, function(_w) { _callback.call(_context, _w); }); } @@ -124,10 +132,15 @@ }); } - this.et2_dataview_resetResizeable = function(_elem) + et2_dataview_resizeable.prototype.resetResizeable = function(_elem) { // Remove all events in the ".resize" namespace from the element _elem.unbind(".resize"); } + + // Publish the et2_dataview_resizeable class + this.et2_dataview_resizeable = et2_dataview_resizeable; +} + }).call(window); diff --git a/etemplate/js/et2_extension_nextmatch.js b/etemplate/js/et2_extension_nextmatch.js index e6b1533228..52a48edba7 100644 --- a/etemplate/js/et2_extension_nextmatch.js +++ b/etemplate/js/et2_extension_nextmatch.js @@ -112,7 +112,7 @@ var et2_nextmatch = et2_DOMWidget.extend(et2_IResizeable, { // Create the outer grid container this.dataviewContainer = new et2_dataview_gridContainer(this.div, - this.dataProvider); + this.dataProvider, this.egw()); this.activeFilters = {}; }, diff --git a/etemplate/js/et2_widget_styles.js b/etemplate/js/et2_widget_styles.js index 6a2b68b2de..c6dcf6569b 100644 --- a/etemplate/js/et2_widget_styles.js +++ b/etemplate/js/et2_widget_styles.js @@ -35,16 +35,16 @@ var et2_styles = et2_widget.extend({ // Create the style node and append it to the head node this.styleNode = document.createElement("style"); this.styleNode.setAttribute("type", "text/css"); - - (document.getElementsByTagName("head")[0]).appendChild(this.styleNode); + + this.head = this.egw().window.document.getElementsByTagName("head")[0]; + this.head.appendChild(this.styleNode); }, destroy: function() { - this._super.apply(this, arguments); - // Remove the style node again and delete any reference to it - (document.getElementsByTagName("head")[0]).removeChild(this.styleNode); - this.styleNode = null; + this.head.removeChild(this.styleNode); + + this._super.apply(this, arguments); }, loadContent: function(_content) { diff --git a/etemplate/js/etemplate2.js b/etemplate/js/etemplate2.js index 709c78b052..7444e5d1f5 100644 --- a/etemplate/js/etemplate2.js +++ b/etemplate/js/etemplate2.js @@ -154,6 +154,9 @@ etemplate2.prototype._createArrayManagers = function(_data) */ etemplate2.prototype.load = function(_url, _data) { + // Create the document fragment into which the HTML will be injected + var frag = document.createDocumentFragment(); + // Asynchronously load the XET file (code below is executed ahead of the // code in the callback function) et2_loadXMLFromURL(_url, function(_xmldoc) { @@ -163,6 +166,9 @@ etemplate2.prototype.load = function(_url, _data) // Inform the widget tree that it has been successfully loaded. this.widgetContainer.loadingFinished(); + // Insert the document fragment to the DOM Container + this.DOMContainer.appendChild(frag); + // Trigger the "resize" event this.resize(); }, this); @@ -174,7 +180,7 @@ etemplate2.prototype.load = function(_url, _data) this.widgetContainer = new et2_container(null); this.widgetContainer.setApiInstance(egw(egw.elemWindow(this.DOMContainer))); this.widgetContainer.setInstanceManager(this); - this.widgetContainer.setParentDOMNode(this.DOMContainer); + this.widgetContainer.setParentDOMNode(frag); // store the id to submit it back to server if(_data) {