我正在创建一个项目列表,我希望用户能够使用键盘进行交互。所以像这样......
<ul contenteditable="true">
<li>Item 1</li>
<li>Item 2</li>
<li>Item 3</li>
</ul>
我的理解是为了捕获keydown / keyup事件,我必须设置contenteditable属性。这有效,但现在li的内容是可编辑的,我不想要。我只需要捕获keydown / keyup事件。
如何在不使内容可编辑的情况下捕获这些事件?
修改
感谢jumpcode,以下内容可以保持只读...
$('ul').on('click', 'li', function (e) {
e.preventDefault();
});
...但是我仍然留在一个闪烁的光标上。我该如何摆脱它?
修改
开始赏金,需要对以下的preventDefault答案进行以下更新。
答案 0 :(得分: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;
};
}
这是working demo。
答案 1 :(得分: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中元素的Tab键顺序。