2010年6月10日木曜日

record_select の google chrome 対応

 規格がどうだ・・・とか、厳密な話をしていても、微妙な違いは起こるものです。自分の開発環境がノートパソコンだからかどうかは、わかりませんが、少なくとも Firefox と Google chrome では、javascript 内における onkeypress イベントで、ハンドリングされないキーが存在します。
 あと、意図せずに、ESC キーを押してしまった場合、フォーカスを当てなおさないと選択リストが表示されません。これらを考慮に入れた上で、record_select.js を修正してみました。


...

/**
* all the behavior to respond to a text field as a search box
*/
_respond_to_text_field: function(text_field) {
// attach the events to start this party
text_field.observe('focus', this.open.bind(this));

// the autosearch event - needs to happen slightly late (keyup is later than keypress)
text_field.observe('keyup', function() {
if (!this.is_open()) return;
this.container.down('.text-input').value = text_field.value;
}.bind(this));

// keyboard navigation, if available
if (this.onkeypress) {
text_field.observe('keypress', this.onkeypress.bind(this));
}
if (this.onkeydown) {
text_field.observe('keydown', this.onkeydown.bind(this));
}
},

_use_iframe_mask: function() {
return this.container.insertAdjacentHTML ? true : false;
}
});

/**
* Adds keyboard navigation to RecordSelect objects
*/
Object.extend(RecordSelect.Abstract.prototype, {
current: null,

/**
* keyboard navigation - where to intercept the keys is up to the concrete class
* some browser does not handle KEY_XXXX. so separate to keydown event
*/
onkeypress: function(ev) {
var elem;
switch (ev.keyCode) {
case Event.KEY_SPACE:
case Event.KEY_RETURN:
if (this.current) this.current.down('a').onclick();
break;
case Event.KEY_RIGHT:
if( !this.is_open() ) this.open();
elem = this.container.down('li.pagination.next');
if (elem) elem.down('a').onclick();
break;
case Event.KEY_LEFT:
if( !this.is_open() ) this.open();
elem = this.container.down('li.pagination.previous');
if (elem) elem.down('a').onclick();
break;
case Event.KEY_ESC:
break;
case Event.KEY_TAB:
return;
default:
if( !this.is_open() ) this.open();
return;
}
Event.stop(ev); // so "enter" doesn't submit the form, among other things(?)
},
/**
* keyboard navigation - where to intercept the keys is up to the concrete class
*/
onkeydown: function(ev) {
var elem;
switch (ev.keyCode) {
var elem;
switch (ev.keyCode) {
case Event.KEY_UP:
if( !this.is_open() ) this.open();
if (this.current && this.current.up('.record-select')) elem = this.current.previous();
if (!elem) elem = this.container.getElementsBySelector('ol li.record').last();
this.highlight(elem);
break;
case Event.KEY_DOWN:
if( !this.is_open() ) this.open();
if (this.current && this.current.up('.record-select')) elem = this.current.next();
if (!elem) elem = this.container.getElementsBySelector('ol li.record').first();
this.highlight(elem);
break;
case Event.KEY_RIGHT:
if( !this.is_open() ) this.open();
elem = this.container.down('li.pagination.next');
if (elem) elem.down('a').onclick();
break;
case Event.KEY_LEFT:
if( !this.is_open() ) this.open();
elem = this.container.down('li.pagination.previous');
if (elem) elem.down('a').onclick();
break;
case Event.KEY_TAB:
case Event.KEY_ESC:
this.close();
break;
default:
return;
}
},

/**
* moves the highlight to a new object
*/
highlight: function(obj) {
if (this.current) this.current.removeClassName('current');
this.current = $(obj);
obj.addClassName('current');
}
});


追記:修正部分が足りてませんでした。追加しました。
2010/06/11 追記:keypress イベントにもリスト再表示のコードを挿入しました。
2010/07/29 追記:tab イベント時の処理がまずかったので、修正。元のコードの方がすっきりしているので、この改造は本末転倒だったかも…

0 件のコメント: