diff --git a/api/js/etemplate/et2_widget_timestamper.js b/api/js/etemplate/et2_widget_timestamper.js new file mode 100644 index 0000000000..5016a7c87a --- /dev/null +++ b/api/js/etemplate/et2_widget_timestamper.js @@ -0,0 +1,168 @@ +/** + * EGroupware eTemplate2 - JS Timestamp button object + * + * @license http://opensource.org/licenses/gpl-license.php GPL - GNU General Public License + * @package etemplate + * @subpackage api + * @link http://www.egroupware.org + * @author Nathan Gray + * @copyright Nathan Gray 2017 + */ + +/*egw:uses + et2_button; +*/ + +/** + * Class which implements the "button-timestamper" XET-Tag + * + * Clicking the button puts the current time and current user at the end of + * the provided field. + * + * @augments et2_button + */ +var et2_timestamper = (function(){ "use strict"; return et2_button.extend([], +{ + attributes: { + target: { + name: "Target field", + type: "string", + default: et2_no_init, + description: "Which field to place the timestamp in" + }, + image: { + default: "timestamp" + }, + background_image: { + default: true + } + }, + + /** + * Constructor + * + * @memberOf et2_button + */ + init: function() { + this._super.apply(this, arguments); + }, + + /** + * Overwritten to maintain an internal clicked attribute + * + * @param _ev + * @returns {Boolean} + */ + click: function(_ev) { + // ignore click on readonly button + if (this.options.readonly) return false; + + this._insert_text(); + + if (!this._super.apply(this, arguments)) + { + return false; + } + + return true; + }, + + _insert_text: function() { + var text = ""; + var now = new Date(); + text += date(egw.preference('dateformat') + ' ' + (egw.preference("timeformat") === "12" ? "h:ia" : "H:i")+' ',now); + + // Get properly formatted user name + var user = parseInt(egw.user('account_id')); + var accounts = egw.accounts('accounts'); + for(var j = 0; j < accounts.length; j++) + { + if(accounts[j].value === user) + { + text += accounts[j].label; + break; + } + } + text += ': '; + + var input = this._get_input(this.target); + var scrollPos = input.scrollTop; + var browser = ((input.selectionStart || input.selectionStart == "0") ? + "standards" : (document.selection ? "ie" : false ) ); + + var pos = 0; + + // Find cursor or selection + if (browser == "ie") + { + input.focus(); + var range = document.selection.createRange(); + range.moveStart ("character", -input.value.length); + pos = range.text.length; + } + else if (browser == "standards") + { + pos = input.selectionStart; + }; + + // Insert the text + var front = (input.value).substring(0, pos); + var back = (input.value).substring(pos, input.value.length); + input.value = front+text+back; + + // If CKEDitor, update it + if(CKEDITOR && CKEDITOR.instances[input.id]) + { + window.setTimeout(function() { + CKEDITOR.instances[input.id].focus(); + }, 10); + } + else + { + // Clean up a little + pos = pos + text.length; + if (browser == "ie") { + input.focus(); + var range = document.selection.createRange(); + range.moveStart ("character", -input.value.length); + range.moveStart ("character", pos); + range.moveEnd ("character", 0); + range.select(); + } + else if (browser == "standards") { + input.selectionStart = pos; + input.selectionEnd = pos; + input.focus(); + } + input.scrollTop = scrollPos; + } + }, + + _get_input: function _get_input(target) + { + var input = null; + var widget = null; + if(jQuery('#'+this.target).is('input')) + { + input = this.target; + } + else if (typeof target == 'string') + { + var widget = this.getRoot().getWidgetById(target); + } + else if (target.instanceOf && target.instanceOf(et2_IInput)) + { + widget = target; + } + if(widget) + { + input = widget.input ? widget.input : widget.getDOMNode(); + } + if(input.context) + { + input = input.get(0); + } + return input; + } +});}).call(this); +et2_register_widget(et2_timestamper, ["button-timestamp", "timestamper"]); \ No newline at end of file diff --git a/api/js/etemplate/etemplate2.js b/api/js/etemplate/etemplate2.js index 28d45a1103..67efe9088f 100644 --- a/api/js/etemplate/etemplate2.js +++ b/api/js/etemplate/etemplate2.js @@ -38,6 +38,7 @@ et2_widget_htmlarea; et2_widget_tabs; et2_widget_taglist; + et2_widget_timestamper; et2_widget_toolbar; et2_widget_tree; et2_widget_historylog; diff --git a/api/templates/default/images/timestamp.png b/api/templates/default/images/timestamp.png new file mode 100644 index 0000000000..864811b6be Binary files /dev/null and b/api/templates/default/images/timestamp.png differ diff --git a/infolog/js/app.js b/infolog/js/app.js index 084f772877..01fd929d18 100644 --- a/infolog/js/app.js +++ b/infolog/js/app.js @@ -273,7 +273,7 @@ app.classes.infolog = AppJS.extend( nm.dataview.getColumnMgr().columns[i].set_visibility(colData[i].visible); } nm.dataview.getColumnMgr().updated = true; - + // Update page - set update_in_progress to true to avoid triggering // the change handler and looping if the user has a custom field // column change @@ -667,7 +667,7 @@ app.classes.infolog = AppJS.extend( extras.link_id = ids; break; } - + egw.open("","timesheet","list", extras, 'timesheet'); }, @@ -697,89 +697,6 @@ app.classes.infolog = AppJS.extend( if (_widget.get_value()) this.et2._inst.submit(); }, - /** - * Insert text at the cursor position (or end) of a text field - * - * @param {et2_inputWidget|string} widget Either a widget object or it's ID - * @param {string} text [text=timestamp username] Text to insert - */ - insert_text: function(widget, text) - { - if(typeof widget == 'string') - { - et2 = etemplate2.getById('infolog-edit'); - if(et2) - { - widget = et2.widgetContainer.getWidgetById(widget); - } - } - if(!widget || !widget.input) - { - return; - } - - if(!text) - { - var now = new Date(); - text = date(egw.preference('dateformat') + ' ' + (egw.preference("timeformat") === "12" ? "h:ia" : "H:i")+' ',now); - - // Get properly formatted user name - var user = parseInt(egw.user('account_id')); - var accounts = egw.accounts('accounts'); - for(var j = 0; j < accounts.length; j++) - { - if(accounts[j].value === user) - { - text += accounts[j].label; - break; - } - } - text += ': '; - } - - var input = widget.input[0]; - var scrollPos = input.scrollTop; - var browser = ((input.selectionStart || input.selectionStart == "0") ? - "standards" : (document.selection ? "ie" : false ) ); - - var pos = 0; - - // Find cursor or selection - if (browser == "ie") - { - input.focus(); - var range = document.selection.createRange(); - range.moveStart ("character", -input.value.length); - pos = range.text.length; - } - else if (browser == "standards") - { - pos = input.selectionStart; - }; - - // Insert the text - var front = (input.value).substring(0, pos); - var back = (input.value).substring(pos, input.value.length); - input.value = front+text+back; - - // Clean up a little - pos = pos + text.length; - if (browser == "ie") { - input.focus(); - var range = document.selection.createRange(); - range.moveStart ("character", -input.value.length); - range.moveStart ("character", pos); - range.moveEnd ("character", 0); - range.select(); - } - else if (browser == "standards") { - input.selectionStart = pos; - input.selectionEnd = pos; - input.focus(); - } - input.scrollTop = scrollPos; - }, - /** * Toggle encryption * @@ -876,7 +793,7 @@ app.classes.infolog = AppJS.extend( responsible.set_value(data.data.info_responsible); } } - + nm_open_popup(_action, _selected); }, diff --git a/infolog/templates/default/edit.xet b/infolog/templates/default/edit.xet index 4e12ca2f40..a18f93c8c5 100644 --- a/infolog/templates/default/edit.xet +++ b/infolog/templates/default/edit.xet @@ -187,7 +187,7 @@ - + diff --git a/pixelegg/images/timestamp.png b/pixelegg/images/timestamp.png new file mode 100644 index 0000000000..da67e09ae9 Binary files /dev/null and b/pixelegg/images/timestamp.png differ