2017-07-25 12 views
0

現在、純粋なJavaScriptでドロップダウンコンポーネントを作成しています。ユーザーがドロップダウン・トグルをクリックすると、コンテンツ・ゲインのフォーカスとそのコンテンツが表示されます。ユーザーがその外部をクリックすると、コンテンツのフォーカスが失われ、非表示になります。ハンドルのドロップダウンのフォーカス状態

これまでのところ、それは素晴らしい作品です。しかし、私は2つの問題に直面しています。

最初のものは、ドロップダウン内の要素(アンカータグなど)がクリックされたときに、ドロップダウンでフォーカスが失われるということです。

2番目の問題は、ドロップダウンコンテンツが表示されているときにドロップダウントグルをクリックしたときに、ドロップダウントグルに登録されたクリックのために閉じるのではなく、閉じることです。

HTML:

<div class="dropdown"> 
    <a href="#" class="dropdown-toggle">Dropdown toggle</a> 
    <div class="dropdown-content" tabindex="0"> 
     <ul> 
      <li> 
       <a href="http://example.com">My profile</a> 
      </li> 
      <li> 
       <a href="http://example.com">Log out</a> 
      </li> 
     </ul> 
    </div> 
</div> 

CSS:

.dropdown { 
    position: relative; 
} 

.dropdown.is-open .dropdown-content { 
    display: block; 
} 

.dropdown-content { 
    display: none; 
    position: absolute; 
    top: 100%; 
    width: 100%; 
    padding: 0.5rem 0; 
    background: #fff; 
    box-shadow: 0 1px 2px rgba(0, 0, 0, 0.5); 
} 

JS:

class Dropdown { 

    constructor(element) { 
     this.element = element; 
     this.toggle = this.element.querySelector('.dropdown-toggle'); 
     this.content = this.element.querySelector('.dropdown-content'); 

     this.bindings(); 
    } 

    bindings() { 
     this.toggle.addEventListener('click', this.open.bind(this)); 
     this.content.addEventListener('keydown', this.handleKeyDown.bind(this)); 
     this.content.addEventListener('focusout', this.close.bind(this)); 
    } 

    open(e) { 
     e.preventDefault(); 
     this.element.classList.add('is-open'); 
     this.content.focus(); 
    } 

    close(e) { 
     this.element.classList.remove('is-open'); 
    } 

    handleKeyDown(e) { 
     if (e.keyCode === 27) { 
      this.close(e); 
     } 
    } 

} 

document.querySelectorAll('.dropdown').forEach(dropdown => new Dropdown(dropdown)); 

私は運なしでこれらの問題を解決する方法を上まわりで私の頭を取得しようとしてきました。どのようにこれらの問題を解決するための任意のアイデア?

+1

CSSを追加すると、質問が少し明確になる場合があります。そして、私はあなたが追加と削除の代わりにclassListの 'toggle'メソッドを望むかもしれないと思います。 https://developer.mozilla.org/en-US/docs/Web/API/Element/classList – Will

+0

フィードバックに感謝します。私はCSSを追加しました。トグルに関しては、私は専門家ではありませんが、特に両方が異なる機能にあるため(たとえば両方がtoggleDropdownメソッドにあったのではないため)、追加と削除を使用する方が明白です。代わりにトグルを使用する理由は何か特別な理由はありますか? – scorchy

+0

@scorchyリンクをクリックするたびにクラスを追加するのではなく、クラスを切り替えるたびに2番目の問題を防ぐオープン関数に少なくともトグルを追加する必要があります。あなたの期待する行動はどちらですか? – SimplyComplexable

答えて

0

いくつかのテストの後、私はうまくいくソリューションを見つけました。以下のコードを試してください

 class Dropdown { 

      constructor(element) { 
       this.element = element; 
       this.toggle = this.element.querySelector('.dropdown-toggle'); 
       this.content = this.element.querySelector('.dropdown-content'); 

       this.bindings(); 
      } 

      bindings() { 
       this.toggle.addEventListener('click', this.open.bind(this)); 
       this.content.addEventListener('keydown', this.handleKeyDown.bind(this)); 
       this.element.addEventListener('focusout', this.onFocusOut.bind(this),true); 
      } 
      onFocusOut(e) { 
       if (!this.element.contains(e.relatedTarget)) { 
        this.close(e) 
       } 
      } 

      open(e) { 
       e.preventDefault(); 
       this.element.classList.toggle('is-open'); 
       this.content.focus(); 
      } 

      close(e) { 
       e.preventDefault(); 
       this.element.classList.remove('is-open'); 
      } 

      handleKeyDown(e) { 
       if (e.keyCode === 27) { 
        this.close(e); 
       } 
      } 

     } 
+0

ありがとうございました!私はちょうど試して、それは最初の問題を解決した。ただし、ドロップダウントグルをクリックすると、ドロップダウンを再び開くのではなく、ドロップダウンを閉じる必要があります。万が一この問題を解決する方法をご存知ですか? – scorchy

+0

@scorchy最後のリビジョンが1つあり、すべてが機能しています。わかりやすくするために、私はfocusoutイベントを内容だけでなく要素全体に更新しました。私はまた、open関数の内部を切り替えるためにadd関数を変更しました。ご質問がある場合はお知らせください。 – SimplyComplexable

+1

私はうまく動作しているように見える、ありがとう!私はあなたの記事を答えとして受け入れました。 – scorchy

関連する問題