プログラミング

【jQuery】移動式マルチプルフォームの作り方【sortable】

HTML JavaScript jQuery jQuery UI
【jQuery】移動式マルチプルフォームの作り方【sortable】

     

    移動式マルチプルフォーム

     

     

    デモページ

     

    htmlの標準マルチプルフォームは、選択したものに色が付く仕様ですが、数が多くなってくると選択しているものがわかり難いということや、並び順の変更がしにくいという難点があります。そういった条件も込みで再現するような選択要素移動式のフォームをご紹介します。

     

    以下サンプルコードです。 

    <!-- head -->
    <script
    src="https://code.jquery.com/jquery-3.5.1.min.js"
    integrity="sha256-9/aliU8dGd2tb6OSsuzixeV4y/faTqgFtohetphbbj0="
    crossorigin="anonymous"></script>
    <script
    src="https://code.jquery.com/ui/1.12.1/jquery-ui.min.js"
    integrity="sha256-VazP97ZCwtekAsvgPBSUwPFKdrwD3unUfSGVYrahUqU="
    crossorigin="anonymous"></script>
    
    <style>
    form{
        max-width: 300px;
        margin-bottom: 16px;
    }
    .flexbox{
        display: flex;
        margin-bottom: 8px;
    }
    .box{
        margin: 0 8px;
    }
    .select-box{
        width: 150px;
        height: 200px;
        overflow-y: scroll;
        background-color: #DDD;
        padding: 4px;
    }
    .item{
        color: #FFF;
        background-color: #888;
        cursor: pointer;
    }
    .item:not(:last-child){
        margin-bottom: 4px;
    }
    .result{
        padding: 4px;
    }
    </style>
    <!-- body -->
    <form action="" method="post">
        <div class="flexbox">
            <div class="box">
                <span>未選択</span>
                <div class="select-box">
                    <div class="item" data-val="item1">
                        アイテム1
                    </div>
                    <div class="item" data-val="item2">
                        アイテム2
                    </div>
                    <div class="item" data-val="item3">
                        アイテム3
                    </div>
                </div>
            </div>
            <div class="box">
                <span>選択済み</span>
                <div class="select-box selected">
                </div>
            </div>
        </div>
        <input type="submit" value="送信">
    </form>
    
    <div class="result">
        <div class="box">
            <span>送信結果</span>
            <pre><?php var_export($_POST); ?></pre>
        </div>
    </div>
    
    <script type="text/javascript">
    $(document).ready(function() {
        $( ".select-box" ).sortable({
            connectWith: ".select-box"
        })
        .bind("sortremove", function(event, ui) {
            var obj = ui.item;
            if (obj.parent(".select-box").hasClass("selected")) {
                // 選択済みエリアに移動してきたらinputを付与
                var val = obj.data("val");
                obj.append(
                    '<input type="hidden" name="select[]" value="' + val + '">'
                );
            } else {
                // 未選択テーブルに移動してきたらinputを削除
                obj.find("input").remove();
            }
        });
    });
    </script>

     

     

    jQueryとUIの読み込み

     

    まずは必要ライブラリを読み込みます。今回はjQuery UIのsortableを使用するので、jQueryとjQuery UIが必要です。CDNでの読み込み方法は以下の通りです。

    <script src="https://code.jquery.com/jquery-3.5.1.min.js" integrity="sha256-9/aliU8dGd2tb6OSsuzixeV4y/faTqgFtohetphbbj0=" crossorigin="anonymous"></script>
    <script src="https://code.jquery.com/ui/1.12.1/jquery-ui.min.js" integrity="sha256-VazP97ZCwtekAsvgPBSUwPFKdrwD3unUfSGVYrahUqU=" crossorigin="anonymous"></script>

     

     

    ブロック要素を使った構成

     

    まずはHTML部分から確認していきます。今回はdivを使って擬似的にマルチプル形式のフォームを作成しています

    まずはデータを飛ばすために、全体をform要素で囲っていますが、送信ボタンも含めて必要なエリアだけが囲えていれば問題ありません。

     

    マルチプル部分で重要なポイントは以下boxの下層部分です。 

    <div class="box">
        <span>未選択</span>
        <div class="select-box">
            <div class="item" data-val="item1">
                アイテム1
            </div>
            <div class="item" data-val="item2">
                アイテム2
            </div>
            <div class="item" data-val="item3">
                アイテム3
            </div>
        </div>
    </div>
    
    <div class="box">
        <span>選択済み</span>
        <div class="select-box selected">
        </div>
    </div>

     

    sortableで移動させる両エリアを判定するために、select-boxというクラスを指定しています。これはライブラリに依存している名称ではないので、自由に決めてもらって構いません。

    選択済みボックスには、それを判別できるように追加でselectedというクラスを付与しています。こちらも未選択との違いを判別できるのであれば名称は自由です。

    次に、itemについてです。これがselectボックスでのoptionの代わりの要素です。itemに付与しているデータ属性(data-val)は、本来optionに付与するvalueの代わりに使用しています。今回はアイテム1、2、3と準備したので、それぞれにitem123と命名しました。

    最後に送信ボタンを準備すれば、HTML部分は完了です。

     

     

    multipleを使用しない理由

     

    selectmultipleを使っても、左右間の移動は可能です。以下のサイトでその方法が紹介されています。

    ※他にも実用的な多くサンプルが紹介されているので、ぜひ参考にしてください

     

    並び順を重視しないのであれば、multipleフォームが使用できるため、データを送信するという点においてはsortableもつよう実装は簡単です。しかし、フレキシブルに送信データを決めることができないのが欠点です。

    また、行としてoptionを選択するため、マルチプルの場合は1行に複数要素を含めることが出来ませんdiv要素等で生成すれば、1行にidname、チェックの有無などを含めることが可能です。

     

     

    tableを使用しない理由

     

    tableを使えば、行づくりはより簡単に実装することが可能です。もし1行に複数要素を含めるとしても、より簡単に実装でき向いていると言えます。

    しかしtableで作成すると、選択済みボックスの方に問題が残ります。行がなければ高さが0になってしまうため、移動エリアが無くなってしまうのです。そうならないため、高さの指定ができるブロック要素であるdivを採用しました。

     

     

    動的なinput要素

     

    div要素で構成している以上、データを送信するためにはinput要素を準備しなければなりません。しかし、最初からinput要素をアイテム内に配置してしまえば、未選択データもPOSTすることになります。そうならないためにも、sortableで移動した先が選択済みかどうかを判定して、input hiddenを追加します。

     

    それでは、sortableの内容と合わせて確認してみましょう。

    $( ".select-box" ).sortable({
        connectWith: ".select-box"
    })

     

    まずは、sortableの宣言です。select-boxのクラスに対してメソッドをつなげています。sortableのオプションには、connectWith指定しています。ここにselect-boxを宣言することで、全てのselect-box内で要素の移動ができるようになっています。

     

    次に要素移動時の処理をsortableにつなげます。

    .bind("sortremove", function(event, ui) {
        var obj = ui.item;
        if (obj.parent(".select-box").hasClass("selected")) {
            // 選択済みエリアに移動してきたらinputを付与
            var val = obj.data("val");
            obj.append(
                '<input type="hidden" name="select[]" value="' + val + '">'
            );
        } else {
            // 未選択テーブルに移動してきたらinputを削除
            obj.find("input").remove();
        }
    });

     

    そのままbindのメソッドをつなげて、sortremoveでコールバック関数を指定しています。この関数内に移動後の処理を記述していきます。

     

    ui.itemには移動してきたアイテム(class=”item”)が該当します。移動後、そのアイテムが未選択エリアにいるのか、選択済みエリアにいるかを確認するため、条件分岐でselect-boxの要素にselectedクラスが含まれているかをhasClass(“selected”)でチェックします。

    もし、selectedのエリアに移動してきたのであれば、input要素を付与します。 

    // 選択済みエリアに移動してきたらinputを付与
    var val = obj.data("val");
    obj.append(
        '<input type="hidden" name="select[]" value="' + val + '">'
    );

     

    ここで使用するのが、data-valです。これをdata(“val”)で取得して、アイテム要素の後ろにappendhiddenで追加します。これで、選択済みエリアに移動すればinput要素が付与されているため、データを送信することができます。

    もし一度選択済みエリアへ移動して、未選択エリアに戻ってきた場合はinput要素は不要です。そのため、条件分岐でのelse内にinput要素を取り除く記述を追加します。

    // 未選択テーブルに移動してきたらinputを削除
    obj.find("input").remove();

     

    これで、左右移動型疑似マルチプルフォームが完成です。

    デモページ 

     

     

    配列での送信

     

    最後に送信データの形式についてです。

    疑似ではありますが、multipleで送られてきたデータがバラバラになっていると処理をしづらくなります。そうならないためにも、input要素は配列として受け渡します。

    name="select[]"

     

    こうすることで、POSTすればselect内に選択済みの要素が上から順番に格納されます。

    # 送信結果
    array (
      'select' =>
      array (
        0 => 'item2',
        1 => 'item1',
      ),
    )

     

    もし1行に複数要素を含めて送信する場合も、配列として管理するようにしましょう。そうすれば受け取り側の処理も簡単になります。

     

     

    まとめ

     

    いかがだったでしょうか。

    今回はjQuery UIsortableを使ったフレキシブルな「移動式マルチプルフォームの作り方」をご紹介しました。

    複雑なデータ登録をする際には非常に役立つ方法ですので、システム要素の強いフォームや、直感的で使いやすいフォームを実装したいと考えている方は、ぜひ参考にしてくださいね。

     

    注目の記事

    なぜプロは有線のマウスやキーボードを選ぶのか?【有線VS無線】
    雑記
    Bluetooth
    なぜプロは有線のマウスやキーボードを選ぶのか?【有線VS無線】

      無線が普及する現代、何故有線のマウスやキーボードは売れているのか   いろんなものが製品の進化と共に無線化している一方、有線の需要も高く、とくにプロなど上層で活躍する人は有線を選択するケースが少なくありません。 今回は、そんな有線と無線の違いや、それぞれのメリットについて解説していき...

    PHPポケモン「バトルシステム実装編〜ランク補正〜」22
    プログラミング
    PHP,PHPポケモン,ポケモン
    PHPポケモン「バトルシステム実装編〜ランク補正〜」22

    ランク補正とは  ポケモンでは通常ステータスとは違い、バトル中にのみ変化するステータスが存在します。初代仕様であれば、「なきごえ」や「かたくなる」といった変化技により「こうげき」や「ぼうぎょ」の強化や弱体化をさせるものです。これはバトル中であれば引き継がれるものですが、交代やバトルが終了すればリ...

    パーティー実装編 戦闘に参加するポケモン PHPポケモン64
    プログラミング
    PHP,PHPポケモン,ポケモン
    パーティー実装編 戦闘に参加するポケモン PHPポケモン64

    先頭のポケモンを選出 前回パーティーのプロパティを準備して、複数(6匹)のポケモンを持ち歩けるようにすることを想定しました。 今回は、そこからバトル画面への連動をさせる部分までを作り込んでいきましょう。   複数のポケモンを所有している場合、戦闘が始まって繰り出されるのは「ひんし状態を除く一番上...

    プログラミングを優しく解説!学んで得する3つの理由
    プログラミング
    プログラミング教育
    プログラミングを優しく解説!学んで得する3つの理由

      プログラミング教育が始まるけど、そもそもよくわかっていない   2020年からは小学校がプログラミング学習が必修化され、翌年には中学校でも導入予定です。 しかし、保護者からすると全くわからず困惑していたり、教える先生たち教師陣からしてもよくわかっていないケースは少なくありません。   今回...

    バズる!ビジネスの見つけ方 〜何で起業するか悩んでいませんか?〜
    マーケティング
    ビジネス,起業
    バズる!ビジネスの見つけ方 〜何で起業するか悩んでいませんか?〜

      独立や起業を志している9割以上の人が「何をビジネスにするか?」を悩んでいます しかし、それは負のサイクルです。 起業するためにビジネスを考えるという行為自体が”矛盾している”ということに気づかなければ、このサイクルからは抜け出すことができません。 その結果、行動できずに終わってしまう人は多...

    保守っていくらで何をする?フリーランスWebエンジニア対象!保守業務について解説します
    フリーランス
    システムエンジニア,フリーランス,プログラマー
    保守っていくらで何をする?フリーランスWebエンジニア対象!保守業務について解説します

      サイトの保守を頼まれたけど、具体的に何をやればいいの?   フリーランスの、特に独学やスクール上がりでなった人にとっては保守は何をすれば良いかわからないという悩みを抱えている人は多いのではないでしょうか。 システム開発会社や制作会社にいた人でも、どのぐらいの金額で請け負うのが良いか検...

    EC-CUBE4内にWordPressを設置(共存)する方法
    SEO対策,プログラミング
    EC-CUBE4,PHP,Symfony,Twig,WordPress
    EC-CUBE4内にWordPressを設置(共存)する方法

    今回使用したバージョン EC-CUBE4.0.5 WordPress5.6 ※EC-CUBE4、WordPressのカスタマイズは自己責任でお願いします。また、現在稼働中のサイトで試す際には、必ずバックアップを取ってから行なうようにしてください。   EC-CUBE4とは ネットショップを作るとなれば、様々なサービスが出回っ...

    データベース定義は超重要!システム開発を始める前に知っておきたい構造と構成の考え方
    プログラミング
    MySQL,データベース,プログラミング学習
    データベース定義は超重要!システム開発を始める前に知っておきたい構造と構成の考え方

      システムやアプリ開発をする場合、そのほとんどでデータベースを使用しますね。 それぞれのデータを連携させるためにも、その構造をどうするかは重要で、設計が甘ければシステムそのものの保守性はもちろん、想定していた仕組みを実現するのが難しくなることもあります。   今回は、これからデータベースを...

    カテゴリ

    SEO対策 イベント デザイン ネットワーク ビジネスモデル フリーランス プログラミング マーケティング ライティング 動画編集 雑記

    タグ

    5G Adobe AfterEffects AI ajax amazon Animate api artisan atom Automator AWS Bluetooth CSS CVR description EC-CUBE4 ECショップ ESLint Facebook feedly foreach function Google Google AdSense Honeycode htaccess HTML IEEE 802.11ax Illustrator Instagram IoT JavaScript jQuery jQuery UI keyword LAN Laravel Linux MacBook MAMP meta MLM MySQL NoCode note OS OSI参照モデル Paypal Photoshop PHP phpMyAdmin PHPポケモン PremierePro rss SEO SEO対策 Sequel Pro Skype SNS SSH Symfony TCP/IP title Toastr Trait Twig Twitter UCC V系 WAN WebSub Wi-Fi wiki Windows WordPress XAMPP xml Xserver YouTube YouTuber Zoom アーティスト アウトプット アクセス層 アニメーション アフィリエイト イーブイ インターネット インプット エンジニア オブジェクト指向 お金配り クリック単価 クリック数 コミュニケーション能力 コロナ コンサルティング サムネイル システムエンジニア スタートアップ スタイルシート スパム データベース ディープフェイク デザイナー デザイン テレワーク ナンパ ニュース ネットワークモデル ノマドワーク バナー ピカチュウ ビジネス フィード フリーランス ブロガー ブログ プログラマー プログラミング プログラミング学習 プログラミング教育 プロトコル ホームページ制作 ポケモン マークアップ マーケティング メール リモートワーク レンダリング 三井住友 三宮 仕事依頼 児童デイ 児童デイサービス 児童発達支援 公開鍵 初心者 助成金 勉強法 営業 広告 広告収入 必勝マニュアル 放課後等デイサービス 朝活 楽天 深層学習 無線LAN 独立 神戸 福祉 秘密鍵 翻訳 自己啓発 英語 見積書 計算機 読書 起業 迷惑メール 配列 銀の弾丸 集客 雑学力