This is a migrated thread and some comments may be shown as answers.

Extending MultiSelect to Capture Paste Event

5 Answers 664 Views
MultiSelect
This is a migrated thread and some comments may be shown as answers.
R. J.
Top achievements
Rank 1
R. J. asked on 02 Dec 2015, 09:00 PM

Hello!

I wish to add functionality to the MultiSelect in order to capture the "paste" event, parse the input and if any values in the pasted input match are options to the MutliSelect, select them.

Below is the code I used to extend the MutliSelect.  The parsingMutliSelect.value(...) call is indeed changing the values, however the UI is not updating and displaying the values as tags within the input field for the MultiSelect.  In fact, the error "TypeError: Argument 1 of Node.removeChild is not an object" keeps occurring when the parsingMultiSelect._change() call is made.  This error occurs at the line "tagList[0].removeChild(tagList[0].children[removedItem.position]);" within the _selectValue function definition within the MultiSelect configuration (kendo.multiselect.js).

Using my FireBug console, I can successfully get the MutliSelect to perform as expected by using the .value() and .trigger("change") methods on the MultiSelect instance.  Why can I not seem to successfully set values from within the MutliSelect extension definition?

 

01.(function ($) {
02. 
03.  var kendo = window.kendo,
04.      ui = kendo.ui,
05.      MultiSelect = ui.MultiSelect,
06.      CHANGE = "change",
07.      PASTE = "paste";
08. 
09.  var ParsingMultiSelect = MultiSelect.extend({
10. 
11.    init: function (element, options) {
12.      var that = this;
13. 
14.      // Base call to MultiSelect to initialize ParsingMultiSelect
15.      MultiSelect.fn.init.call(that, element, options);
16. 
17.      that.input.on(PASTE, that, that._paste);
18.    },
19. 
20.    options: {
21.      // Assigns the name as it should appear off the kendo namespace (i.e. kendo.ui.ParsingMultiSelect).
22.      // The jQuery plugin would be jQuery.fn.kendoParsingMultiSelect
23.      name: "ParsingMultiSelect"
24.    },
25. 
26.    events: [
27.      PASTE
28.    ],
29. 
30.    _paste: function (e) {
31.      alert("data pasted!");
32.      var parsingMultiSelect = e.data,
33.        dataValueField = parsingMultiSelect.options.dataValueField,
34.        parsingMultiSelectDataSource = parsingMultiSelect.dataSource,
35.        pastedData = e.originalEvent.clipboardData.getData('text'),
36.        validValues = [];
37. 
38.      multiSelect._close();
39. 
40.      parsingMultiSelectDataSource.fetch().done(function () {
41.        var dataSourceData = parsingMultiSelectDataSource.data();
42.        var dataSourceValues = [];
43. 
44.        if (dataSourceData instanceof kendo.data.ObservableArray) {
45.          dataSourceValues = dataSourceData.map(function (arrayElement, index) {
46.            return arrayElement[dataValueField];
47.          });
48.        }
49. 
50.        // Convert all commas to a single space then reduce all whitespace (and consecutive)
51.        // characters in the pasted input to a single space to get ready for splitting
52.        pastedData = pastedData.replace(/,/g, "").replace(/\s\s+/g, " ").trim();
53. 
54.        pastedValues = pastedData.split(" ");
55. 
56.        // Loop through the values pasted in.  If any exist in the dataSource, push them to
57.        // the array of valid values.
58.        $.each(pastedValues, function (index, value) {
59.          if (dataSourceValues.indexOf(value) != -1) {
60.            validValues.push(value);
61.          }
62.        });
63. 
64.        parsingMultiSelect.value(e.data.value().concat(validValues));
65.        parsingMultiSelect._change();
66.      });
67. 
68.      e.preventDefault();
69.    }
70.  });
71. 
72.  // Add the ParsingMultiSelect to Kendo UI
73.  ui.plugin(ParsingMultiSelect);
74. 
75.})(jQuery);
76. 
77. 
78.$("#parsingmultiselect").kendoParsingMultiSelect({
79.  dataSource: [
80.    { unitId: "0001X" },
81.    { unitId: "0002X" },
82.    { unitId: "0003X" },
83.    { unitId: "0004X" },
84.    { unitId: "0005X" },
85.    { unitId: "0006X" }
86.  ],
87.  dataTextField: "unitId",
88.  dataValueField: "unitId",
89.  placeholder: "Select a Unit ID..."
90.});

...and a jsFiddle: https://jsfiddle.net/Lvvwzmyv/3/.  Try pasting a single value: "0002X" and try pasting multiple values: "0002X, 0004X, 0005X" and observe the unintended behaviour.

 

Thank you,

R. J.

5 Answers, 1 is accepted

Sort by
0
R. J.
Top achievements
Rank 1
answered on 02 Dec 2015, 09:04 PM

Please disregard lines 76-90 in the code block of my previous post.  That was a direct cut-and-paste from jsFiddle and I did not mean to include it.  Lines 1-75 are what I use to extend the MutliSelect.

Thank you,

R. J.

0
Konstantin Dikov
Telerik team
answered on 04 Dec 2015, 03:29 PM
Hello,

As documented in the following help article, the value method of the MultiSelect accepts a string value or an array of string value:

With that in mind, please pass the validvalues array directly to the value method and you will get the desired result:
//multiSelect._close(); this line is throwing an error in your example, so I have commented it
...
parsingMultiSelect.value(validValues);

Hope this helps.


Regards,
Konstantin Dikov
Telerik
 
Join us on our journey to create the world's most complete HTML 5 UI Framework - download Kendo UI now!
 
0
R. J.
Top achievements
Rank 1
answered on 04 Dec 2015, 04:05 PM

Konstantin -

Thank you for your response.  I am indeed passing an array of strings directly into the value() function.  That is what e.data.value().concat(validValues) produces.  It's an array of the current values of the MultiSelect appended with the pasted (valid) values (which then, of course, gets normalized within the labyrinth of function calls internal to the MultiSelect).

I'm experiencing very different results with version 2 of the Fiddle (I included version 3 above).  Version 2 seems to actually work using FireFox, however does NOT work in IE.  This may be because of the use of clipboardData as it's not cross-browser supported.  I'll work that issue once I get the behavior of internally setting the value of the MultiSelect consistent.  My actual code is an MVVM implementation (which I could not reproduce exactly in the Fiddle).  I'm suspecting much of the behavior issues related to setting the value has to do with this.  I'll continue to work from your Create a Custom UI Widget page to see if I can get my extended version of your MutliSelect MVVM-aware and working.

Again, thank you for your response.

R. J.

0
R. J.
Top achievements
Rank 1
answered on 04 Dec 2015, 04:21 PM

...then again, all MVVM-aware features such as the dataBinding and dataBound events as well as setDataSource() are all still accessible to ParsingMultiSelect from the extended (underlying) MutliSelect.

Hmmm.........

0
Accepted
Konstantin Dikov
Telerik team
answered on 08 Dec 2015, 01:40 PM
Hi,

Indeed, your code for setting the value was correct and the only problem was due to the following line, which is throwing an error in your initial example:
//multiSelect._close();

Here is a the working code:
(function ($) {
 
  var kendo = window.kendo,
      ui = kendo.ui,
      MultiSelect = ui.MultiSelect,
      CHANGE = "change",
      PASTE = "paste";
 
  var ParsingMultiSelect = MultiSelect.extend({
 
    init: function (element, options) {
      var that = this;
 
      // Base call to MultiSelect to initialize ParsingMultiSelect
      MultiSelect.fn.init.call(that, element, options);
 
      that.input.on(PASTE, that, that._paste);
    },
 
    options: {
      // Assigns the name as it should appear off the kendo namespace (i.e. kendo.ui.ParsingMultiSelect).
      // The jQuery plugin would be jQuery.fn.kendoParsingMultiSelect
      name: "ParsingMultiSelect"
    },
 
    events: [
      PASTE
    ],
 
    _paste: function (e) {
      alert("data pasted!");
      var parsingMultiSelect = e.data,
          dataValueField = parsingMultiSelect.options.dataValueField,
          parsingMultiSelectDataSource = parsingMultiSelect.dataSource,
          pastedData = e.originalEvent.clipboardData.getData('text'),
          validValues = [];
 
      //e.sender._close();
 
      parsingMultiSelectDataSource.fetch().done(function () {
        var dataSourceData = parsingMultiSelectDataSource.data();
        var dataSourceValues = [];
 
        if (dataSourceData instanceof kendo.data.ObservableArray) {
          dataSourceValues = dataSourceData.map(function (arrayElement, index) {
            return arrayElement[dataValueField];
          });
        }
 
        // Convert all commas to a single space then reduce all whitespace (and consecutive)
        // characters in the pasted input to a single space to get ready for splitting
        pastedData = pastedData.replace(/,/g, "").replace(/\s\s+/g, " ").trim();
 
        pastedValues = pastedData.split(" ");
 
        // Loop through the values pasted in.  If any exist in the dataSource, push them to
        // the array of valid values.
        $.each(pastedValues, function (index, value) {
          if (dataSourceValues.indexOf(value) != -1) {
            validValues.push(value);
          }
        });
debugger;
        parsingMultiSelect.value(e.data.value().concat(validValues));
        parsingMultiSelect._change();
        parsingMultiSelect.close();
      });
 
      e.preventDefault();
    }
  });
 
  // Add the ParsingMultiSelect to Kendo UI
  ui.plugin(ParsingMultiSelect);
 
})(jQuery);
 
 
$("#parsingmultiselect").kendoParsingMultiSelect({
  dataSource: [
    { unitId: "0001X" },
    { unitId: "0002X" },
    { unitId: "0003X" },
    { unitId: "0004X" },
    { unitId: "0005X" },
    { unitId: "0006X" }
  ],
  dataTextField: "unitId",
  dataValueField: "unitId",
  placeholder: "Select a Unit ID..."
});



Regards,
Konstantin Dikov
Telerik
 
Join us on our journey to create the world's most complete HTML 5 UI Framework - download Kendo UI now!
 
Tags
MultiSelect
Asked by
R. J.
Top achievements
Rank 1
Answers by
R. J.
Top achievements
Rank 1
Konstantin Dikov
Telerik team
Share this question
or