Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fixed focus movement within a modal. #87

Open
wants to merge 6 commits into
base: master
Choose a base branch
from

Conversation

1000-x-t30
Copy link

No description provided.

@1000-x-t30 1000-x-t30 linked an issue Jun 29, 2023 that may be closed by this pull request
Copy link
Contributor

@uidev1116 uidev1116 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@1000-x-t30
気になったところコメントつけさせていただきました。
ご確認よろしくお願いします。:bow:

@@ -306,13 +305,33 @@ export default class SmartPhoto extends ATemplate {
this.data.currentIndex = parseInt(element.getAttribute('data-index'), 10);
this._setHashByCurrentIndex();
const currentItem = this._getSelectedItem();

const onFocus = (e) => {
if(e.keyCode === 9) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@1000-x-t30
KeyboardEvent.keyCode は非推奨になってるみたいなので、KeyboardEvent.key を活用したほうがプログラムが長持ちしそうです。

https://developer.mozilla.org/ja/docs/Web/API/KeyboardEvent/keyCode

念のためIEも対応したい場合は↓とかでもいいかもです。
いかがでしょうか?

e.key === 'Tab' || e.keyCode === 9;

class="\{classNames.smartPhotoDismiss\}"
data-action-click="hidePhoto()">
<span class="smartphoto-sr-only">\{message.closeDialog\}</span>
</button>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@1000-x-t30
おそらく button タグの位置が変わったためだと思うのですが、バツボタンをクリックしても hidePhoto が実行されなくなってしまってます。!!

修正お願いします。!!


const onFocus = (e) => {
if(e.keyCode === 9) {
const smartPhoto = document.querySelector(`.${this.data.classNames.smartPhoto}`);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@1000-x-t30
すみません。この実装だとTabを押してフォーカスを移動させたときは良いのですが、shift + Tab でフォーカスを戻ったときに、フォーカスがモーダルの外に行ってしまいます。

以下は jQuery での例ですが、ライブラリを利用しない場合はこんな感じが良いかもです。

   var focusableElements = 'a[href], area[href], input:not([disabled]), select:not([disabled]), textarea:not([disabled]), button:not([disabled]), object, embed, *[tabindex], *[contenteditable]';
    var $first = $modal.find(focusableElements).filter(":visible").first();
    var $last = $modal.find(focusableElements).filter(":visible").last();
    $first.off('keydown.acms-dialog').on('keydown.acms-dialog', function (e) {
      if ((e.which === 9 && e.shiftKey)) {
        e.preventDefault();
        $last.focus();
      }
    });
    $last.off('keydown.acms-dialog').on('keydown.acms-dialog', function (e) {
      if ((e.which === 9 && !e.shiftKey)) {
        e.preventDefault();
        $first.focus();
      }
    });
    $first.focus();

修正よろしくお願いします。!!

Comment on lines 330 to 334

const smartPhoto = document.querySelector(`.${this.data.classNames.smartPhoto}`);
smartPhoto.focus();
document.addEventListener('keydown', onFocus);
this._registerRemoveEvent(window, 'keydown', onFocus);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@1000-x-t30

ここですが、数行下にも同じ処理があるので、if ~ else の外で1回の処理で済ませたほうが良いかと思いました。
また、そもそも addNewItem 内でやらなくてもいい気がしてます…。

ご検討よろしくお願いします。:bow:

@@ -321,7 +340,12 @@ export default class SmartPhoto extends ATemplate {
this.update();
body.style.overflow = 'hidden';
this._fireEvent('open');
});

const smartPhoto = document.querySelector(`.${this.data.classNames.smartPhoto}`);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@1000-x-t30
以下のような処理がいくつか出てきますが、.${this.data.classNames.smartPhoto} の要素がHTML上に存在した場合に意図した挙動にならないかと思いますので、[data-id='${this.id}'] を前につけてあげたほうが良いかもです。

lite-editor のコードが参考になるので共有します。
https://github.com/appleple/lite-editor/blob/101a3b4f93a4a0198503cf84260711425e6d276a/src/core/index.js#L299

ご確認よろしくお願いします。!:bow:

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@1000-x-t30
すみません。こちら意図が正しく伝えられてなかったです。
結論としては、要素を取得する場合には this._getElementByClass メソッドを活用してくださいというところになります。

data-id="className" を取得したい要素につけるでも悪くはないのですが、不要な data-id が乱立するのでスマートではないと思いますがいかがでしょうか?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@uidev1116
なるほど...
モーダル自身のdata-idを利用し詳細度を高くするということですね!
確かに不要なdata-idを増やさずに安全に実装できると思います、ありがとうございます🙇

Copy link
Contributor

@uidev1116 uidev1116 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

コメントしました。!


_onFocus(e) {
const smartPhoto = document.querySelector(`[data-id='${this.data.classNames.smartPhoto}']`);
const dismiss = document.querySelector(`[data-id='${this.data.classNames.smartPhotoDismiss}']`);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@1000-x-t30
ここですが、smartPhoto 及び dismiss の要素を取得したいのではなく、モーダル内でフォーカス可能な最初と最後の要素を取得したいということだと思うので、モーダル内でフォーカス可能な最初と最後の要素を取得するという実装にしませんか?

現状の問題点は、今後、viewer.html のテンプレートを変更して、smartPhoto 及び dismiss がモーダル内でフォーカス可能な最初と最後の要素でなくなった場合に、_onFocusメソッド内も変更する必要があることです。

ご確認よろしくお願いします。:bow:

if (eventName === 'open') {
const smartPhoto = document.querySelector(`[data-id='${this.data.classNames.smartPhoto}']`);
smartPhoto.focus();
}
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@1000-x-t30
_fireEvent メソッドはイベントを発火することが責任なので、その中で副作用となる処理を書いてしまうと保守しづらくなってしまうため修正お願いしたいです。

addNewItem メソッドで実際に open イベントを発火しているところで書くべきかと思います。

ご確認よろしくお願いします。:bow:

@@ -323,6 +323,8 @@ export default class SmartPhoto extends ATemplate {
this._fireEvent('open');
});
}
document.addEventListener('keydown', this._onFocus.bind(this));
this._registerRemoveEvent(window, 'keydown', this._onFocus);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@1000-x-t30
実際に検証できてないので申し訳ないのですが、bind してaddEventListener した関数を removeEventListener できるのでしょうか?

以下のように、そのままでは別の関数として判別されてしまい、removeEventListener できないような気がしてます。
https://log.tkyisgk.com/addeventlistener-this

ご確認よろしくお願いします。:bow:

@1000-x-t30 1000-x-t30 self-assigned this Sep 21, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Focus not trapped when image is opened
2 participants