From fe02eda1a7e2ea8c09f2f1c1df4869dbe2d0617d Mon Sep 17 00:00:00 2001 From: Hadi Nategh Date: Tue, 19 Aug 2014 12:48:22 +0000 Subject: [PATCH 001/318] * Etemplate/Nextmatch: Do not trigger resize event on nextmatch header columns if the clicked element is select-tag, as it may cause conflict between two click and resize handlers in some browsers. - Fix clicking on selectboxes located at nm header causes to resize the column, in FireFox. --- etemplate/js/et2_dataview_view_resizeable.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/etemplate/js/et2_dataview_view_resizeable.js b/etemplate/js/et2_dataview_view_resizeable.js index b7779f4583..83e247207d 100644 --- a/etemplate/js/et2_dataview_view_resizeable.js +++ b/etemplate/js/et2_dataview_view_resizeable.js @@ -112,7 +112,8 @@ // Bind the "mousedown" event in the "resize" namespace _elem.bind("mousedown.resize", function(e) { - if (inResizeRegion(e.pageX, _elem)) + // Do not triger startResize if clicked element is select-tag, as it may causes conflict in some browsers + if (inResizeRegion(e.pageX, _elem) && e.target.tagName != 'SELECT') { // Start the resizing startResize(outerTable, _elem, function(_w) { From 162c08a4575d4915bc77e1aada2ec304fa0d1700 Mon Sep 17 00:00:00 2001 From: Klaus Leithoff Date: Tue, 19 Aug 2014 13:54:04 +0000 Subject: [PATCH 002/318] fix broken move via nm-action-menu-entry --- mail/js/app.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mail/js/app.js b/mail/js/app.js index 2d657753c5..4ac6f12630 100644 --- a/mail/js/app.js +++ b/mail/js/app.js @@ -2773,7 +2773,7 @@ app.classes.mail = AppJS.extend( var key = window.localStorage.key(i); // Find directly by what the key would look like - if(key.indexOf('cached_fetch_mail::{"selectedFolder":"'+_target.id+'"') == 0) + if(key.indexOf('cached_fetch_mail::{"selectedFolder":"'+target+'"') == 0) { window.localStorage.removeItem(key); } From a512c04183d00d255a977b5ff57b564a0efed1dc Mon Sep 17 00:00:00 2001 From: Hadi Nategh Date: Tue, 19 Aug 2014 13:58:35 +0000 Subject: [PATCH 003/318] Fix F.F does not trigger resize nm column onmousedown, but after mouseup --- etemplate/js/et2_dataview_view_resizeable.js | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/etemplate/js/et2_dataview_view_resizeable.js b/etemplate/js/et2_dataview_view_resizeable.js index 83e247207d..d2f5e61e3a 100644 --- a/etemplate/js/et2_dataview_view_resizeable.js +++ b/etemplate/js/et2_dataview_view_resizeable.js @@ -41,9 +41,17 @@ if (overlay == null || helper == null) { // Prevent text selection - _elem[0].onselectstart = function() { - return false; - }; + // 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; + }; + } // Reset the "didResize" flag didResize = false; From cb50632f05fcb9d51dde60a335c2fa99397d8d76 Mon Sep 17 00:00:00 2001 From: Ralf Becker Date: Tue, 19 Aug 2014 14:12:40 +0000 Subject: [PATCH 004/318] * Addressbook: no longer offering to move contacts to accounts addressbook, as we do not support that --- addressbook/inc/class.addressbook_ui.inc.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/addressbook/inc/class.addressbook_ui.inc.php b/addressbook/inc/class.addressbook_ui.inc.php index dc9bf792ca..52289a34e9 100644 --- a/addressbook/inc/class.addressbook_ui.inc.php +++ b/addressbook/inc/class.addressbook_ui.inc.php @@ -496,6 +496,7 @@ class addressbook_ui extends addressbook_bo // move to AB if (($move2addressbooks = $this->get_addressbooks(EGW_ACL_ADD))) // do we have addressbooks, we should { + unset($move2addressbooks[0]); // do not offer action to move contact to an account, as we dont support that currrently foreach($move2addressbooks as $owner => $label) { $this->type_icon((int)$owner, substr($owner,-1) == 'p', 'n', $icon, $type_label); @@ -2066,6 +2067,7 @@ window.egw_LAB.wait(function() { $sel_options['fileas_type'] = $this->fileas_options($content); $sel_options['owner'] = $this->get_addressbooks(EGW_ACL_ADD); + if ($content['owner']) unset($sel_options['owner'][0]); // do not offer to switch to accounts, as we do not support moving contacts to accounts if ((string) $content['owner'] !== '') { if (!isset($sel_options['owner'][(int)$content['owner']])) From e4a80cbfc6bf2f4899b8dbd23050705628f82a3d Mon Sep 17 00:00:00 2001 From: Ralf Becker Date: Tue, 19 Aug 2014 17:15:50 +0000 Subject: [PATCH 005/318] exclude login failures from session list --- admin/inc/class.admin_accesslog.inc.php | 1 + admin/inc/class.admin_ui.inc.php | 2 +- phpgwapi/inc/class.egw_session.inc.php | 10 ++++++---- 3 files changed, 8 insertions(+), 5 deletions(-) diff --git a/admin/inc/class.admin_accesslog.inc.php b/admin/inc/class.admin_accesslog.inc.php index 614102644d..57b7bf97eb 100644 --- a/admin/inc/class.admin_accesslog.inc.php +++ b/admin/inc/class.admin_accesslog.inc.php @@ -68,6 +68,7 @@ class admin_accesslog $query['col_filter']['lo'] = null; // not logged out $query['col_filter'][0] = 'session_dla > '.(int)(time() - $GLOBALS['egw_info']['server']['sessions_timeout']); $query['col_filter'][1] = "(notification_heartbeat IS NULL OR notification_heartbeat > $heartbeat_limit)"; + $query['col_filter'][2] = 'account_id>0'; } $total = $this->so->get_rows($query,$rows,$readonlys); diff --git a/admin/inc/class.admin_ui.inc.php b/admin/inc/class.admin_ui.inc.php index c21ea2ed6b..a53af0c3d2 100644 --- a/admin/inc/class.admin_ui.inc.php +++ b/admin/inc/class.admin_ui.inc.php @@ -225,7 +225,6 @@ class admin_ui $apps = array_unique(array_merge(array('admin'), $GLOBALS['egw']->hooks->hook_implemented('edit_user'))); foreach($apps as $app) { -if ($app == 'felamimail') continue; // disabled fmail for now, as it break whole admin, dono why $GLOBALS['menuData'] = $data = array(); $data = $GLOBALS['egw']->hooks->single('edit_user', $app, true); if (!is_array($data)) $data = $GLOBALS['menuData']; @@ -264,6 +263,7 @@ if ($app == 'felamimail') continue; // disabled fmail for now, as it break whole 'group' => ++$group, 'popup' => '400x200', 'url' => 'menuaction=admin.admin_account.delete&account_id=$id', + 'allowOnMultiple' => false, ); } //error_log(__METHOD__."() actions=".array2string($actions)); diff --git a/phpgwapi/inc/class.egw_session.inc.php b/phpgwapi/inc/class.egw_session.inc.php index 20771e7d13..519d9b7602 100644 --- a/phpgwapi/inc/class.egw_session.inc.php +++ b/phpgwapi/inc/class.egw_session.inc.php @@ -522,7 +522,7 @@ class egw_session // for WebDAV and GroupDAV we use a pseudo sessionid created from md5(user:passwd) // --> allows this stateless protocolls which use basic auth to use sessions! - if ($this->sessionid = self::get_sessionid(true)) + if (($this->sessionid = self::get_sessionid(true))) { $no_session = true; // no need to set cookie session_id($this->sessionid); @@ -577,7 +577,7 @@ class egw_session if ($reason) // called hook requests to deny the session { $this->reason = $this->cd_reason = $reason; - $this->log_access($this->reason,$login,$user_ip,$this->account_id); // log unsuccessfull login + $this->log_access($this->reason,$login,$user_ip,0); // log unsuccessfull login if (self::ERROR_LOG_DEBUG) error_log(__METHOD__."($this->login,$this->passwd,$this->passwd_type,$no_session,$auth_check) UNSUCCESSFULL ($this->reason)"); return false; } @@ -1677,6 +1677,7 @@ class egw_session $order_by = 'session_dla DESC'; } $filter['lo'] = null; + $filter[] = 'account_id>0'; $filter[] = 'session_dla > '.(int)(time() - $GLOBALS['egw_info']['server']['sessions_timeout']); $filter[] = '(notification_heartbeat IS NULL OR notification_heartbeat > '.self::heartbeat_limit().')'; foreach($GLOBALS['egw']->db->select(self::ACCESS_LOG_TABLE, '*', $filter, __LINE__, __FILE__, @@ -1690,12 +1691,13 @@ class egw_session /** * Query number of sessions (not more then once every N secs) * - * @param array $filter=array() extra filter for sessions + * @param array $filter =array() extra filter for sessions * @return int number of active sessions */ public static function session_count(array $filter=array()) { $filter['lo'] = null; + $filter[] = 'account_id>0'; $filter[] = 'session_dla > '.(int)(time() - $GLOBALS['egw_info']['server']['sessions_timeout']); $filter[] = '(notification_heartbeat IS NULL OR notification_heartbeat > '.self::heartbeat_limit().')'; return $GLOBALS['egw']->db->select(self::ACCESS_LOG_TABLE, 'COUNT(*)', $filter, __LINE__, __FILE__)->fetchColumn(); @@ -1708,7 +1710,7 @@ class egw_session */ public static function heartbeat_limit() { - static $limit; + static $limit=null; if (is_null($limit)) { From ec1471c6d2f328aa4a6d4de21514d7941eb2427b Mon Sep 17 00:00:00 2001 From: Nathan Gray Date: Tue, 19 Aug 2014 21:22:26 +0000 Subject: [PATCH 006/318] Another attempt at resolving the browser timezone issue --- .../inc/class.etemplate_widget_date.inc.php | 70 +++++++++++++++---- etemplate/js/et2_widget_date.js | 36 ++++++---- 2 files changed, 79 insertions(+), 27 deletions(-) diff --git a/etemplate/inc/class.etemplate_widget_date.inc.php b/etemplate/inc/class.etemplate_widget_date.inc.php index 46bcc4bc99..68ea86a57a 100644 --- a/etemplate/inc/class.etemplate_widget_date.inc.php +++ b/etemplate/inc/class.etemplate_widget_date.inc.php @@ -30,9 +30,10 @@ * * @todo validation of date-duration * - * @info beforeSendToClient is no longer neccessary, in order to handle date/time conversion, for this widget - * as we are handling both timestamp and string date/time formats on client side - * + * @info Communication between client and server is always done as a string in ISO8601/W3C + * format ("Y-m-d\TH:i:sP"). If the application specifies a different format + * for the field, the conversion is done as needed understand what the application + * sends, and to give the application what it wants when the form is submitted. */ class etemplate_widget_date extends etemplate_widget_transformer { @@ -48,9 +49,48 @@ class etemplate_widget_date extends etemplate_widget_transformer protected $legacy_options = 'dataformat,mode'; + /** + * Convert the provided date into the format needed for unambiguous communication + * with browsers (Javascript). We use W3C format to avoid timestamp issues. + */ + public function beforeSendToClient($cname) + { + if($this->type == 'date-houronly') + { + return parent::beforeSendToClient($cname); + } + + $form_name = self::form_name($cname, $this->id); + $value =& self::get_array(self::$request->content, $form_name, false, true); + + if($this->type != 'date-duration' && $value) + { + // string with formatting letters like for php's date() method + if ($this->attrs['dataformat'] && !is_numeric($value)) + { + $date = date_create_from_format($this->attrs['dataformat'], $value, new DateTimeZone('UTC')); + } + else + { + $date = new egw_time((int)$value, new DateTimeZone('UTC')); + } + if($date) + { + // Set timezone to UTC so javascript doesn't add/subtract anything + $date->setTimezone(new DateTimeZone('UTC')); + $value = $date->format(egw_time::W3C); + } + } + } + /** * Validate input * + * For dates (except duration), it is always a full timestamp in W3C format, + * which we then convert to the format the application is expecting. This can + * be either a unix timestamp, just a date, just time, or whatever is + * specified in the template. + * * @param string $cname current namespace * @param array $expand values for keys 'c', 'row', 'c_', 'row_', 'cont' * @param array $content @@ -65,13 +105,7 @@ class etemplate_widget_date extends etemplate_widget_transformer { $value = self::get_array($content, $form_name); $valid =& self::get_array($validated, $form_name, true); - - // Client / etemplate always deals in 'user time', which has no timezone - // The change to server time is handled elsewhere - // Change to UTC to avoid PHP doing automatic timezone math - $default_tz = date_default_timezone_get(); - date_default_timezone_set('UTC'); - + if ((string)$value === '' && $this->attrs['needed']) { self::set_validation_error($form_name,lang('Field must not be empty !!!')); @@ -84,12 +118,21 @@ class etemplate_widget_date extends etemplate_widget_transformer { $valid = (string)$value === '' ? '' : (int)$value; } + if($value) + { + $date = new egw_time($value); + } + if(!$value) + { + // Not null, blank + $value = ''; + } elseif (empty($this->attrs['dataformat'])) // integer timestamp { - $valid = (int)$value; + $valid = $date->format('ts'); } // string with formatting letters like for php's date() method - elseif (($valid = date($this->attrs['dataformat'], $value))) + elseif (($valid = $date->format($this->attrs['dataformat']))) { // Nothing to do here } @@ -98,8 +141,7 @@ class etemplate_widget_date extends etemplate_widget_transformer // this is not really a user error, but one of the clientside engine self::set_validation_error($form_name,lang("'%1' is not a valid date !!!", $value).' '.$this->dataformat); } - - date_default_timezone_set($default_tz); + //error_log("$this : ($valid)" . egw_time::to($valid)); } } } diff --git a/etemplate/js/et2_widget_date.js b/etemplate/js/et2_widget_date.js index e1dd5321d4..ee4de08b67 100644 --- a/etemplate/js/et2_widget_date.js +++ b/etemplate/js/et2_widget_date.js @@ -23,10 +23,8 @@ /** * Class which implements the "date" XET-Tag * - * Care must be taken anytime a date from the user is parsed. eTemplate client - * side dates are all in 'user time', which is dealt with on the server and has - * no timezone. Javascript uses the browser's timezone, which affects parsing - * and calculations. + * Dates are passed to the server in ISO8601 format ("Y-m-d\TH:i:sP"), and data_format is + * handled server-side. * * @augments et2_inputWidget */ @@ -40,7 +38,7 @@ var et2_date = et2_inputWidget.extend( "ignore": false }, "data_format": { - "ignore": false, + "ignore": true, "description": "Date/Time format. Can be set as an options to date widget", "default": '' } @@ -57,7 +55,7 @@ var et2_date = et2_inputWidget.extend( this._super.apply(this, arguments); this.date = new Date(); - this.date.setHours(0); + this.date.setUTCHours(0); this.date.setMinutes(0); this.date.setSeconds(0); this.input = null; @@ -126,6 +124,11 @@ var et2_date = et2_inputWidget.extend( return; } + // Check for full timestamp + if(typeof _value == 'string' && _value.match(/(\d{4})-(\d{2})-(\d{2})T(\d{2})\:(\d{2})\:(\d{2})[+-](\d{2})\:(\d{2})/)) + { + _value = new Date(_value); + } // Handle just time as a string in the form H:i if(typeof _value == 'string' && isNaN(_value)) { @@ -163,7 +166,7 @@ var et2_date = et2_inputWidget.extend( this.change(this.input_date); } } - this._oldValue = _value; + this._oldValue = this.date.toJSON(); return; default: // Parse customfields's date with storage data_format to date object @@ -189,11 +192,13 @@ var et2_date = et2_inputWidget.extend( this.set_validation_error(this.egw().lang("%1' han an invalid format !!!",_value)); return; } + // These should be the same, but this should clear any offset problems + parsed.setUTCHours(parsed.getHours()); } - // Update local variable, but remove the timezone offset that javascript adds + // Update local variable, but remove the timezone offset that javascript adds by using timestamp if(parsed) { - this.date = new Date(parsed.valueOf() - (parsed.getTimezoneOffset()*60*1000)); + this.date = new Date(parsed.valueOf()); } this.set_validation_error(false); @@ -210,11 +215,11 @@ var et2_date = et2_inputWidget.extend( // Update input - popups do, but framework doesn't _value = ''; + var formatDate = new Date(this.date.valueOf() + this.date.getTimezoneOffset() * 60 * 1000); if(this._type != 'date-timeonly') { _value = jQuery.datepicker.formatDate(this.input_date.datepicker("option","dateFormat"), - // Add timezone offset for datepicker format, or it will lose that many hours - new Date(this.date.valueOf() + (this.date.getTimezoneOffset()*60*1000)) + formatDate ); } if(this._type != 'date') @@ -222,7 +227,7 @@ var et2_date = et2_inputWidget.extend( if(this._type != 'date-timeonly') _value += ' '; _value += jQuery.datepicker.formatTime(this.input_date.datepicker("option","timeFormat"),{ - hour: this.date.getHours(), + hour: this.date.getUTCHours(), minute: this.date.getMinutes(), seconds: 0, timezone: 0 @@ -249,10 +254,15 @@ var et2_date = et2_inputWidget.extend( this.date.setMonth(0); this.date.setFullYear(1970); } + else if (this._type == 'date') + { + this.date.setUTCHours(0); + this.date.setUTCMinutes(0); + } // Convert to timestamp - no seconds this.date.setSeconds(0,0); - return Math.round(this.date.valueOf() / 1000); + return this.date.toJSON(); } }); et2_register_widget(et2_date, ["date", "date-time", "date-timeonly"]); From 28d2fad14a47364d4aad5fd78e761c214a861971 Mon Sep 17 00:00:00 2001 From: Nathan Gray Date: Tue, 19 Aug 2014 23:33:06 +0000 Subject: [PATCH 007/318] * Change nextmatch column size calculations so extra size is allocated better. --- etemplate/js/et2_dataview.js | 6 +- etemplate/js/et2_dataview_model_columns.js | 101 +++++-------------- etemplate/js/et2_dataview_view_resizeable.js | 7 +- etemplate/js/et2_extension_nextmatch.js | 23 ++++- etemplate/js/et2_widget_grid.js | 10 ++ 5 files changed, 65 insertions(+), 82 deletions(-) diff --git a/etemplate/js/et2_dataview.js b/etemplate/js/et2_dataview.js index a3c78c0692..5fbd24001c 100644 --- a/etemplate/js/et2_dataview.js +++ b/etemplate/js/et2_dataview.js @@ -390,9 +390,9 @@ var et2_dataview = Class.extend({ // make column resizable var enc_column = self.columnMgr.getColumnById(col.id); et2_dataview_makeResizeable(column, function(_w) { - this.set_width(this.relativeWidth ? (_w / self.columnMgr.totalWidth * 100) + "%" : _w + "px"); - self.columnMgr.updated = true; - self.updateColumns(); + this.set_width(this.relativeWidth ? (_w / self.columnMgr.totalWidth) : _w + "px"); + self.columnMgr.updated = true; + self.updateColumns(); }, enc_column); // Store both nodes in the columnNodes array diff --git a/etemplate/js/et2_dataview_model_columns.js b/etemplate/js/et2_dataview_model_columns.js index cd29c9fec7..49311e8e3b 100755 --- a/etemplate/js/et2_dataview_model_columns.js +++ b/etemplate/js/et2_dataview_model_columns.js @@ -59,9 +59,15 @@ var et2_dataview_column = ClassWithAttributes.extend({ "width": { "name": "Width", "type": "dimension", - "default": "auto", + "default": "80px", "description": "Width of the column." }, + "minWidth": { + "name": "Minimum width", + "type": "integer", + "default": 50, + "description": "Minimum width of the column, in pixels. Values below this are rejected." + }, "maxWidth": { "name": "Maximum width", "type": "integer", @@ -90,12 +96,16 @@ var et2_dataview_column = ClassWithAttributes.extend({ // 1. "100" => fixedWidth 100px // 2. "100px" => fixedWidth 100px // 3. "50%" => relativeWidth 50% - // 4. "auto" => fixedWidth false, relativeWidth false + // 4. 0.5 => relativeWidth 50% this.relativeWidth = false; this.fixedWidth = false; var w = _value; - if (w.charAt(w.length - 1) == "%" && !isNaN(w.substr(0, w.length - 1))) + if (typeof w == 'number') + { + this.relativeWidth = parseFloat(w.toFixed(3)); + } + else if (w.charAt(w.length - 1) == "%" && !isNaN(w.substr(0, w.length - 1))) { this.relativeWidth = parseInt(w.substr(0, w.length - 1)) / 100; @@ -145,6 +155,7 @@ var et2_dataview_columns = Class.extend({ init: function(_columnData) { // Initialize some variables this.totalWidth = 0; + this.totalFixed = 0; this.columnWidths = []; // Create the columns object @@ -308,9 +319,8 @@ var et2_dataview_columns = Class.extend({ // Calculate how many space is - relatively - not occupied with columns with // relative or fixed width - var remRelWidth = 1; - var fixedTotal = 0; - var noWidthCount = 0; + var totalRelative = 0; + this.totalFixed = 0; for (var i = 0; i < this.columns.length; i++) { @@ -328,72 +338,14 @@ var et2_dataview_columns = Class.extend({ } if (col.relativeWidth) { - remRelWidth -= col.relativeWidth; + totalRelative += col.relativeWidth; } else if (col.fixedWidth) { - fixedTotal += col.fixedWidth; - } - else - { - noWidthCount++; + this.totalFixed += col.fixedWidth; } } } - remRelWidth -= fixedTotal / tw; - - // Check whether the width of columns with relative width is larger than their - // maxWidth - var done; - do - { - done = true; - - var noWidth = remRelWidth / noWidthCount; - - for (var i = 0; i < this.columns.length; i++) - { - var col = this.columns[i]; - - if (col.visibility != ET2_COL_VISIBILITY_INVISIBLE) - { - if (col.maxWidth && !col._larger) - { - if (col.relativeWidth) - { - var w = col.relativeWidth * tw; - col._larger = w > col.maxWidth; - if (col._larger) - { - // Recalculate the remaining relative width: - // col.maxWidth / w is the relative amount of space p which - // is remaining for the element. E.g. an element with - // w = 150px and maxWidth = 100px => p = 2/3 - // The space which got removed is 1 - p => 1/3 - // ==> we have to add 1/3 * oldRelWidth to the remRelWidth - // variable. - remRelWidth += col.relativeWidth * (1 - col.maxWidth / w); - done = false; - break; - } - } - else - { - col._larger = noWidth * tw > col.maxWidth; - if (col._larger) - { - remRelWidth -= col.maxWidth / tw; - noWidthCount--; - done = false; - break; - } - } - } - } - } - // As some columns take their max width, new space might come available, which - // requires other columns to take their maximum width. - } while (!done); // Now calculate the absolute width of the columns in pixels var usedTotal = 0; @@ -414,16 +366,18 @@ var et2_dataview_columns = Class.extend({ } else if (col.relativeWidth) { - w = Math.round(tw * col.relativeWidth); + // Reset relative to an actual percentage (of 1.00) or + // resizing eventually sends them to 0 + col.relativeWidth = col.relativeWidth / totalRelative; + w = Math.round((tw-this.totalFixed) * col.relativeWidth); } - else + if (w > tw || (col.maxWidth && w > col.maxWidth)) { - w = Math.round(tw * (remRelWidth / noWidthCount)); + w = Math.min(tw - usedTotal, col.maxWidth); } - - if (w < 0) + if (w < 0 || w < col.minWidth) { - w = 0; + w = Math.max(0, col.minWidth); } } this.columnWidths.push(w); @@ -468,8 +422,7 @@ var et2_dataview_columns = Class.extend({ } else { - this.columnWidths[columnIndex] -= remaining_width; - column.set_width(column.relativeWidth ? (this.columnWidths[columnIndex] / self.totalWidth * 100) + "%" : this.columnWidths[columnIndex] + "px"); + this.columnWidths[columnIndex] = Math.max(column.minWidth, this.columnWidths[columnIndex] - remaining_width); } } } diff --git a/etemplate/js/et2_dataview_view_resizeable.js b/etemplate/js/et2_dataview_view_resizeable.js index d2f5e61e3a..5067cd857a 100644 --- a/etemplate/js/et2_dataview_view_resizeable.js +++ b/etemplate/js/et2_dataview_view_resizeable.js @@ -36,7 +36,7 @@ var didResize = false; var resizeWidth = 0; - function startResize(_outerElem, _elem, _callback) + function startResize(_outerElem, _elem, _callback, _column) { if (overlay == null || helper == null) { @@ -72,7 +72,8 @@ .bind("mousemove", function(e) { didResize = true; resizeWidth = Math.max(e.pageX - left + RESIZE_ADD, - RESIZE_MIN_WIDTH); + _column && _column.minWidth ? _column.minWidth : RESIZE_MIN_WIDTH + ); helper.css("width", resizeWidth + "px"); }) @@ -126,7 +127,7 @@ // Start the resizing startResize(outerTable, _elem, function(_w) { _callback.call(_context, _w); - }); + }, _context); } }); diff --git a/etemplate/js/et2_extension_nextmatch.js b/etemplate/js/et2_extension_nextmatch.js index 0b81a652bd..42993b3e42 100644 --- a/etemplate/js/et2_extension_nextmatch.js +++ b/etemplate/js/et2_extension_nextmatch.js @@ -803,7 +803,18 @@ var et2_nextmatch = et2_DOMWidget.extend([et2_IResizeable, et2_IInput], var colName = this._getColumnName(_row[i].widget); if(!colName) continue; - if(size[colName]) _colData[i].width = size[colName]; + if(size[colName]) + { + // Make sure percentages stay percentages, and forget any preference otherwise + if(_colData[i].width.charAt(_colData[i].width.length - 1) == "%") + { + _colData[i].width = typeof size[colName] == 'string' && size[colName].charAt(size[colName].length - 1) == "%" ? size[colName] : _colData[i].width; + } + else + { + _colData[i].width = parseInt(size[colName])+'px'; + } + } for(var j = 0; j < columnDisplay.length; j++) { if(columnDisplay[j] == colName) @@ -955,7 +966,15 @@ var et2_nextmatch = et2_DOMWidget.extend([et2_IResizeable, et2_IInput], "visibility": (!_colData[x] || _colData[x].disabled) ? ET2_COL_VISIBILITY_INVISIBLE : ET2_COL_VISIBILITY_VISIBLE, "width": _colData[x] ? _colData[x].width : 0 - }; + } + if(_colData[x].minWidth) + { + columnData[x].minWidth = _colData[x].minWidth; + } + if(_colData[x].maxWidth) + { + columnData[x].maxWidth = _colData[x].maxWidth; + } // No action columns in et2 var colName = this._getColumnName(_row[x].widget); diff --git a/etemplate/js/et2_widget_grid.js b/etemplate/js/et2_widget_grid.js index 4309aaabe3..67c1dc002d 100644 --- a/etemplate/js/et2_widget_grid.js +++ b/etemplate/js/et2_widget_grid.js @@ -180,6 +180,16 @@ var et2_grid = et2_DOMWidget.extend([et2_IDetachedDOM, et2_IAligned], colDataEntry["class"] = et2_readAttrWithDefault(node, "class", ""); colDataEntry["align"] = et2_readAttrWithDefault(node, "align", ""); colDataEntry["span"] = et2_readAttrWithDefault(node, "span", "1"); + + // Keep any others attributes set, there's no 'column' widget + for(var i in node.attributes) + { + var attr = node.attributes[i]; + if(attr.nodeType == 2 && typeof colDataEntry[attr.nodeName] == 'undefined') + { + colDataEntry[attr.nodeName] = attr.value; + } + } } else { From 76e229b7182738f40af43a5e540a50fccb247a8f Mon Sep 17 00:00:00 2001 From: Ralf Becker Date: Wed, 20 Aug 2014 08:24:27 +0000 Subject: [PATCH 008/318] remove unnecessary .useElipsis:after --- mail/templates/default/app.css | 3 --- mail/templates/pixelegg/app.css | 6 +----- 2 files changed, 1 insertion(+), 8 deletions(-) diff --git a/mail/templates/default/app.css b/mail/templates/default/app.css index 346e16a5a4..0118c09ccb 100644 --- a/mail/templates/default/app.css +++ b/mail/templates/default/app.css @@ -280,9 +280,6 @@ pre { overflow: hidden; word-wrap: break-word; float: left; - &:after{ - content: " ..."; - } } #mail-index { position: relative diff --git a/mail/templates/pixelegg/app.css b/mail/templates/pixelegg/app.css index 3da09016db..4f552fcf7e 100755 --- a/mail/templates/pixelegg/app.css +++ b/mail/templates/pixelegg/app.css @@ -276,9 +276,6 @@ pre { word-wrap: break-word; float: left; } -.useEllipsis:after { - content: " ..."; -} #mail-index { position: relative; } @@ -1787,8 +1784,7 @@ div#displayToolbar-menulist img { /*Label*/ } #mail-subscribe table.et2_grid tr td .mail_subscription_header { - font-size: 250%; - line-height: 270%; + /*line-height: 270%;*/ margin: 0.6em 0 0; font-weight: lighter; line-height: 2em; From 091e0aeaf8c37272145f67d2bd7ca310f856b0ec Mon Sep 17 00:00:00 2001 From: Ralf Becker Date: Wed, 20 Aug 2014 09:05:10 +0000 Subject: [PATCH 009/318] setting default width for admin accounts --- admin/templates/default/index.xet | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/admin/templates/default/index.xet b/admin/templates/default/index.xet index b31b5acbf0..d0fa1947d1 100644 --- a/admin/templates/default/index.xet +++ b/admin/templates/default/index.xet @@ -8,15 +8,15 @@