0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

カテゴリープルダウン機能の実装

Last updated at Posted at 2020-06-11

 某プログラミングスクールの最終課題において、カテゴリープルダウン機能(トップページのヘッダーにあるカテゴリーという文字に触れるとプルダウンでカテゴリーが表示される機能)を実装したので、自分のアウトプットのためにも解説していきたいと思います。
スクリーンショット 2022-02-23 152058.jpeg

早速ですが、プルダウン機能実装の流れは以下の通りとなります。

① カテゴリーの文字に触れる

② jQueryでイベントが発生し、カテゴリーに貼られているリンクを読み取る

③ そのリンクでAjax通信を行い、取得したカテゴリーID(0の場合は親要素)に応じて子要素をデータベースから取得し、json形式で値を戻す。

④ 後は、取得したデータをHTMLの形に組み直して、カテゴリーの文字の下に付け加えるだけです。

⑤ 子要素に対しても、以上と同様な流れで表示し、孫要素までいくと表示されないようにしています。

これを実現したソースコードは以下の通りとなります。(該当する部分だけ抜き出しています)

_header.html.haml
.header-bottom-left-category
  .header-bottom-left-category-title
    = link_to categories_path ,class:"category_name", data:{category_id:0} do
      %i.fas.fa-list
        カテゴリから探す
  .header-bottom-left-category-field   
categories_pulldown.js
$(function(){

  // プルダウンのHTMLを生成
  function buildHTML(categories){

    var link_tag, outline = $("<ul>");
    var link_class =$(".header-bottom-left-category-title").find("a").attr("class")
    var base_href = $(".header-bottom-left-category-title").find("a").attr("href") + "/";

    categories.forEach(function(category){
      link_tag = $("<a>", { href: base_href + category.id ,"class":link_class }).text(category.name)
      link_tag = $("<li>").append(link_tag)
      outline.append(link_tag)
    })

    return outline

  }
  
  // カーソルが触れたときに起動
  $(document).on({

    // カーソルが乗ったときに起動
    'mouseenter' : function(enter_event) {
      
      // mouseoverのデフォルト動作をクリアする
      enter_event.preventDefault();

      // カテゴリーのIDを取得できた場合には、子要素を取得
      $.ajax({
        url: $(this).attr("href"),
        type: "GET",
        dataType: "json",
        context: this,
        cache: false
      })
      .done(function(categories){

        // 子要素がなければ選択肢を表示しない
        if( categories.length > 0 ){

          // 「カテゴリから探す」以外に触れたら一掃する
          if( $(this).data("category-id") == 0){
            $(".header-bottom-left-category-field").empty();
          }

          // それ以外の場合は自分の後に表示されている子要素を削除する
          else{
            $(this).closest("ul").nextAll().remove()
          }

          // 選択したフォームの下に新たなフォームを追加
          var html = buildHTML(categories)
          $(".header-bottom-left-category-field").append(html)
        }
          
      })
      .fail(function(error){
        alert(error)
      })
    },
    
    // カーソルが離れたときに起動
    'mouseleave' : function(leave_event){

      // mouseleaveのデフォルト動作をクリアする
      leave_event.preventDefault();

      // 出る前と後の親要素のインデックスを取得する。
      var old_parent = $(this).closest("ul").index();
      var new_parent = $(leave_event.relatedTarget).closest("ul").index();

      // 子要素へ移る場合はオレンジ色のままにする
      if( old_parent < new_parent ){
        $(this).css("color","orange");
      }

      // 親要素に移る場合には、その先の要素全てを黒にする。
      else if(old_parent > new_parent ){
        $(leave_event.relatedTarget).closest("ul").find("a").css("color","");
      }

    }
  },".category_name");

  // カテゴリーリストからカーソルが離れたらすべて消す
  $(".header-bottom-left-category").mouseleave(function(){
    $(".header-bottom-left-category-field").empty();
    $(".header-bottom-left-category-title").find("a").css("color","");
  })

})
routes.rb
 resources :categories, only: [:index,:show]
categories_controller.rb
class CategoriesController < ApplicationController

  def index

    @categories = Category.where(ancestry:nil)

    respond_to do |format|
      format.html
      format.json{
        render json: @categories
      }
    end 
  end

  def show

    @category = Category.find(params[:id])
    @categories = @category.children

    respond_to do |format|
      format.html
      format.json{
        render json: @categories
      }
    end 

  end

end

_header.scss
 & a {
      color:black;
      padding:10px;
      display: block;
      text-decoration: none;
      &:hover {
        color:orange;
      }
    }
    > div {
      display: flex;
    }
    &-left{
      &-category {
        position: relative;
        &-field {
          position: absolute;
          display: flex;
          background-color:white;
          z-index:1;
          & ul {
            width:200px;
          }
        }
      }
    }

(※)自分の環境に合うようにしてから、使用していただくようお願いします。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?