LoginSignup
22
27

More than 5 years have passed since last update.

jQuery: ajaxの戻り値Jsonでブラウザに色々なことをさせる共通ロジック

Posted at

目的

サーバーサイドから返却するJsonでクライアントにアレ・コレさせたいけれど、その都度値の受け渡し方法を考えたり、JavaScriptをゴリゴリ書くのは骨が折れるので共通化してみました。クライアントにさせたい仕事をサーバーサイドで簡単に記述できるのがメリットです。最新のJavaScriptフレームワークとか使えばこういうのいらないのかもしれません。

概要

サーバーサイドから返却するJsonを以下の形式で出力し、命令記号によるswitchでクライアントが行う処理を切り替えます。
・key 1文字目: 命令記号(クライアント側の処理の分岐に使用)
・key 2文字目以降: セレクタ(処理対象の選択)
・value: 処理対象に設定する値

Json例)##Issues_Ver: "3"

上記は、「#」が命令記号、「#Issues_Ver」がセレクタ、「3」が値です。
id="Issues_Ver"のvalueに3をセットせよという命令です。

実装例

クライアントサイドの処理

Transport.js
function request(requestUrl, methodType, data) {
    return $.ajax({
        url: requestUrl,
        type: methodType,
        cache: false,
        data: data,
        dataType: 'json'
    })
    .done(function (json, textStatus, jqXHR) {
        if (json) {
            // サーバーサイドから返却されたJsonを列挙
            $.each(json, function (key) {
                apply(key, this, data);
            });
        }
        return true;
    });

    function apply(key, value, data) {

        // keyの1文字目に含まれる命令記号を取得
        var selector = key.substring(1, key.length);

        // 処理対象のセレクタを選択
        var $control = $(selector);

        // Jsonに含まれる命令記号に基づき処理を分岐
        switch (key.substring(0, 1)) {
            case ' ': // htmlの書き換え命令
                $control.html(value);
                break;
            case '>': // メッセージ領域への出力命令
                setMessage(value);
                break;
            case '@': // 他のUrlへの遷移命令
                location.href = value;
                break;
            case '_': // クライアントのデータ書き換え命令
                data[$control.attr('id')] = value;
                break;
            case '+': // 要素の末尾に要素を追加する命令
                $control.append(value);
                break;
            case '^': // 先頭に要素を追加する命令
                $control.prepend(value);
                break;
            case '-': // 要素を削除する命令
                $control.remove();
                break;
            case '.': // フォーカスをセットする命令
                $control.focus();
                break;
            case '#': // 要素の値をセットする命令
                setValue($control, value);
                break;
            case '$': // クライアント上のデータを書き換える命令
                data[$control.attr('id')] = value;
                setValue($control, value);
                break;
            case '%': // クライアント上のデータを消去する命令
                clearFormData(selector, data);
                break;
            case ')': // clickなどイベントをキックする命令
                $control.trigger(value);
                break;
            case '!': // 要素の内容を消去する命令
                $control.empty();
                break;
        }

        // メッセージ領域への出力
        function setMessage(value) {
            var $control = $('.message-dialog:visible');
            if ($control.length == 0) {
                $('#Message').html(value);
            } else {
                $control.html(value);
            }
        }

        // 要素の値をセットする
        function setValue($control, value) {
            switch ($control.prop('type')) {
                case 'checkbox':
                    $control.prop('checked', value);
                    break;
                case 'radio':
                    $control.val([value]);
                    break;
                default:
                    switch ($control.prop('tagName')) {
                        case 'SPAN':
                            $control.html(value);
                        default:
                            $control.val('' + value + '');
                            break;
                    }
            }
        }
    }
}

サーバーサイドの処理(c# ASP.NET MVCの例)

命令記号の部分は定数などを割り当てておくと分かりやすいコードになります。
Newtonsoft.JsonはNuGetで取得しています。

response.cs
using Newtonsoft.Json;
using System.Collections.Generic;
namespace Implem.Pleasanter.Libraries.Responses
{
    public class IssueModel
    {
        // 更新処理を行った後にクライアントのバージョンテキストボックスの内容更新と
        // メッセージ領域へのメッセージ出力を命令します。
        public string Update()
        {
            // 更新処理を記述。

            // レスポンス処理。
            return JsonConvert.SerializeObject(new Dictionary<string, string>
            {
                { "#" + "#Issues_Ver", "3" },
                { ">", Title + "の更新が完了しました。" }
            });
        }
    }
}

動作イメージ

更新ボタン押下後にバージョンの数字が変更され、更新メッセージが表示されます。
demo.gif

ご参考

下記プロジェクトで使用しています。ほかにも実装例などがありましたら情報交換お願いします。
https://github.com/Implem/Implem.CodeDefiner

22
27
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
22
27