web-dev-qa-db-ja.com

複数の選択が可能なハンドソン可能なドロップダウン

Handsontableプラグインを拡張して、ドロップダウンリストでの複数選択をサポートしようとしています。ライブラリに組み込まれているベースエディターを拡張するために、「dropdownEditor」を提案されたように変更してみました https://github.com/trebuchetty/Handsontable-select2-editor/issues/7 。キーワードのソースを読んだり検索したりするのに何時間も費やしましたが、実際に役立つものは思いつきません。

Angular拡張機能または別のネイティブECMA5または https://github.com/handsontable/handsontable プラグインを拡張する6つの方法を使用してこれが答えられてもかまいません。

これまでのところ、私の唯一の考えは、実際に存在するパターンに従ってこのコードのコードでフレームワークを拡張することでした。以下を指すすべての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);
_

この時点では、ユーザーがドロップダウンリストから項目を選択したときにクリックイベントが発生している手がかりがありません。 Traceurを使用しているため、デバッグは私にとって苦痛でした。モジュールの準備が整い、DOMも同様にクリックイベントを設定しようとしましたが、選択したドロップダウンセルの1つをクリックしただけではアラートが発生しません。シンプルでクリックできる「通常の」セル:

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

ただし、メニューの内容についてはそうではありません。右クリックしてドロップダウンメニューを確認するということは、最初に http://handsontable.com/ のようなコンテキストメニューを無効にすることを意味します。次に、右クリックして何かを検査すると、検査しようとしているドロップダウンメニューを閉じるイベントが発生します。

ライブラリのソースコード全体にブレークポイントを設定しましたが、これを理解することはできません。

私がやりたい唯一のことは、メニュー項目を強調表示してアクティブな選択に設定するコードの部分を見つけ出し、それを複数の選択を受け入れるメソッドに変更することです(利用可能なオプションの配列全体まで、クリックしてアクティブなアイテムはそれを無効にします。

次に、それらの選択が実際にHandsontableの「データスコープ」にあることを確認します。

残念ながら、私はまだドロップダウンのオプションが表示される場所を見つけることができないので、どんな助けも素晴らしいでしょうが、それはセルに選択されたものを表示することさえも必要ありません。

http://jsfiddle.net/4mpyhbjw/40/ および https://github.com/trebuchetty/Handsontable-select2-のように、handsontable用に作成されたSelect2Editorを使用してみましたeditor/issues/ 、しかしそれは私の原因にはあまり役立ちません。 handsontableのドロップダウンセルは次のようになります。

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

最後に、フィドルがここにあります: http://jsfiddle.net/tjrygch6/

誰かが私をここで助けてくれれば私はとても感謝しています。ありがとうSO!

[〜#〜]更新[〜#〜]

セルの値を解析し、型を値を含む配列に変換しました(したがって、赤青を入力すると_['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の両方の値を認識して部分的に選択するための内部メソッドを取得しましたが、まだ正確にはほど遠いです。

Showing the selection (sort of) of both items based on two values typed into the cell, also showing the output in the console for the coord being returned from the WalkOnTable util being used behind the scenes in this handsontable plugin. Output is below

以下は、呼び出されるメソッドWalkOnTableCellCordsによって生成されるコンソール出力です。これは、セルに値が1つしか含まれていない場合(デフォルト機能)のドロップダウン選択を強調表示するようです。この出力は、リストの個々のオプションとして青と黒の両方を含むドロップダウンセルに黒青を入力した結果です。

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

[〜#〜] update [〜#〜]誰かがこれを解決した場合、私はあなたが実際にどこにいても直接飛んで、握手します。 TWICE。

18
Alpha G33k

ワオ。とても努力。今では、1年以上後、それははるかに簡単です。

Chosen 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
Rolok

わかりました、それがあなたを助けることを願っています。 APIを読んでコードをカスタマイズするのに時間がかかりました:)

Handsontableライブラリ(最新バージョン)からサンプルコードを取得し、ほとんど変更を加えていません。

それにはいくつかのバグがあるかもしれませんが、それはプロトタイプにすぎないので、編集して、もちろん見栄えを良くすることができます。

何らかの理由で、dropdownlistをクリック可能にすることができませんでした。 Z-indexの問題や他のCSSプロパティゲームのようです。私はあなたがそれを修正する方法を見つけることを信頼しています。とりあえず今のところ、Shiftキーを押しながら選択すると、キーボードを使用して選択できます。

出力は、カンマで区切られた、結合された選択オプションのコレクションです。

例えば:

enter image description hereenter image description here

これを機能させるには、handsontableライブラリをロードした後でこのコードを追加します。 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'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);

それを使用する方法:

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つの方法を変更することができます。

  1. prepare-ユーザーがエディターのopenイベントをトリガーするたびに呼び出されます。構成および操作用。
  2. init-そのメソッドは、セルをクリックするたびに呼び出されます。これはHTMLコードを作成するため、たとえばチェックボックスに変更できます。

もう1つは、コードのどこにあるかについての質問に関連しています。

Handsontableは、任意のセルタイプをエディターに分割してレンダリングします。エディターのすべてのHTMLコードは、そのうちの1つを変更する場合に備えて、おそらくinitに存在します。 valueは、編集モードのときにnotのときにセルに表示されるhtmlコンテンツですgetValueに存在します方法。

お役に立てば幸いです。また、現在のバージョンに合うことを願っています。

4
Dvir