3
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

プリザンターのサーバスクリプト「context.AddResponse」のMethodを詳しくみてみる

Last updated at Posted at 2025-03-13

はじめに

プリザンターのサーバスクリプトの関数の1つである「context.AddResponse」、マニュアルページはあるものの記載されている内容はかなりシンプルで、何がどこまで出来るの?というところまでは記載がありません。今回は実装から中身を読み解いていきます。

実装を見てみる

早速実装をみてみましょう。サーバスクリプト(ClearScript)で呼び出される部分は下記になります。

Implem.Pleasanter/Libraries/ServerScripts/ServerScriptModelContext.cs
        public void AddResponse(
            string method,
            string target = null,
            object value = null,
            string options = null)
        {
            ResponseCollection.Add(
                method: method,
                target: target,
                value: value,
                options: options);
        }

ここでは受け取った値をResponseCollection.Addに渡しているだけなので、ResponseCollection.Addを見てみます。

Implem.Pleasanter/Libraries/Responses/ResponseCollection.cs
        public ResponseCollection Add(
            string method,
            string target = null,
            object value = null,
            string options = null)
        {
            Add(new Response(
                method: method,
                target: target,
                value: value != null
                    ? value
                    : string.Empty,
                options: options));
            return this;
        }

ざっくりと説明してしまうと、ResponseCollectioncontext.AddResponseでセットされた値を追加していっています。最終的にResponseCollectionにセットされた値はJSONにシリアライズされブラウザに送られます。
ブラウザ側で送られたResponseCollectionを受け取っているのはJavaScriptで書かれたライブラリです。その実装部を見てみましょう。

Implem.Pleasanter/wwwroot/scripts/_dispatch.js
$p.setByJsonElement = function (jsonElement, data, $control) {
    var method = jsonElement.Method;
    var target = jsonElement.Target;
    var value = jsonElement.Value;
    var options = jsonElement.Options !== undefined
        ? JSON.parse(jsonElement.Options)
        : {};
    switch (method) {
        case 'Html':
            $(target).html(value);
            break;
        case 'ReplaceAll':
            $(value).replaceAll(target);
            break;
        case 'Message':
            $p.setMessage(target, value);
            break;
        case 'Href':
            $control.addClass('no-send');
            $p.transition(value);
            break;
        case 'PushState':
            history.pushState(target, '', value);
            break;
        case 'Set':
            var $target = $p.getControl(target);
            if (!$target) {
                $target = $(target);
            }
            $p.set($target, value);
            break;
        case 'SetData':
            $p.setData($(target));
            break;
        case 'SetFormData':
            data[target] = value;
            break;
        case 'SetMemory':
            $p[target] = value;
            break;
        case 'Append':
            $(target).append(value);
            break;
        case 'Prepend':
            $(target).prepend(value);
            break;
        case 'After':
            if ($(target).length !== 0) {
                $(target).after(value);
            } else {
                $control.after(value);
            }
            break;
        case 'Before':
            if ($(target).length !== 0) {
                $(target).before(value);
            } else {
                $control.before(value);
            }
            break;
        case 'InsertText':
            $p.insertText($(target), value);
            break;
        case 'Remove':
            $(target).remove();
            break;
        case 'Attr':
            var json = JSON.parse(value);
            $(target).attr(json.Name, json.Value);
            break;
        case 'RemoveAttr':
            $(target).removeAttr(value);
            break;
        case 'Css':
            var json = JSON.parse(value);
            $(target).css(json.Name, json.Value);
            break;
        case 'Focus':
            if (target === '') {
                $('#' + data.ControlId).focus();
            } else {
                $(target).focus();
            }
            break;
        case 'SetValue':
            $p.setValue($(target), value);
            $p.hideField(target, options);
            break;
        case 'ClearFormData':
            $p.clearData(target, data, value);
            break;
        case 'CloseDialog':
            $p.clearMessage();
            if (target !== undefined) { 
                if ($(target).hasClass('ui-dialog-content')) {
                    $(target).dialog('close');
                }
            } else {
                $('.ui-dialog-content').dialog('close');
            }
            break;
        case 'Paging':
            $p.paging(target);
            break;
        case 'Toggle':
            $(target).toggle(value === '1');
            break;
        case 'Trigger':
            $(target).trigger(value);
            break;
        case 'Invoke':
            $p[target](value);
            break;
        case 'Events':
            $p.execEvents(target, '');
            break;
        case 'WindowScrollTop':
            $(window).scrollTop(value);
            break;
        case 'ScrollTop':
            $(target).scrollTop(value);
            break;
        case 'LoadScroll':
            $p.loadScroll();
            break;
        case 'FocusMainForm':
            $p.focusMainForm();
            break;
        case 'Disabled':
            $(target).prop('disabled', value);
        case 'Log':
            if (value) {
                console.log(value);
            }
            break;
    }
}

ここまで来ると何か見たことがあるものがありませんか?そうですswitch文で処理されているmethodです。
このmethodがマニュアルに記載されている引数methodそのものになります。

methodを細かく見ていく

では実際にそれぞれのmethodでどのような処理が行われているか見てみましょう。

Html

$(target).html(value);とある通り、jQueryのhtmlメソッドそのままです。targetで指定された要素の中身をvalueで書き換えます。

ReplaceAll ※マニュアルに記載あり

$(target).replaceAll(value);とある通り、jQueryのreplaceAllメソッドそのままです。targetで指定された要素ごとvalueで書き換えます。

Message

$p.setMessage(target, value);なので、スクリプトの$p.setMessageになります。

Href

$control.addClass('no-send');で現在の画面内容をサーバに対して送信しない様にしたあとに、$p.transitionを呼んでいます。$p.transitionの実装は下記のようになっています。

Implem.Pleasanter/wwwroot/scripts/navigation.js
$p.transition = function (url) {
    try {
        location.href = url;
    } catch (e) {
        if (e.number !== -2147467259) {
            throw e;
        }
    }
};

location.hrefvalueを渡しています。location.hrefはJavaScriptの標準プロパティなので、mdn web docsを参照してください。location: href プロパティ

PushState

history.pushStateを呼び出しています。JavaScriptの標準メソッドなので、mdn web docsを参照してください。History: pushState() メソッド

Set ※マニュアルに記載あり

指定された要素に$p.setで値をセットしています。ポイントとなるのは詳しくは$p.getControlで標準項目の取得を行い、取得出来なければそのままで要素が使用されるという部分です。$p.setについてはマニュアルを参照してください。

SetData

指定された要素に$p.setDataで値をセットしています。$p.setDataはマニュアルに記載がないので簡単に紹介します。実装を見てみましょう。

Implem.Pleasanter/wwwroot/scripts/_data.js
$p.setData = function ($control, data) {
    var controlId = $control.attr('id');
    if (!$control.hasClass('not-send')) {
        if (data === undefined) {
            data = $p.getData($control);
        }
        $p.setGridTimestamp($control, data);
        switch ($control.prop('type')) {
            case 'checkbox':
                data[controlId] = $control.prop('checked');
                break;
            case 'radio':
                if ($control.prop('checked')) {
                    var name = $control.attr('name');
                    data[name] = $control.val();
                    $('[id="' + name + '"]').val($control.val());
                    $('[id="' + name + '-error"]').remove();
                }
                break;
            default:
                switch ($control.prop('tagName')) {
                    case 'SPAN':
                        data[controlId] = $control.attr('data-value') !== undefined
                            ? $control.attr('data-value')
                            : $control.text();
                        break;
                    case 'SELECT':
                        if ($control.attr('multiple')) {
                            $p.setMultiSelectData($control);
                        } else {
                            data[controlId] = $control.val();
                        }
                        break;
                    case 'OL':
                        if ($control.hasClass('control-selectable')) {
                            data[controlId] = $p.toJson($control.find('li.ui-selected'));
                            if ($control.hasClass('send-all')) {
                                data[controlId + 'All'] = $p.toJson($control.find('li'));
                            }
                        } else {
                            data[controlId] = $p.toJson($control.find('li'));
                        }
                        break;
                    case 'TABLE':
                        data[controlId] = JSON.stringify($control
                            .find('.select')
                            .filter(':checked')
                            .map(function () {
                                return $(this).closest('.grid-row').attr('data-id');
                            })
                            .toArray());
                        break;
                    case 'P':
                        if ($control.hasClass('control-slider')) {
                            data[controlId] = $control.attr('data-value');
                        } else {
                            data[controlId] = $control.val();
                        }
                        break;
                    default:
                        data[controlId] = $control.val();
                        break;
                }
                break;
        }
    }
}

指定された要素がnot-sendという属性を持つときのみdataという連想配列にセットされているデータを詰め替えています。このdataというのはプリザンターのブラウザからサーバに対して送るデータを保持しているものになります。UIや$p.setなどでデータの変更を行うときに裏で動いている関数となります。通常は使うことがないので詳細は割愛します。

SetFormData

前項のSetDataと類似ではあるのですが、コントロールを直接指定しているという部分が異なります。通常は使うことがないので詳細は割愛します。

SetMemory

$pという連想配列にデータをセットします。メソッド名の示すとおり一時的にデータを保管する用途で使用されます。任意の関数を作成して一時的に格納するということにも使用可能で、その場合はInvokeで発火させます。

Append

$(target).append(value);とある通り、jQueryのappendメソッドそのままです。valuetargetの末尾に追加します。

Prepend

$(target).prepend(value);とある通り、jQueryのprependメソッドそのままです。valuetargetの先頭に追加します。

After

$(target).after(value);とある通り、jQueryのafterメソッドそのままです。targetの直後に要素を追加します。

Before

$(target).before(value);とある通り、jQueryのbeforeメソッドそのままです。targetの直前に要素を追加します。

InsertText

$p.insertTextを呼び出しています。$p.insertTextの実装を見てみましょう。

$p.insertText = function ($control, value) {
    var body = $control.get(0);
    body.focus();
    var start = body.value;
    var caret = body.selectionStart;
    var next = caret + value.length;
    body.value = start.substr(0, caret) + value + start.substr(caret);
    body.setSelectionRange(next, next);
    $p.setData($control);
    if (!$control.is(':visible')) {
        $p.showMarkDownViewer($control);
    }
}

指定された要素の末尾で文字列を追記して、送信データに組み入れる処理を行っています。説明項目などに文字列を追記する時に使用します。

Remove

$(target).remove();とある通り、jQueryのremoveメソッドそのままです。targetをまるごと削除します。

Attr

$(target).attr(json.Name, json.Value);とある通り、jQueryのattrメソッドそのままです。targetに属性を追加します。使い方に若干癖があり、valueに対して{Name:'',Value:''}というJSONをシリアライズしたものを格納する必要があります。

RemoveAttr

$(target).attr(json.Name, json.Value);とある通り、jQueryのattrメソッドそのままです。targetから指定属性を削除します。

Css

$(target).css(value);とある通り、jQueryのcssメソッドそのままです。targetに対してCSSを適用します。使い方に若干癖があり、valueに対して{Name:'',Value:''}というJSONをシリアライズしたものを格納する必要があります。

Focus

$(target).focus();とある通り、jQueryのfocusメソッドそのままです。targetに対してファーカスを当てる操作を行います。

SetValue

$p.setValue($(target), value);$p.hideField(target, options);が連続実行されています。まずは$p.setValueの実装を見てみましょう。

Implem.Pleasanter/wwwroot/scripts/_view.js
$p.setValue = function ($control, value) {
    switch ($control.prop('type')) {
        case 'checkbox':
            $control.prop('checked', value);
            break;
        case 'radio':
            $control.val([value]);
            break;
        case 'textarea':
            $control.val(value);
            $p.showMarkDownViewer($control);
            break;
        default:
            switch ($control.prop('tagName')) {
                case 'SELECT':
                    if ($control.attr('multiple')) {
                        $p.selectMultiSelect($control, value);
                    } else {
                        $control.val(value);
                    }
                    break;
                case 'SPAN':
                    $control.html(value);
                case 'TIME':
                    $control.html(value);
                    $control.attr('datetime', value);
                    break;
                default:
                    if ($control.hasClass('radio-value')) {
                        // type="radio"のチェック変更
                        $('input[name="' + $control.attr('id') + '"]').val([value]);
                    }
                    $control.val(value);
                    break;
            }
    }
}

やっていることはとても簡単で指定要素をvalueで書き換えています。$p.setと似たような処理ではあるのですが、差違としては$p.setDataを叩いていない(=サーバに送るデータとして処理しない)部分になります。

次は$p.hideFieldを見てみましょう。

Implem.Pleasanter/wwwroot/scripts/visibility.js
$p.hideField = function (target, options) {
    $field = $(target + 'Field');
    if (options.Hide && !$field.hasClass('hidden')) {
        $field.addClass('hidden');
    } else if (options.Hide !== true && $field.hasClass('hidden')) {
        $field.removeClass('hidden');
    }
}

項目の表示・非表示を判断して、表示・非表示を再設定しています。$p.setValueで表示・非表示が外れることがあるので、この関数で復旧させています。

画面上の要素で表示名などのデータ以外の項目を書き換えたいときに使用します。

ClearFormData

$p.clearDataを呼び出しています。実装を見てみましょう。

Implem.Pleasanter/wwwroot/scripts/_data.js
$p.clearData = function (target, data, type) {
    if (!data) {
        data = $p.getData($('.main-form'));
    }
    if (target === undefined) {
        for (controlId in data) {
            if (!$('#' + controlId).hasClass('control-selectable')) {
                Delete(controlId);
            }
        }
    } else if (type === 'startsWith') {
        for (controlId in data) {
            if (controlId.indexOf(target) === 0) {
                Delete(controlId);
            }
        }
    } else {
        if (target in data) {
            Delete(target);
        } else if ($(target).length !== 0) {
            Delete($(target).attr('id'));
        }
    }
    function Delete(key) {
        if (type === 'ignoreView') {
            if (key.indexOf('View') === 0) {
                return;
            }
        }
        delete data[key];
    }
};

$p.setDataとは反対にdataにセットされたデータを削除(=サーバに送信しないデータにする)を行っています。通常は使用することはないため割愛します。

CloseDialog

開かれているダイアログを閉じるために使用します。通常は使用することはないため割愛します。

Paging

$p.pagingを呼び出しています。実装を見てみましょう。

$p.paging = function (selector) {
    if ($('.ui-dialog:visible').length > 0) {
        return;
    }
    var $control = $(selector);
    var $offset = $(selector + 'Offset');
    if ($control.length) {
        if ($(window).scrollTop() + $(window).height() >= $control.offset().top + $control.height()) {
            if ($offset.val() !== '-1') {
                $p.setData($offset);
                $offset.val('-1');
                $p.send($control);
            }
        }
    }
}

一覧項目などでサイトの下部までスクロールした際に次の項目を読み出してくるときに使用します。通常は使用することはないため割愛します。

Toggle

$(target).toggle(value === '1');とある通り、jQueryのtoggleメソッドそのままです。指定された要素の表示・非表示を切替ます。value1かそうでないかでtrue/falseを指定しているので、true/falseを直接指定出来ないことに注意が必要です。

Trigger

$(target).trigger(value);とある通り、jQueryのtriggerメソッドそのままです。指定された要素に対してトリガーを発火させることができます。サーバスクリプト側から選択肢一覧のモーダルを表示させたり、一覧メニューを表示させたりとUI操作でかなり強力な操作が可能です。

Invoke

$p[target](value);と書いてある通り、$pにセットされている任意の関数を実行出来ます。SetMemoryでセットしてInvokeで発火させるという使い方になります。

Events

$p.execEventsを呼び出しています。実装を見てみましょう。

$p.execEvents = function (event, args) {
    var result = exec(event);
    var $control = args.$control;
    if ($control) {
        result = exec(event + '_' + $control.attr('id')) && result;
        if ($control.attr('id') !== $control.attr('data-action')) {
            result = exec(event + '_' + $control.attr('data-action')) && result;
        }
    }
    return result;
    function exec(name) {
        if ($p.events[name] !== undefined) {
            return ($p.events[name](args) === false) ? false : true;
        }
        return true;
    }
}

かなり強力な機能で、任意の関数を実行することが可能ですが、実行対象は$p.eventsに格納されている関数になるので、使いどころがむずかいしいところがあります。

WindowScrollTop

$(window).scrollTop(value);とある通り、jQueryのscrollTopメソッドそのままです。valueに指定された数値の位置までスクロールします。

ScrollTop

$(target).scrollTop(value);とある通り、jQueryのscrollTopメソッドそのままです。valueに指定された数値の位置までスクロールします。WindowScrollTopとの違いは、ウインドウではなく要素が指定されているところになります。

LoadScroll

$p.loadScrollを呼んでいるので、$p.loadScrollの実装を見てみましょう。

Implem.Pleasanter/wwwroot/scripts/scroll.js
$p.loadScroll = function () {
    window.scroll($p.scrollX, $p.scrollY);
}

さらに別の$p.scrollX$p.scrollYも出てきたので、こちらの実装も見てみます。

Implem.Pleasanter/wwwroot/scripts/scroll.js
$p.saveScroll = function () {
    $p.scrollX = document.documentElement.scrollLeft || document.body.scrollLeft;
    $p.scrollY = document.documentElement.scrollTop || document.body.scrollTop;
}

$p.clearScroll = function () {
    $p.scrollX = 0;
    $p.scrollY = 0;
}

これは現在のスクロール位置を取得しています。
画面の再ロードがおこなわれた際に元々の表示位置に画面をスクロールするのに使用します。通常は使用することはない思います。

FocusMainForm

$p.focusMainFormが呼び出されています。実装を見てみましょう。

Implem.Pleasanter/wwwroot/scripts/focus.js
$p.focusMainForm = function () {
    $('#FieldSetGeneral').find('[class^="control-"]').each(function () {
        if (!$(this).is(':hidden') &&
            !$(this).hasClass('control-text') &&
            !$(this).hasClass('control-markup')) {
            $(this).focus();
            return false;
        }
    });
}

編集画面中の先頭のアイテムにフォーカスを当てる動作をしています。通常は使用することはないとおもいm

Disabled

$(target).prop('disabled', value);とある通り、jQueryのpropメソッドそのままです。指定要素にdisabledを付与したり外したりといった操作が可能です。

Log

valueに値が格納されていればconsole.logで値が出力されます。context.Logと同じ働きをします。

まとめ

今回はcontext.AddResponseの中身を見てみました。マニュアルには記載がないけどかなり使えるmethodが複数あります。HrefWindowScrollTopなどかなり使いどころがある機能なので、是非使ってみてください。

3
1
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
3
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?