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

This commit is contained in:
Andreas Stöckel 2012-03-07 15:33:21 +00:00
parent 292f18bc1a
commit c0db2e36a9
8 changed files with 54 additions and 143 deletions

View File

@ -584,16 +584,6 @@ function et2_hasChild(_nodes, _child)
return false; 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) * Functions to work with ranges and range intersection (used in the dataview)
*/ */

View File

@ -267,7 +267,7 @@
// Do some tracing of the getMem_freeMem_trace is activated // Do some tracing of the getMem_freeMem_trace is activated
if (getMem_freeMem_trace) if (getMem_freeMem_trace)
{ {
this.__OBJ_UID = "obj_" + et2_uniqueId(); this.__OBJ_UID = "obj_" + egw.uid();
var className = this.className(); var className = this.className();
tracedObjects[this.__OBJ_UID] = { tracedObjects[this.__OBJ_UID] = {
"created": new Date().getTime(), "created": new Date().getTime(),

View File

@ -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;
}

View File

@ -15,10 +15,9 @@
/*egw:uses /*egw:uses
jquery.jquery; jquery.jquery;
et2_core_common; et2_core_common;
et2_core_stylesheet;
et2_dataview_view_grid; 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 * Constructor for the grid container
* @param object _parentNode is the DOM-Node into which the grid view will be inserted * @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 // Copy the arguments
this.parentNode = $j(_parentNode); this.parentNode = $j(_parentNode);
this.dataProvider = _dataProvider; this.dataProvider = _dataProvider;
this.egw = _egw;
// Initialize some variables // Initialize some variables
this.columnNodes = []; // Array with the header containers this.columnNodes = []; // Array with the header containers
@ -67,7 +67,7 @@ var et2_dataview_gridContainer = Class.extend({
this.width = 0; this.width = 0;
this.height = 0; this.height = 0;
this.uniqueId = "gridCont_" + et2_uniqueId(); this.uniqueId = "gridCont_" + this.egw.uid();
// Build the base nodes // Build the base nodes
this._createElements(); this._createElements();
@ -256,9 +256,6 @@ var et2_dataview_gridContainer = Class.extend({
* The columns will be updated. * The columns will be updated.
*/ */
_updateColumns: function() { _updateColumns: function() {
// Get the stylesheet singleton
var styleSheet = new et2_dynStyleSheet();
// Copy the columns data // Copy the columns data
this.columns = this.columnMgr.getColumnData(); this.columns = this.columnMgr.getColumnData();
@ -289,7 +286,7 @@ var et2_dataview_gridContainer = Class.extend({
this.visibleColumnCount++; this.visibleColumnCount++;
// Update the visibility of the column // Update the visibility of the column
styleSheet.updateRule("." + col.tdClass, this.egw.css("." + col.tdClass,
"display: table-cell; " + "display: table-cell; " +
((vis_col == total_cnt) ? "border-right-width: 0 " : "border-right-width: 1px ") + ((vis_col == total_cnt) ? "border-right-width: 0 " : "border-right-width: 1px ") +
"!important;"); "!important;");
@ -327,12 +324,12 @@ var et2_dataview_gridContainer = Class.extend({
// Write the width of the header columns // Write the width of the header columns
var headerWidth = Math.max(0, (col.width - this.headerBorderWidth - subHBorder)); 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;"); "width: " + headerWidth + "px;");
// Write the width of the body-columns // Write the width of the body-columns
var columnWidth = Math.max(0, (col.width - this.columnBorderWidth - subBorder)); 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;"); "width: " + columnWidth + "px;");
totalWidth += col.width; totalWidth += col.width;
@ -341,14 +338,14 @@ var et2_dataview_gridContainer = Class.extend({
} }
else else
{ {
styleSheet.updateRule("." + col.tdClass, "display: none;"); this.egw.css("." + col.tdClass, "display: none;");
} }
} }
// Add the full row and spacer class // 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;"); "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;"); "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 // 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) { if(i < this.columns.length-1) {
var enc_column = self.columnMgr.getColumnById(col.id); 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"); this.set_width(_w + "px");
self.columnMgr.updated = true; self.columnMgr.updated = true;
self.updateColumns(); self.updateColumns();
}, enc_column); }, enc_column);*/
} }
// Store both nodes in the columnNodes array // Store both nodes in the columnNodes array

View File

@ -16,7 +16,8 @@
* This set of functions is currently only supporting resizing in ew-direction * This set of functions is currently only supporting resizing in ew-direction
*/ */
(function() { (function ()
{
// Define some constants // Define some constants
var RESIZE_BORDER = 7; var RESIZE_BORDER = 7;
@ -31,14 +32,9 @@
return (ol > (_elem.outerWidth(true) - RESIZE_BORDER)); return (ol > (_elem.outerWidth(true) - RESIZE_BORDER));
} }
var helper = null;
var overlay = null;
var didResize = false;
var resizeWidth = 0;
function startResize(_outerElem, _elem, _callback) function startResize(_outerElem, _elem, _callback)
{ {
if (overlay == null || helper == null) if (this.overlay == null || this.helper == null)
{ {
// Prevent text selection // Prevent text selection
_elem[0].onselectstart = function() { _elem[0].onselectstart = function() {
@ -46,11 +42,11 @@
} }
// Reset the "didResize" flag // Reset the "didResize" flag
didResize = false; this.didResize = false;
// Create the resize helper // Create the resize helper
var left = _elem.offset().left; var left = _elem.offset().left;
helper = $j(document.createElement("div")) this.helper = $j(document.createElement("div"))
.addClass("egwResizeHelper") .addClass("egwResizeHelper")
.appendTo("body") .appendTo("body")
.css("top", _elem.offset().top + "px") .css("top", _elem.offset().top + "px")
@ -58,7 +54,7 @@
.css("height", _outerElem.outerHeight(true) + "px"); .css("height", _outerElem.outerHeight(true) + "px");
// Create the overlay which will be catching the mouse movements // Create the overlay which will be catching the mouse movements
overlay = $j(document.createElement("div")) this.overlay = $j(document.createElement("div"))
.addClass("egwResizeOverlay") .addClass("egwResizeOverlay")
.bind("mousemove", function(e) { .bind("mousemove", function(e) {
@ -69,7 +65,7 @@
}) })
.bind("mouseup", function() { .bind("mouseup", function() {
stopResize(); stopResize.call();
// Reset text selection // Reset text selection
_elem[0].onselectstart = null; _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 // Get the table surrounding the given element - this element is used to
// align the helper properly // align the helper properly
@ -115,7 +123,7 @@
if (inResizeRegion(e.clientX, _elem)) if (inResizeRegion(e.clientX, _elem))
{ {
// Start the resizing // Start the resizing
startResize(outerTable, _elem, function(_w) { startResize.call(this, outerTable, _elem, function(_w) {
_callback.call(_context, _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 // Remove all events in the ".resize" namespace from the element
_elem.unbind(".resize"); _elem.unbind(".resize");
} }
// Publish the et2_dataview_resizeable class
this.et2_dataview_resizeable = et2_dataview_resizeable;
}
}).call(window); }).call(window);

View File

@ -112,7 +112,7 @@ var et2_nextmatch = et2_DOMWidget.extend(et2_IResizeable, {
// Create the outer grid container // Create the outer grid container
this.dataviewContainer = new et2_dataview_gridContainer(this.div, this.dataviewContainer = new et2_dataview_gridContainer(this.div,
this.dataProvider); this.dataProvider, this.egw());
this.activeFilters = {}; this.activeFilters = {};
}, },

View File

@ -36,15 +36,15 @@ var et2_styles = et2_widget.extend({
this.styleNode = document.createElement("style"); this.styleNode = document.createElement("style");
this.styleNode.setAttribute("type", "text/css"); 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() { destroy: function() {
this._super.apply(this, arguments);
// Remove the style node again and delete any reference to it // Remove the style node again and delete any reference to it
(document.getElementsByTagName("head")[0]).removeChild(this.styleNode); this.head.removeChild(this.styleNode);
this.styleNode = null;
this._super.apply(this, arguments);
}, },
loadContent: function(_content) { loadContent: function(_content) {

View File

@ -154,6 +154,9 @@ etemplate2.prototype._createArrayManagers = function(_data)
*/ */
etemplate2.prototype.load = function(_url, _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 // Asynchronously load the XET file (code below is executed ahead of the
// code in the callback function) // code in the callback function)
et2_loadXMLFromURL(_url, function(_xmldoc) { 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. // Inform the widget tree that it has been successfully loaded.
this.widgetContainer.loadingFinished(); this.widgetContainer.loadingFinished();
// Insert the document fragment to the DOM Container
this.DOMContainer.appendChild(frag);
// Trigger the "resize" event // Trigger the "resize" event
this.resize(); this.resize();
}, this); }, this);
@ -174,7 +180,7 @@ etemplate2.prototype.load = function(_url, _data)
this.widgetContainer = new et2_container(null); this.widgetContainer = new et2_container(null);
this.widgetContainer.setApiInstance(egw(egw.elemWindow(this.DOMContainer))); this.widgetContainer.setApiInstance(egw(egw.elemWindow(this.DOMContainer)));
this.widgetContainer.setInstanceManager(this); this.widgetContainer.setInstanceManager(this);
this.widgetContainer.setParentDOMNode(this.DOMContainer); this.widgetContainer.setParentDOMNode(frag);
// store the id to submit it back to server // store the id to submit it back to server
if(_data) { if(_data) {