LoginSignup
15
0

More than 3 years have passed since last update.

jQueryとjQuery Mobileでcloneしてみた

Last updated at Posted at 2020-12-12

はじめに

この記事の筆者はひよっこWebエンジニア(2年目)で、jQueryとJavaScriptはほぼ未経験です。
温かい目で見ていただけると幸いですm(_ _)m
コード例はPHPで動的に書いたものを説明しやすくするためにHTMLに書き直し、なおかつ読みやすいように調整したものですので、間違っているかもしれません。

背景

自社サービスにおいて、cloneを使う機会があったので、
また使う事になったときのためにまとめておくことにしました。

使った技術

  • PHP
  • JS
    • jQuery
    • jQuery Mobile
  • CSS
    • jQuery
    • jQuery Mobile

jQuery編

コード例

<table>
    <tr id="like_fruits_1">
        <th>
            <label>好きなフルーツ</label>
            <input type="hidden" id="like_fruits_count" value="1">
        </th>
        <td>
            <select name="fruits[1]" class="select">
                <option value="">--</option>
                <option value="apple">りんご</option>
                <option value="orange">オレンジ</option>
                <option value="water_melon">スイカ</option>
                <option value="melon">メロン</option>
            </select>
            <button type="button" id="add_like_fruits_button" class="button button-pill button-primary" style="width: 100px;"><i class="fa fa-plus-square"></i> 追加</button>
            <button type="button" id="delete_like_fruits_button" class="button button-pill button-caution" style="width: 100px;"><i class="fa fa-trash"></i> 削除</button>
        </td>
    </tr>

    <tr id="clone_like_fruits_template" style="display: none">
        <th></th>
        <td>
            <select name="fruits[xxx]" class="select">
                <option value="">--</option>
                <option value="apple">りんご</option>
                <option value="orange">オレンジ</option>
                <option value="water_melon">スイカ</option>
                <option value="melon">メロン</option>
            </select>
        </td>
    </tr>
</table>

<script type=text/javascript>
    $(document).ready(function() {
        // 削除ボタンを無効化する
        $('#delete_like_fruits_button').prop('disabled', true);
    });

    // 追加ボタンをクリックしたときの処理
    $(document).on('click', '#add_like_fruits_button', function() {
        // 追加ボタンが押下されたら削除ボタンを有効化する
        $('#delete_like_fruits_button').prop('disabled', false);

        // 今ある要素数を取得
        let creation_times = +$('#like_fruits_count').val();

        // 追加したあとの要素数を保存
        $('#like_fruits_count').val(creation_times + 1);

        // clone_like_fruits_templateのクローンを作成
        let copy = $('#clone_like_fruits_template').clone(true);

        // xxxを置換
        copy.html(function(i, oldHTML) {
            return oldHTML.replace(/xxx/g, creation_times+1)
        });

        // styleを外す。
        copy.prop('style', false);

        // 属性を付加する
        copy.attr('id', 'like_fruits_'+(creation_times+1));

        // 現要素の一番最後に格納
        copy.insertAfter('#like_fruits_'+creation_times);
    });

    // 削除ボタンをクリックしたときの処理
    $(document).on('click', '#delete_like_fruits_button', function() {
        // 今ある要素数を取得
        let creation_times = +$('#like_fruits_count').val();

        // 削除した後の個数を保存する
        $('#like_fruits_count').val(creation_times - 1);

        // 項目の一番最後の行を削除する
        $('#like_fruits_'+creation_times).remove();

        // 一番最初の要素は消せないように削除ボタンを無効化する
        if (creation_times <= 2) {
            $('#delete_like_fruits_button').prop('disabled', true);
        }
    });
</script>

で定義して、「追加」を押すと、

<table>
    <tr id="like_fruits_1">
        <th>
            <label>好きなフルーツ</label>
            <input type="hidden" id="like_fruits_count" value="2">
        </th>
        <td>
            <select name="fruits[1]" class="select">
                <option value="">--</option>
                <option value="apple">りんご</option>
                <option value="orange">オレンジ</option>
                <option value="water_melon">スイカ</option>
                <option value="melon">メロン</option>
            </select>
            <button type="button" id="add_like_fruits_button" class="button button-pill button-primary" style="width: 100px;"><i class="fa fa-plus-square"></i> 追加</button>
            <button type="button" id="delete_like_fruits_button" class="button button-pill button-caution" style="width: 100px;"><i class="fa fa-trash"></i> 削除</button>
        </td>
    </tr>

    <tr id="like_fruits_2">
        <th></th>
        <td>
            <select name="fruits[2]" class="select">
                <option value="">--</option>
                <option value="apple">りんご</option>
                <option value="orange">オレンジ</option>
                <option value="water_melon">スイカ</option>
                <option value="melon">メロン</option>
            </select>
        </td>
    </tr>

    <tr id="clone_like_fruits_template" style="display: none">
        <th></th>
        <td>
            <select name="fruits[xxx]" class="select">
                <option value="">--</option>
                <option value="apple">りんご</option>
                <option value="orange">オレンジ</option>
                <option value="water_melon">スイカ</option>
                <option value="melon">メロン</option>
            </select>
        </td>
    </tr>
</table>

<script type=text/javascript>
    $(document).ready(function() {
        // 削除ボタンを無効化する
        $('#delete_like_fruits_button').prop('disabled', true);
    });

    // 追加ボタンをクリックしたときの処理
    $(document).on('click', '#add_like_fruits_button', function() {
        // 追加ボタンが押下されたら削除ボタンを有効化する
        $('#delete_like_fruits_button').prop('disabled', false);

        // 今ある要素数を取得
        let creation_times = +$('#like_fruits_count').val();

        // 追加したあとの要素数を保存
        $('#like_fruits_count').val(creation_times + 1);

        // clone_like_fruits_templateのクローンを作成
        let copy = $('#clone_like_fruits_template').clone(true);

        // xxxを置換
        copy.html(function(i, oldHTML) {
            return oldHTML.replace(/xxx/g, creation_times+1)
        });

        // styleを外す。
        copy.prop('style', false);

        // 属性を付加する
        copy.attr('id', 'like_fruits_'+(creation_times+1));

        // 一番最後に格納
        copy.insertAfter('#like_fruits_'+creation_times);
    });

    // 削除ボタンをクリックしたときの処理
    $(document).on('click', '#delete_like_fruits_button', function() {
        // 今ある要素数を取得
        let creation_times = +$('#like_fruits_count').val();

        // 削除した後の個数を保存する
        $('#like_fruits_count').val(creation_times - 1);

        // 一番最後の行を削除する
        $('#like_fruits_'+creation_times).remove();

        // 一番最初は消せないように削除ボタンを無効化する
        if (creation_times <= 2) {
            $('#delete_like_fruits_button').prop('disabled', true);
        }
    });
</script>

みたいな感じに展開されるように作った。
jQueryは初心者でも結構あっさり実装できた。

jQuery Mobile編

コード例

<table>
    <tr id="like_fruits_1">
        <th>
            <label>好きなフルーツ</label>
            <input type="hidden" id="like_fruits_count" value="1">
        </th>
        <td>
            <select name="fruits[1]" class="select">
                <option value="">--</option>
                <option value="apple">りんご</option>
                <option value="orange">オレンジ</option>
                <option value="water_melon">スイカ</option>
                <option value="melon">メロン</option>
            </select>
            <button type="button" id="add_like_fruits_button" class="button button-pill button-primary" style="width: 100px;"><i class="fa fa-plus-square"></i> 追加</button>
            <button type="button" id="delete_like_fruits_button" class="button button-pill button-caution" style="width: 100px;"><i class="fa fa-trash"></i> 削除</button>
        </td>
    </tr>

    <tr id="clone_like_fruits_template" style="display: none">
        <th></th>
        <td>
            <my-select name="fruits[xxx]" class="select">
                <option value="">--</option>
                <option value="apple">りんご</option>
                <option value="orange">オレンジ</option>
                <option value="water_melon">スイカ</option>
                <option value="melon">メロン</option>
            </my-select>
        </td>
    </tr>
</table>

<script type=text/javascript>
    $(document).ready(function() {
        // 削除ボタンを無効化する
        $('#delete_like_fruits_button').attr('class', 'button button-pill button-caution button-large ui-btn-inline ui-shadow ui-link disabled');
    });

    // 追加ボタンをクリックしたときの処理
    $(document).on('click', '#add_like_fruits_button', function() {
        // 追加ボタンが押下されたら削除ボタンを有効化する
        $('#delete_like_fruits_button').attr('class', 'button button-pill button-caution button-large ui-btn-inline ui-shadow ui-link');

        // 今ある要素数を取得
        let creation_times = +$('#like_fruits_count').val();

        // 追加したあとの要素数を保存
        $('#like_fruits_count').val(creation_times + 1);

        // clone_like_fruits_templateのクローンを作成
        let copy = $('#clone_like_fruits_template').clone(true);

        // xxxを置換。my-selectを置換
        copy.html(function(i, oldHTML) {
            return oldHTML.replace(/xxx/g, creation_times+1).replace(/my-select/g, 'select')
        });

        // styleを外す。
        copy.prop('style', false);

        // 属性を付加する
        copy.attr('id', 'like_fruits_'+(creation_times+1));

        // 一番最後に格納
        copy.insertAfter('#like_fruits_'+creation_times).trigger('create');
    });

    // 削除ボタンをクリックしたときの処理
    $(document).on('click', '#delete_like_fruits_button', function() {
        // 今ある要素数を取得
        let creation_times = +$('#like_fruits_count').val();

        // 一番最初の要素しか無いときは何も処理をさせない
        if (creation_times === 1) {
            return;
        }

        // 削除した後の個数を保存する
        $('#like_fruits_count').val(creation_times - 1);

        // 一番最後の行を削除する
        $('#like_fruits_'+creation_times).remove();

        // 一番最初は消せないように削除ボタンを無効化する
        if (creation_times <= 2) {
            $('#delete_like_fruits_button').attr('class', 'button button-pill button-caution button-large ui-btn-inline ui-shadow ui-link disabled');
            return;
        }
    });
</script>

で定義して、「追加」を押すと、

<table>
    <tr id="like_fruits_1">
        <th>
            <label>好きなフルーツ</label>
            <input type="hidden" id="like_fruits_count" value="2">
        </th>
        <td>
            <select name="fruits[1]" class="select">
                <option value="">--</option>
                <option value="apple">りんご</option>
                <option value="orange">オレンジ</option>
                <option value="water_melon">スイカ</option>
                <option value="melon">メロン</option>
            </select>
            <button type="button" id="add_like_fruits_button" class="button button-pill button-primary" style="width: 100px;"><i class="fa fa-plus-square"></i> 追加</button>
            <button type="button" id="delete_like_fruits_button" class="button button-pill button-caution" style="width: 100px;"><i class="fa fa-trash"></i> 削除</button>
        </td>
    </tr>

    <tr id="like_fruits_2">
        <th></th>
        <td>
            <select name="fruits[2]" class="select">
                <option value="">--</option>
                <option value="apple">りんご</option>
                <option value="orange">オレンジ</option>
                <option value="water_melon">スイカ</option>
                <option value="melon">メロン</option>
            </select>
        </td>
    </tr>

    <tr id="clone_like_fruits_template" style="display: none">
        <th></th>
        <td>
            <my-select name="fruits[xxx]" class="select">
                <option value="">--</option>
                <option value="apple">りんご</option>
                <option value="orange">オレンジ</option>
                <option value="water_melon">スイカ</option>
                <option value="melon">メロン</option>
            </my-select>
        </td>
    </tr>
</table>

<script type=text/javascript>
    $(document).ready(function() {
        // 削除ボタンを無効化する
        $('#delete_like_fruits_button').attr('class', 'button button-pill button-caution button-large ui-btn-inline ui-shadow ui-link disabled');
    });

    // 追加ボタンをクリックしたときの処理
    $(document).on('click', '#add_like_fruits_button', function() {
        // 追加ボタンが押下されたら削除ボタンを有効化する
        $('#delete_like_fruits_button').attr('class', 'button button-pill button-caution button-large ui-btn-inline ui-shadow ui-link');

        // 今ある要素数を取得
        let creation_times = +$('#like_fruits_count').val();

        // 追加したあとの要素数を保存
        $('#like_fruits_count').val(creation_times + 1);

        // clone_like_fruits_templateのクローンを作成
        let copy = $('#clone_like_fruits_template').clone(true);

        // xxxを置換。my-selectを置換
        copy.html(function(i, oldHTML) {
            return oldHTML.replace(/xxx/g, creation_times+1).replace(/my-select/g, 'select')
        });

        // styleを外す。
        copy.prop('style', false);

        // 属性を付加する
        copy.attr('id', 'like_fruits_'+(creation_times+1));

        // 一番最後に格納
        copy.insertAfter('#like_fruits_'+creation_times).trigger('create');
    });

    // 削除ボタンをクリックしたときの処理
    $(document).on('click', '#delete_like_fruits_button', function() {
        // 今ある要素数を取得
        let creation_times = +$('#like_fruits_count').val();

        // 一番最初の要素しか無いときは何も処理をさせない
        if (creation_times === 1) {
            return;
        }

        // 削除した後の個数を保存する
        $('#like_fruits_count').val(creation_times - 1);

        // 一番最後の行を削除する
        $('#like_fruits_'+creation_times).remove();

        // 一番最初は消せないように削除ボタンを無効化する
        if (creation_times <= 2) {
            $('#delete_like_fruits_button').attr('class', 'button button-pill button-caution button-large ui-btn-inline ui-shadow ui-link disabled');
            return;
        }
    });
</script>

これでほぼjQueryと同じ感じに展開された。

名前は似ているが、実は結構違った「jQuery」と「jQuery Mobile」

「jQuery Mobile」は「Mobile」とつくだけだから、「jQuery」で書いたコードがそのまま動くでしょ。なんて軽く思っていたら違う部分が結構あった。
jQuery Mobileでは、cloneで追加されたセレクトボックスを選択しても、画面上に反映されなかった。
これの解消に2日くらい時間を要した。

理由は、DOMとしてレンダリングされたとき、すでに「jQuery Mobile」によってselectui-selectに変換されていたからだった。
今回は対処法としてDOMの段階ではmy-selectみたいな「jQuery Mobile」に勝手に変換されないようにして解決させた。

さすがに「Java」と「JavaScript」のように全く違う言語とまではいかないけど、それでも結構違った。

最後に、今回作成した成果物をご紹介

jQuery

追加ボタンを押す前
スクリーンショット 2020-12-12 20.38.32.png

追加ボタンを押した後
スクリーンショット 2020-12-12 20.38.49.png

jQuery Mobile

追加ボタンを押す前
スクリーンショット 2020-12-12 20.39.26.png

追加ボタンを押した後
スクリーンショット 2020-12-12 20.39.40.png

15
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
15
0