Module: check_mk
Branch: master
Commit: 392b3da42ecede93621bc7048f8710231f896d5a
URL:
http://git.mathias-kettner.de/git/?p=check_mk.git;a=commit;h=392b3da42ecedeā¦
Author: Lars Michelsen <lm(a)mathias-kettner.de>
Date: Wed Aug 29 07:47:52 2018 +0200
6509 Pasting with automatic text splitting in list of input elements
When a dialog is using a self extending list of input elements, like e.g. the
host- and service input fields at the bottom of the "hosts & service
parameters"
rule editor, a text can be pasted into the last input field which is then split
by ";" separators. Each of the resulting parts is then added to a dedicated
input
field. This is only active for the last (empty) input field.
This makes it a lot easier to populate such dialogs with a longer list of items.
Change-Id: I66c5901f41a1db064e4686bf33d32dcd643efc1d
---
.werks/6509 | 16 +++++++
cmk/gui/valuespec.py | 26 +++++++----
web/htdocs/js/checkmk.js | 112 ++++++++++++++++++++++++++++++++---------------
3 files changed, 110 insertions(+), 44 deletions(-)
diff --git a/.werks/6509 b/.werks/6509
new file mode 100644
index 0000000..b991362
--- /dev/null
+++ b/.werks/6509
@@ -0,0 +1,16 @@
+Title: Pasting with automatic text splitting in list of input elements
+Level: 2
+Component: multisite
+Compatible: compat
+Edition: cre
+Version: 1.6.0i1
+Date: 1535521285
+Class: feature
+
+When a dialog is using a self extending list of input elements, like e.g. the
+host- and service input fields at the bottom of the "hosts & service
parameters"
+rule editor, a text can be pasted into the last input field which is then split
+by ";" separators. Each of the resulting parts is then added to a dedicated
input
+field. This is only active for the last (empty) input field.
+
+This makes it a lot easier to populate such dialogs with a longer list of items.
diff --git a/cmk/gui/valuespec.py b/cmk/gui/valuespec.py
index 4c550c0..858c463 100644
--- a/cmk/gui/valuespec.py
+++ b/cmk/gui/valuespec.py
@@ -1080,17 +1080,23 @@ class ListOfStrings(ValueSpec):
self._max_entries = kwargs.get("max_entries")
self._separator = kwargs.get("separator", "") # in case of
float
+ self._split_on_paste = kwargs.get("split_on_paste", True)
+ self._split_separators = kwargs.get("split_separators", ";")
+
def help(self):
- help_text = ValueSpec.help(self)
+ help_texts = [
+ ValueSpec.help(self),
+ self._valuespec.help(),
+ ]
- field_help = self._valuespec.help()
- if help_text and field_help:
- return help_text + " " + field_help
- elif field_help:
- return field_help
- else:
- return help_text
+ if self._split_on_paste:
+ help_texts.append(_("You may paste a text from your clipboard which
contains several "
+ "parts separated by \"%s\" characters into the last input
field. The text will "
+ "then be split by these separators and the single parts are added
into dedicated "
+ "input fields.") % self._split_separators)
+
+ return " ".join([ t for t in help_texts if t ])
def render_input(self, varprefix, value):
@@ -1123,7 +1129,9 @@ class ListOfStrings(ValueSpec):
html.close_div()
html.div('', style="clear:left;")
html.help(self.help())
- html.javascript("list_of_strings_init('%s');" % varprefix)
+ html.javascript("list_of_strings_init(%s, %s, %s);" %
+ (json.dumps(varprefix), json.dumps(self._split_on_paste),
+ json.dumps(self._split_separators)))
def canonical_value(self):
return []
diff --git a/web/htdocs/js/checkmk.js b/web/htdocs/js/checkmk.js
index c18a388..6a781c4 100644
--- a/web/htdocs/js/checkmk.js
+++ b/web/htdocs/js/checkmk.js
@@ -2004,63 +2004,105 @@ function valuespec_toggle_dropdownn(oDropdown, divid) {
has been rendered. It attaches the onFocus-function to the last
of the input elements. That function will append another
input field as soon as the user focusses the last field. */
-function list_of_strings_init(divid) {
- var oContainer = document.getElementById(divid);
- var oDivChildren = oContainer.getElementsByTagName("div");
- var oLastChild = oDivChildren[oDivChildren.length-1];
- list_of_strings_add_focus(oLastChild);
-}
-
-function list_of_strings_add_focus(oLastChild) {
- /* look for <input> in last child node and attach focus handler to it. */
- var input = oLastChild.getElementsByTagName("input");
- if (input.length == 1) {
- var handler_func = function(e) {
- if (this.value != "") {
- return list_of_strings_extend(this);
+function list_of_strings_init(divid, split_on_paste, split_separators) {
+ var container = document.getElementById(divid);
+ var children = container.getElementsByTagName("div");
+ var last_input =
children[children.length-1].getElementsByTagName("input")[0];
+ list_of_strings_add_event_handlers(last_input, split_on_paste, split_separators);
+}
+
+function list_of_strings_add_event_handlers(input, split_on_paste, split_separators) {
+ var handler_func = function(e) {
+ if (this.value != "") {
+ return list_of_strings_extend(this, split_on_paste, split_separators);
+ }
+ };
+
+ input.onfocus = handler_func;
+ input.oninput = handler_func;
+
+ if (split_on_paste) {
+ input.onpaste = function(e) {
+ // Get pasted data via clipboard API
+ var clipboard_data = e.clipboardData || window.clipboardData;
+ var pasted = clipboard_data.getData('Text');
+
+ if (this.value != "")
+ return true; // The field had a value before: Don't do custom stuff
+
+ // When pasting a string, trim separators and then split by the given
separators
+ var stripped = pasted.replace(new
RegExp("^["+split_separators+"]+|["+split_separators+"]+$",
"g"), "");
+ if (stripped == "")
+ return true; // Only separators in clipboard: Don't do custom stuff
+ var splitted = stripped.split(new
RegExp("["+split_separators+"]+"));
+
+ // Add splitted parts to the input fields
+ var last_input = this;
+ for (var i = 0; i < splitted.length; i++) {
+ // Put the first item to the current field
+ if (i != 0)
+ last_input = list_of_strings_add_new_field(last_input);
+
+ last_input.value = splitted[i];
}
- };
- input[0].onfocus = handler_func;
- input[0].oninput = handler_func;
+ // Focus the last populated field
+ last_input.focus();
+
+ // And finally add a new empty field to the end (with attached handlers)
+ list_of_strings_extend(last_input, split_on_paste, split_separators);
+
+ // Stop original data actually being pasted
+ return prevent_default_events(e);
+ };
}
}
+function list_of_strings_remove_event_handlers(input) {
+ input.oninput = null;
+ input.onfocus = null;
+ input.onpaste = null;
+}
+
/* Is called when the last input field in a ListOfString gets focus.
In that case a new input field is being appended. */
-function list_of_strings_extend(oInput, j) {
+function list_of_strings_extend(input, split_on_paste, split_separators) {
+ var new_input = list_of_strings_add_new_field(input);
+ /* Move focus function from old last to new last input field */
+ list_of_strings_add_event_handlers(new_input, split_on_paste, split_separators);
+ list_of_strings_remove_event_handlers(input);
+}
+
+
+function list_of_strings_add_new_field(input) {
/* The input field has a unique name like "extra_emails_2" for the field
with
the index 2. We need to convert this into "extra_emails_3". */
- var oldName = oInput.name;
- var splitted = oldName.split("_");
+ var old_name = input.name;
+ var splitted = old_name.split("_");
var num = 1 + parseInt(splitted[splitted.length-1]);
splitted[splitted.length-1] = "" + num;
- var newName = splitted.join("_");
+ var new_name = splitted.join("_");
/* Now create a new <div> element as a copy from the current one and
replace this name. We do this by simply copying the HTML code. The
last field is always empty. Remember: ListOfStrings() always renders
one exceeding empty element. */
- var oDiv = oInput.parentNode;
- while (oDiv.parentNode.classList &&
!oDiv.parentNode.classList.contains("listofstrings"))
- oDiv = oDiv.parentNode;
- var oContainer = oDiv.parentNode;
+ var div = input.parentNode;
+ while (div.parentNode.classList &&
!div.parentNode.classList.contains("listofstrings"))
+ div = div.parentNode;
+ var container = div.parentNode;
- var oNewDiv = document.createElement("DIV");
- oNewDiv.innerHTML = oDiv.innerHTML.replace('"' + oldName +
'"', '"' + newName + '"');
+ var new_div = document.createElement("DIV");
+ new_div.innerHTML = div.innerHTML.replace('"' + old_name +
'"', '"' + new_name + '"');
// IE7 does not have quotes in innerHTML, trying to workaround this here.
- oNewDiv.innerHTML = oNewDiv.innerHTML.replace('=' + oldName + ' ',
'=' + newName + ' ');
- oNewDiv.innerHTML = oNewDiv.innerHTML.replace('=' + oldName + '>',
'=' + newName + '>');
- oContainer.appendChild(oNewDiv);
-
- /* Move focus function from old last to new last input field */
- list_of_strings_add_focus(oNewDiv);
+ new_div.innerHTML = new_div.innerHTML.replace('=' + old_name + ' ',
'=' + new_name + ' ');
+ new_div.innerHTML = new_div.innerHTML.replace('=' + old_name +
'>', '=' + new_name + '>');
+ container.appendChild(new_div);
- oInput.oninput = null;
- oInput.onfocus = null;
+ return new_div.getElementsByTagName("input")[0];
}
function valuespec_cascading_change(oSelect, varprefix, count) {