3

ユーザーがキーボードを使用して操作できるようにするアイテムのリストを作成しています。だから、このようなもの...

<ul contenteditable="true">
    <li>Item 1</li>
    <li>Item 2</li>
    <li>Item 3</li>
</ul>

私の理解では、キーダウン/キーアップ イベントをキャプチャするには、contenteditable 属性を設定する必要があります。これは機能しますが、li の内容は編集可能になりましたが、これは望ましくありません。キーダウン/キーアップイベントをキャプチャするだけです。

コンテンツを編集可能にせずにこれらのイベントをキャプチャするにはどうすればよいですか?

編集

jumpingcode のおかげで、次のように動作して読み取り専用になります...

$('ul').on('click', 'li', function (e) {
    e.preventDefault();
});

...しかし、li にカーソルが点滅したままです。どうすればそれを取り除くことができますか?

編集

報奨金を開始しました。以下の preventDefault の回答に対する次の更新が必要です。

  1. 点滅するカーソルを取り除く方法は?
  2. 選択不可にする方法は?私は本当にキーダウンイベントをキャプチャしたいだけです! contenteditable を設定せずにそれを達成できれば、それが望ましいでしょう。
  3. ドキュメント レベルでキーダウンをキャプチャできますが、キーダウンがどこから発生したかという問題が生じます。いくつかのプラグインが動作している可能性があり、すべてが同じイベントに応答する必要がありますが、それらがアクティブなスコープである場合のみです。
4

2 に答える 2

5

おっしゃる通り、リスト項目を編集する必要はないので、使う理由はありませんcontenteditable

必要なのは、リストの現在アクティブな項目に対応するインデックスと、矢印が押されたときにそのインデックスをインクリメントおよびデクリメントする関数です。必要な機能を実装するコンストラクター関数を次に示します。

var NavigableList = function (ul, selectedClass, activeClass) {
    var list   = null,
        index  = 0,
        walk   = function (step) {
            var walked = true;
            index += step;
            if (index < 0 || index === list.length) {
                index -= step;
                walked = false;
            }
            return walked;
        },
        active = false;
    this.active = function (state) {
        if (state !== active) {
            active = state;
            if (active) {
                ul.addClass(activeClass);
            } else {
                ul.removeClass(activeClass);
            }
        }
    };
    this.isActive = function () {
        return active;
    };
    this.down = function () {
        var previous = index,
            changed  = false;
        if (walk(1)) {
            $(list[previous]).removeClass(selectedClass);
            $(list[index]).addClass(selectedClass);
            changed = true;
        }
        return changed;
    };
    this.up = function () {
        var previous = index,
            changed  = false;
        if (walk(-1)) {
            $(list[previous]).removeClass(selectedClass);
            $(list[index]).addClass(selectedClass);
            changed = true;
        }
        return changed;
    };
    this.currentIndex = function () {
        return index;
    };
    this.currentElementx = function () {
        return $(list[index]);
    };
    ul = $(ul);
    list = ul.find('>li');
    selectedClass = selectedClass || 'current';
    activeClass = activeClass || 'active';
    $(ul).click(function (e) {
        this.active(true);
        NavigableList.activeList = this;
    }.bind(this));
    $(document).keydown(function(e) {
        var event = $.Event('change');
        if (this.isActive() && e.keyCode === 40) {
            if (this.down()) {
                event.selected = $(list[index]);
                event.index = index;
                ul.trigger(event);
            }
        } else if (this.isActive() && e.keyCode === 38) {
            if (this.up()) {
                event.selected = $(list[index]);
                event.index = index;
                ul.trigger(event);
            }
        }
    }.bind(this));
    $(list[index]).addClass(selectedClass);
};

これを使うのはとても簡単です:

var list = new NavigableList($('#list'), 'current', 'active'),
    list2 = new NavigableList($('#list2'));
$(document).click(function (e) {
    if (NavigableList.activeList) {
        switch (NavigableList.activeList) {
            case list:
                list2.active(false);
                break;
            case list2:
                list.active(false);
                break;
        }
    } else {
        list.active(false);
        list2.active(false);
    }
    NavigableList.activeList = null;
});

また、次のchange方法で使用できるリストにイベントを実装しました。

$('#list').change(function (e) {
    console.log('List. Selected: ' + e.index);
});
$('#list2').change(function (e) {
    console.log('List 2. Selected: ' + e.index);
});

ブラウザ間の互換性のために、すべての Javascript コードの前にこれが必要になります。

if (!Function.prototype.bind) {
  Function.prototype.bind = function (oThis) {
    if (typeof this !== "function") {
      throw new TypeError("Function.prototype.bind - what is trying to be bound is not callable");
    }
    var aArgs = Array.prototype.slice.call(arguments, 1), 
        fToBind = this, 
        fNOP = function () {},
        fBound = function () {
          return fToBind.apply(this instanceof fNOP && oThis
                                 ? this
                                 : oThis,
                               aArgs.concat(Array.prototype.slice.call(arguments)));
        };
    fNOP.prototype = this.prototype;
    fBound.prototype = new fNOP();
    return fBound;
  };
}

これが実際のデモです。

于 2013-10-21T14:08:34.667 に答える
0

これを試して。

<ul contenteditable="true">
   <li tabindex="1">Item 1</li>
   <li tabindex="2">Item 2</li>
   <li tabindex="3">Item 3</li>
</ul>

Tabindex は、HTML 内の要素のタブ オーダーを設定します。

于 2013-10-18T14:37:46.637 に答える