Подтвердить что ты не робот

Удобные выпадающие меню с несколькими вариантами выбора

Я пытаюсь расширить плавный плагин для поддержки нескольких вариантов в раскрывающемся списке. Я уже пробовал расширить базовый редактор, встроенный в библиотеку, изменив "dropdownEditor", как было предложено https://github.com/trebuchetty/Handsontable-select2-editor/issues/7. Я часами читал и просматривал источники ключевых слов, но я не придумываю ничего реального.

Я не возражаю, если на это ответят с помощью расширения Angular или другого родного ECMA5 или 6 способов расширения https://github.com/handsontable/handsontable плагин.

До сих пор мои единственные мысли заключались в том, чтобы на самом деле расширить рамки с помощью этого бита кода, следуя существующим шаблонам. Я добавил все LOC ниже, которые указывают на: multiselect или Handsontable.MultiselectDropdownCell скопировал метод dropdown, названный новым именем, и все работает, однако все еще не может видеть, где я мог бы найти то, что я ищу.

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
}};

У меня есть модифицированная версия редактора выпадающего списка, которая выглядит так:

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);

В этот момент я не знаю, где происходит событие click, когда пользователь выбирает элемент из выпадающего списка. Отладка была болезненной для меня, потому что она через Трейсера. Я попытался настроить событие щелчка после того, как модуль готов, а DOM тоже, но я не могу получить предупреждение даже при нажатии на одну из выделенных выпадающих ячеек. "Нормальные" ячейки я могу получить щелчок простым:

$('body').on('click','#handsontable td', someAlert)

Однако это не так для содержимого меню. Щелчок правой кнопкой мыши, чтобы просмотреть раскрывающееся меню, означает сначала отключить контекстное меню, как на http://handsontable.com/. Затем вы заметите, что щелчок правой кнопкой мыши для проверки чего-либо приведет к событию, закрывающему раскрывающееся меню, которое вы пытаетесь проверить.

Я поставил точки останова по всему исходному коду библиотек, я не могу понять это.

Единственное, что я хочу сделать, это выяснить, где часть кода, которая выделяет элемент меню и устанавливает его на активный выбор, превращает это в метод, который принимает несколько выборов (вплоть до всего массива опций доступно, нажатие активного элемента отключит его, просто скажу).

Затем убедитесь, что эти выборки действительно находятся в области "Доступные данные".

Вот оно, мне не нужно даже рисовать в камере то, что было выбрано, хотя любая помощь там была бы замечательной, потому что, к сожалению, мне еще предстоит найти место, когда параметры в выпадающем меню отображаются либо.

Я также пробовал использовать Select2Editor для handsontable, как показано http://jsfiddle.net/4mpyhbjw/40/ и https://github.com/trebuchetty/Handsontable-select2-editor/issues/3, однако это не очень помогает моей причине. Вот как выглядит раскрывающаяся ячейка в handsontable:

http://docs.handsontable.com/0.15.1/demo-dropdown.html

Наконец, heres a скрипт: http://jsfiddle.net/tjrygch6/

Я был бы очень признателен, если бы кто-то мог помочь мне здесь. Спасибо, SO!

UPDATE

Мне удалось проанализировать значения в ячейке и превратить этот тип в массив, содержащий значения (поэтому набрав красный синий цвет, он будет содержать массив, содержащий ['red','blue']). Я запустил этот массив через внутренний алгоритм сортировки, который анализирует параметры и возвращает индекс соответствующего элемента. Я получаю эту работу отлично, и теперь я передаю массив методу выделения. Этот метод передает значения основной библиотеки WalkOnTable. Я не вижу, где я могу изменить логику, чтобы выбрать более одного значения вместо того, чтобы не высвечивать первый вариант.

 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);
}

Это место, где мне кажется, что мне нужно WalkontableCellCoords изменить, чтобы принять массив, а затем выделить и выбрать оба значения при открытии и закрытии раскрывающегося списка. Мне также нужно иметь возможность выбирать несколько опций с помощью сенсорного или клик-события.

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;

};

Обновление 2

Я получил внутренние методы для распознавания и частичного выбора обоих значений в DOM, но он еще далек от правильного.

Отображение выбора (вида) обоих элементов на основе двух значений, введенных в ячейку, также показывающий вывод в консоли для того, чтобы координата была возвращена из утилиты WalkOnTable, используемой за кулисами этого плавного подключаемого модуля. Выходной сигнал ниже

Здесь вызывается вывод консоли, сгенерированный методом WalkOnTableCellCords, который, как представляется, выделяет выпадающий выбор в случае, когда ячейка содержит только 1 значение (функция по умолчанию). Этот вывод состоит из ввода черного синего цвета в выпадающую ячейку, содержащую как синий, так и черный, как отдельные параметры в списке.

extended_hot_v15-01.js:5041 DropdownEditor {
            "highlight": {
                    "row": 6,
                    "col": 0
            },
            "from":
                   {
                    "row": 4,
                    "col": 0
                   },
             "to": {
                    "row": 6,
                    "col": 0
                    }
            }

ОБНОВЛЕНИЕ. Если кто-то решит это, я лично вылечу туда, где вы лично, и пожимаете руку. ДВАЖДЫ.

4b9b3361

Ответ 1

Ого. Столько усилий. Теперь, более года спустя, это намного проще.

Я успешно использовал выбранный плагин jQuery. Это было довольно легко.

Вот пример одного человека: https://github.com/mydea/handsontable-chosen-editor

Выбран красивый. Я использую автозаполнение с мультиселекцией. Здесь средство визуализации:

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;
}

а затем я просто установил конкретный столбец следующим образом:

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}
],

Ответ 2

Хорошо, надеюсь, это поможет вам. Мне потребовалось время, чтобы прочитать api и настроить код:)

Я взял образец кода из библиотеки Handsontable (последняя версия) и внес небольшие изменения.

В нем могут быть некоторые ошибки, но это только прототип, поэтому вы можете редактировать и, конечно же, выглядеть лучше.

По какой-то причине я не смог сделать клик dropdownlist доступным. Это похоже на проблему z-index или другие игры css-свойств. Я верю, что вы найдете, как это исправить. В любом случае, вы можете использовать клавиатуру для выбора, удерживая shift для множественного выбора.

Вывод представляет собой набор объединенных выбранных опций разделенным запятой.

например:

введите описание изображения здесь введите описание изображения здесь

Чтобы сделать эту работу, добавьте этот код после загрузки handsontable libary. Он расширит ваши типы Handsontable.

(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 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);

Способ использования:

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
    } {}]
});

Демо-версия в здесь

Чтобы вам было легко. Если вы хотите отредактировать код, вы можете изменить 2 метода.

  • prepare - будет вызываться каждый раз, когда пользователь запускает событие открытия редактора. Для конфигураций и манипуляций.
  • init - этот метод будет вызываться каждый раз, когда вы нажимаете на ячейку. Он создает html-код, поэтому вы можете изменить его на флажки, например.

Еще одна вещь относится к вашим вопросам о том, где вещи в коде.

Совместим с любыми типами ячеек для редактора и рендеринга. Весь HTML-код редактора, вероятно, существует в init, если вы хотите изменить один из них. value, который представляет собой содержимое html, которое появляется в ячейке, когда вы находитесь не в режиме редактирования, существует в методе getValue.

Я надеюсь, что это поможет, и я надеюсь, что это соответствует вашей текущей версии.

Ответ 3

С jExcel вы можете получить гораздо большую поддержку, чтобы справиться с этим.

https://bossanova.uk/jexcel/examples/working-with-dropdowns

<html>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>

<script src="https://cdnjs.cloudflare.com/ajax/libs/jexcel/2.1.0/js/jquery.jexcel.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jexcel/2.1.0/js/jquery.jdropdown.js"></script>
<link rel="stylesheet" href="#" onclick="location.href='https://cdnjs.cloudflare.com/ajax/libs/jexcel/2.1.0/css/jquery.jexcel.min.css'; return false;" type="text/css" />
<link rel="stylesheet" href="#" onclick="location.href='https://cdnjs.cloudflare.com/ajax/libs/jexcel/2.1.0/css/jquery.jdropdown.min.css'; return false;" type="text/css" />

<div id="my"></div>

<script>
data2 = [
    [3, 'Cheese', 0],
    [1, 'Apples', 1],
    [2, 'Carrots', 0],
    [1, 'Oranges', 0],
];

dropdown = function(instance, cell, c, r, source) {
    // Get a value from the same row but previous column
    var value = $(instance).jexcel('getValue', c-1 + '-' + r);

    // Return the values will be part in your current column
    if (value == 1) {
        return ['Apples','Bananas','Oranges'];
    } else if (value == 2) {
        return ['Carrots'];
    } else {
        return source;
    }
}

$('#my2').jexcel({
    data:data2,
    colHeaders: ['Category','Product', 'Buy later'],
    colWidths: [ 300, 200, 100 ],
    columns: [
        { type: 'dropdown', source: [ {'id':'1', 'name':'Fruits'},  {'id':'2', 'name':'Legumes'}, {'id':'3', 'name':'General Food'} ] },
        { type: 'dropdown', source: [ 'Apples', 'Bananas', 'Carrots', 'Oranges', 'Cheese' ], filter:dropdown },
        { type: 'checkbox' },
    ]
});
</script>
</html>