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

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

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

Json例）##Issues_Ver: "3"

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

#実装例
##クライアントサイドの処理
```js: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で取得しています。

```csharp: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://qiita-image-store.s3.amazonaws.com/0/78230/1ce1ccc7-a8a2-772b-006a-9c40bc90407b.gif)

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