Dropdowns handstable avec plusieurs sélections
j'essaie d'étendre le plugin handsontable pour supporter plusieurs sélections dans sa liste déroulante. J'ai déjà essayé d'étendre l'éditeur de base construit dans la bibliothèque en modifiant le 'dropdownEditor' comme suggéré https://github.com/trebuchetty/Handsontable-select2-editor/issues/7. J'ai passé des heures à lire et à chercher des mots-clés dans la source, mais je ne trouve rien d'utile.
cela ne me dérange pas si on répond en utilisant le Extension angulaire ou une autre ECMA5 ou 6 façon d'étendre lehttps://github.com/handsontable/handsontable plugin.
jusqu'à présent, mes seules pensées étaient d'étendre le cadre avec ce peu de code en suivant les modèles qui existent. J'ai ajouté tous LOC, ci-dessous, pointant vers: multiselect
ou Handsontable.MultiselectDropdownCell
copié le dropdown
méthode, appelée le nouveau nom et tout fonctionne, cependant, ne voyez toujours pas où je pourrais commencer à trouver ce que je cherche pour.
Handsontable.MultiselectDropdownCell = {
editor: getEditorConstructor('multiselectdropdown'),
renderer: getRenderer('autocomplete')
};
Handsontable.cellTypes = {
text: Handsontable.TextCell,
date: Handsontable.DateCell,
numeric: Handsontable.NumericCell,
checkbox: Handsontable.CheckboxCell,
autocomplete: Handsontable.AutocompleteCell,
handsontable: Handsontable.HandsontableCell,
password: Handsontable.PasswordCell,
dropdown: Handsontable.DropdownCell,
multiselect: Handsontable.MultiselectDropdownCell
};
Handsontable.cellLookup = { validator: {
numeric: Handsontable.NumericValidator,
autocomplete: Handsontable.AutocompleteValidator
}};
j'ai une version modifiée de dropdown editor en place qui ressemble à:
import {getEditor, registerEditor} from './../editors.js';
import {AutocompleteEditor} from './autocompleteEditor.js';
/**
* @private
* @editor MultiSelectDropdownEditor
* @class MultiSelectDropdownEditor
* @dependencies AutocompleteEditor
*/
class MultiSelectDropdownEditor extends AutocompleteEditor {
prepare(row, col, prop, td, originalValue, cellProperties) {
super.prepare(row, col, prop, td, originalValue, cellProperties);
this.cellProperties.filter = false;
this.cellProperties.strict = true;
}
}
export {MultiSelectDropdownEditor};
registerEditor('multiselectdropdown', MultiSelectDropdownEditor);
À ce stade, je n'ai aucune idée de où l'événement click se produit lorsque l'utilisateur sélectionne un élément dans la liste déroulante. Débogage a été douloureux pour moi parce que c'est à travers Traceur. J'ai essayé de définir un événement de clic après le module est prêt et le DOM est aussi bien, mais je ne peux pas obtenir même une alerte à tirer basé sur un clic sur l'un des dropdown select cellule. "Normal", les cellules que je peux obtenir un cliquer avec un simple:
$('body').on('click','#handsontable td', someAlert)
cependant, ce n'est pas le cas pour le contenu du menu. Clic droit pour inspecter le menu déroulant signifie d'abord désactiver le menu contextuel comme sur http://handsontable.com/. Ensuite, vous remarquerez que le clic droit d'inspecter tout va déclencher un événement qui ferme le menu déroulant, vous essayez de les inspecter.
j'ai mis des points de rupture dans toutes les bibliothèques source code, Je ne peux pas comprendre celui-là.
la seule chose que je veux faire est de comprendre où se trouve la partie du code qui met en évidence l'élément du menu et le place dans une sélection active, le transformer en une méthode qui accepte plusieurs sélections (jusqu'à l'ensemble des options disponibles, cliquer sur un élément actif le désactivera, disons).
puis s'assurer que ces sélections sont effectivement dans le Handsontable 'data scope'.
c'est ça, je n'ai pas besoin il même pour rendre dans la cellule ce que les choses ont été choisies, bien que n'importe quelle aide là-bas serait grande parce que malheureusement, je ne suis pas encore trouver l'endroit où les options dans le dropdown sont rendus soit.
j'ai aussi essayé D'utiliser le Select2Editor fait pour handsontable comme vu http://jsfiddle.net/4mpyhbjw/40/ et https://github.com/trebuchetty/Handsontable-select2-editor/issues/3, cependant cela n'aide pas beaucoup ma cause. Voici ce que l' liste déroulante de la cellule dans handsontable ressemble à:
http://docs.handsontable.com/0.15.1/demo-dropdown.html
Enfin, voici un violon: http://jsfiddle.net/tjrygch6/
je vous serais super reconnaissante si quelqu'un pouvait m'aider ici. Merci!
UPDATE
j'ai réussi à analyser les valeurs dans la cellule et tournez le type dans un tableau contenant les valeurs (donc en tapant rouge bleu va tourner un tableau contenant ['red','blue']
). J'ai lancé ce tableau à travers l'algorithme de tri interne qui analyse les options et renvoie un index d'un élément correspondant. J'obtiens que cela fonctionne bien et je passe maintenant le tableau dans la méthode de surlignage. Cette méthode passe les valeurs de la bibliothèque de base WalkOnTable. Je ne vois pas où je peux modifier la logique pour sélectionner plus d'une valeur au lieu de décrocher la première option.
this.selectCell = function(row, col, endRow, endCol, scrollToCell, changeListener) {
var coords;
changeListener = typeof changeListener === 'undefined' || changeListener === true;
if (typeof row !== 'number' && !Array.isArray(row) || row < 0 || row >= instance.countRows()) {
return false;
}
if (typeof col !== 'number' || col < 0 || col >= instance.countCols()) {
return false;
}
if (typeof endRow !== 'undefined') {
if (typeof endRow !== 'number' || endRow < 0 || endRow >= instance.countRows()) {
return false;
}
if (typeof endCol !== 'number' || endCol < 0 || endCol >= instance.countCols()) {
return false;
}
}
// Normal number value, one item typed in
if (!Array.isArray(row) && typeof row === 'number'){
coords = new WalkontableCellCoords(row, col);
walkSelection(coords);
}
C'est la endroit où je pense que j'ai besoin WalkontableCellCoords
à modifier pour accepter un tableau, puis mettre en surbrillance et sélectionner les deux valeurs lorsque la liste déroulante est ouverte et fermée. J'ai aussi besoin d'être capable de sélectionner plusieurs options via l'événement touch ou click.
else {
// Array found, apply to each value
new WalkontableCellCoords(row[0], col);
new WalkontableCellCoords(row[1], col);
}
function walkSelection(coords){
priv.selRange = new WalkontableCellRange(coords, coords, coords);
if (document.activeElement && document.activeElement !== document.documentElement && document.activeElement !== document.body) {
document.activeElement.blur();
}
if (changeListener) {
instance.listen();
}
if (typeof endRow === 'undefined') {
selection.setRangeEnd(priv.selRange.from, scrollToCell);
} else {
selection.setRangeEnd(new WalkontableCellCoords(endRow, endCol), scrollToCell);
}
instance.selection.finish();
}
return true;
};
mise à Jour 2
j'ai obtenu les méthodes internes pour reconnaître et sélectionner partiellement les deux valeurs dans le DOM mais il est encore loin d'être correct.
Voici la sortie de la console générés par la méthode WalkOnTableCellCords
pour être appelé, ce qui semble être ce que souligne la liste déroulante de sélection dans le cas où la cellule ne contient que des 1 (valeur par défaut de la fonctionnalité). Cette sortie est de dactylographier le bleu noir dans une cellule de descente contenant à la fois le bleu et le noir comme options individuelles dans la liste.
extended_hot_v15-01.js:5041 DropdownEditor {
"highlight": {
"row": 6,
"col": 0
},
"from":
{
"row": 4,
"col": 0
},
"to": {
"row": 6,
"col": 0
}
}
UPDATE si quelqu'un résout cela, je le ferai volez personnellement à l'endroit où vous êtes en personne, et serrez votre main. À deux reprises.
2 réponses
Wow. Tant d'efforts. Maintenant, plus d'un an plus tard, il est beaucoup plus facile.
j'ai utilisé le plugin jQuery choisi avec succès. C'était assez facile.
Voici l'exemple d'une personne: https://github.com/mydea/handsontable-chosen-editor
choisi est beau. J'utilise autocomplete avec un multi-select. Voici le rendu:
function customDropdownRenderer(instance, td, row, col, prop, value, cellProperties) {
var selectedId;
var optionsList = cellProperties.chosenOptions.data;
if(typeof optionsList === "undefined" || typeof optionsList.length === "undefined" || !optionsList.length) {
Handsontable.TextCell.renderer(instance, td, row, col, prop, value, cellProperties);
return td;
}
var values = (value + "").split(",");
value = [];
for (var index = 0; index < optionsList.length; index++) {
if (values.indexOf(optionsList[index].id + "") > -1) {
selectedId = optionsList[index].id;
value.push(optionsList[index].label);
}
}
value = value.join(", ");
Handsontable.TextCell.renderer(instance, td, row, col, prop, value, cellProperties);
return td;
}
et puis je viens de mettre en place la colonne particulière comme ceci:
columns: [
{},
{},
{type: 'numeric'},
{type: 'dropdown', source: ['', 'NAME', 'FNB']},
{},
{},
{},
{},
{},
{},
{},
{type: 'dropdown', source: ['', 'S', 'M']},
{},
{},
{
renderer: customDropdownRenderer,
editor: "chosen",
width: 150,
chosenOptions: {
multiple: true,
data: productData
}
},
{},
{editor: false, readOnly: true, width: 1},
{editor: false, readOnly: true, width: 1}
],
Ok, j'espère que ça va vous aider. Il m'a fallu le temps de lire l'api et de personnaliser le code :)
j'ai pris un exemple de code à partir de Handsontable
bibliothèque (dernière version) et fait peu de changements.
il y a peut-être des bugs, mais ce n'est qu'un prototype, donc vous pouvez éditer et rendre cela plus visible bien sûr.
Pour une raison que je n'ai pas de succès pour faire de l' dropdownlist
pour être cliquable. Il semble comme l'édition de z-index ou d'autres jeux de propriétés css. J'ai confiance sur vous pour trouver comment corriger le problème.
De toute façon pour l'instant, vous pouvez utiliser le clavier pour sélectionner en tenant Maj pour la sélection multiple.
la sortie est une collection d'options sélectionnées jointes par virgule séparée.
par exemple:
pour que cela fonctionne, ajoutez ce code après avoir chargé handsontable libary. Il permettra de prolonger votre Handsontable
types de cellules.
(function(Handsontable) {
var SelectEditor = Handsontable.editors.BaseEditor.prototype.extend();
SelectEditor.prototype.init = function() {
// Create detached node, add CSS class and make sure its not visible
this.select = document.createElement('SELECT');
Handsontable.Dom.addClass(this.select, 'htSelectEditor');
this.select.style.display = 'none';
// Attach node to DOM, by appending it to the container holding the table
this.instance.rootElement.appendChild(this.select);
};
// Create options in prepare() method
SelectEditor.prototype.prepare = function() {
// Remember to invoke parent's method
Handsontable.editors.BaseEditor.prototype.prepare.apply(this, arguments);
this.isMultiple = !!this.cellProperties.multiple;
if (this.isMultiple) this.select.multiple = true;
var selectOptions = this.cellProperties.selectOptions;
var options;
if (typeof selectOptions == 'function') {
options = this.prepareOptions(selectOptions(this.row,
this.col, this.prop))
} else {
options = this.prepareOptions(selectOptions);
}
Handsontable.Dom.empty(this.select);
for (var option in options) {
if (options.hasOwnProperty(option)) {
var optionElement = document.createElement('OPTION');
optionElement.value = option;
Handsontable.Dom.fastInnerHTML(optionElement, options[option]);
this.select.appendChild(optionElement);
}
}
};
SelectEditor.prototype.prepareOptions = function(optionsToPrepare) {
var preparedOptions = {};
if (Array.isArray(optionsToPrepare)) {
for (var i = 0, len = optionsToPrepare.length; i < len; i++) {
preparedOptions[optionsToPrepare[i]] = optionsToPrepare[i];
}
} else if (typeof optionsToPrepare == 'object') {
preparedOptions = optionsToPrepare;
}
return preparedOptions;
};
SelectEditor.prototype.getValue = function() {
var result = [];
var options = this.select && this.select.options;
var opt;
for (var i = 0, iLen = options.length; i < iLen; i++) {
opt = options[i];
if (opt.selected) {
result.push(opt.value || opt.text);
}
}
return result.join();
};
SelectEditor.prototype.setValue = function(value) {
this.select.value = value;
};
SelectEditor.prototype.open = function() {
var width = Handsontable.Dom.outerWidth(this.TD);
// important - group layout reads together for better performance
var height = Handsontable.Dom.outerHeight(this.TD);
var rootOffset = Handsontable.Dom.offset(this.instance.rootElement);
var tdOffset = Handsontable.Dom.offset(this.TD);
var editorSection = this.checkEditorSection();
var cssTransformOffset;
if (this.select && this.select.options && this.isMultiple) {
var height = 0;
for (var i = 0; i < this.select.options.length - 1; i++) {
height += Handsontable.Dom.outerHeight(this.TD);
}
}
switch (editorSection) {
case 'top':
cssTransformOffset = Handsontable.Dom.getCssTransform(this.instance.view.wt.wtScrollbars.vertical.clone.wtTable.holder.parentNode);
break;
case 'left':
cssTransformOffset = Handsontable.Dom.getCssTransform(this.instance.view.wt.wtScrollbars.horizontal.clone.wtTable.holder.parentNode);
break;
case 'corner':
cssTransformOffset = Handsontable.Dom.getCssTransform(this.instance.view.wt.wtScrollbars.corner.clone.wtTable.holder.parentNode);
break;
}
var selectStyle = this.select.style;
if (cssTransformOffset && cssTransformOffset !== -1) {
selectStyle[cssTransformOffset[0]] = cssTransformOffset[1];
} else {
Handsontable.Dom.resetCssTransform(this.select);
}
selectStyle.height = height + 'px';
selectStyle.minWidth = width + 'px';
selectStyle.top = tdOffset.top - rootOffset.top + 'px';
selectStyle.left = tdOffset.left - rootOffset.left + 'px';
selectStyle.margin = '0px';
selectStyle.display = '';
};
SelectEditor.prototype.checkEditorSection = function() {
if (this.row < this.instance.getSettings().fixedRowsTop) {
if (this.col < this.instance.getSettings().fixedColumnsLeft) {
return 'corner';
} else {
return 'top';
}
} else {
if (this.col < this.instance.getSettings().fixedColumnsLeft) {
return 'left';
}
}
};
SelectEditor.prototype.close = function() {
this.select.style.display = 'none';
};
Handsontable.editors.registerEditor('dvirH', SelectEditor);
})(Handsontable);
le chemin vers utiliser:
var container = document.getElementById("example1");
var hot1;
hot1 = new Handsontable(container, {
data: [
['2008', 'Nissan', 11],
['2009', 'Honda', 11],
['2010', 'Kia', 15]
],
colHeaders: true,
contextMenu: false,
columns: [{}, {
editor: 'select',
selectOptions: ['Kia', 'Nissan', 'Toyota', 'Honda'],
// notice that attribute. You can remove it to get a regular select
multiple: true
} {}]
});
démonstration ici
Pour le rendre facile sur vous. Si vous souhaitez modifier le code il y a 2 méthodes que vous souhaitez modifier.
prepare
- sera appelé à chaque fois que l'Utilisateur a déclenché un événement Open editor. Pour configurations et manipulations.
une autre chose se rapporte à vos questions sur l'endroit où les choses dans le code.
Handsontable split importe quel type de cellule à l'éditeur et les restitue.
Tout le code html de l'éditeur existe probablement dans le init
au cas où vous voudriez en changer un.
value
qui est le contenu html qui apparaît dans la cellule quand vous êtes en mode édition existe en getValue
méthode.
j'espère que cela aide, et j'espère qu'il s'adapte à votre version actuelle.