Dynamics CRM 2011 Xrm.Page サンプルライブラリ紹介 その 2

みなさん、こんにちは。

今回も引き続き、クライアントサイドスクリプトの紹介を行います。

サンプルを確認するにあたり準備があるため、こちらの記事
ご覧いただき、サンプルのインストールを行ってください。

サンプルの解説

前回はコントロール系のサンプルである addCustomView サンプル関数を
紹介しました。今回も引き続きコントロールのサンプルを紹介します。

サンプルは以下のフォルダにあります。
SDK\SampleCode\JS\FormScripts\SDK.ControlSamples.js

オプションセット操作サンプル

reverseOptions サンプル関数では、オプションセットの中身を逆にします。 また removeLastOption サンプル関数は、オプションセットの最後の アイテムのみを削除します。

サンプルコード解説

サンプルコードに直接コメントを入れて解説していきます。非常に
シンプルなサンプルです。

[reverseOptions 関数]

reverseOptions: function ()
{
        // IsOptionSet カスタム関数と Xrm.Page.ui.controls.get を利用して、
        // フォーム上の コントロールから 1つ 目のオプションセットコントロールを取得する。 
        var optionsetControl = Xrm.Page.ui.controls.get(SDK.ControlSamples.isOptionSet)[0];
        if (optionsetControl != null)
        {
            // getAttribute メソッドを利用して、コントロール内のアイテムを全て取得
            var options = optionsetControl.getAttribute().getOptions();

            // clearOptions メソッドで一旦オプションセット内のアイテムを削除
            optionsetControl.clearOptions();
            // 取得したアイテムを並び替える
            for (var i = 1; i <= options.length; i++)
            {
                if (options[options.length - i].value != "null")
                {
                    // addOption メソッドでオプションセットにアイテムを追加
                    optionsetControl.addOption(options[options.length - i], i - 1);
                }
            }
            // メッセージの表示
            alert("The options for the " + optionsetControl.getLabel() + " field have been reversed.");
        }
        else
        { alert("There are no Option set controls in this form."); }
},

[isOptionSet 関数]
オプションセットか判定するための関数です。

isOptionSet: function (control, index){
    // コントロールが OptionSet 型か確認する。 
    return control.getControlType() == "optionset";
},

[removeLastOption 関数]
オプションセットの最後の項目だけ削除します。

removeLastOption: function ()
{
    // IsOptionSet カスタム関数と Xrm.Page.ui.controls.get を利用して、
    // フォーム上の全てのオプションセットコントロールを取得する。 
    var controls = Xrm.Page.ui.controls.get(SDK.ControlSamples.isOptionSet);
    if (controls.length > 0)
    {
        // 初めのオプションセットを取得する。
        var firstOptionSet = controls[0];
        // getAttribute メソッドで、全てのオプションアイテムを取得する。
        var options = firstOptionSet.getAttribute().getOptions();
        // 最後のオプションセットアイテムの値と文字を取得する。
        var lastOptionText = options[options.length - 1].text;
        var lastOptionValue = options[options.length - 1].value;
        // removeOption メソッドでオプションセットから特定のアイテムを削除する。
        firstOptionSet.removeOption(lastOptionValue);
        // 削除したアイテムの情報を表示する。
        alert("The option '" + lastOptionText + "' has been removed from the '" + firstOptionSet.getName() + "' control.");
    }
    else
    {
        alert("There are no optionset controls on the current form.");
    }
},

※注意
実際にこのスクリプトは画面上では最後のオプションセットアイテムを
削除しません。理由はオプションセットがフォームに読み込まれた際に、
空白の項目を付け足すため、この空白が削除されるからです。

試す場合には、以下の箇所を変更してください。

修正前)
var lastOptionText = options[options.length - 1].text;
var lastOptionValue = options[options.length - 1].value;

修正後)
var lastOptionText = options[options.length - 2].text;
var lastOptionValue = options[options.length - 2].value;

コントロールの情報取得サンプル

showControlTypes、showControlParents および showIframeUrls
サンプル関数では、フォーム上のコントロールの各種値を取得して
表示します。それぞれ結果を別の画面に表示するための HTML を作成します。

また redirectAllIframes では、IFrame のソースを書き換えます。

[showControlTypes 関数]
表示する HTML 全体を作成

showControlTypes: function ()
{
    var html = "<html><head><title>Show Control Types</title>";
    html += "<style type=\"text/css\">body { font-family:Calibri;}";
    html += "table {border:1px solid gray; border-collapse:collapse;}";
    html += "th {text-align:left; border:1px solid gray;}";
    html += "td {border:1px solid gray;}</style>";
    html += "</head><body>";
    // 各種コントロールのタイプを取得
    html += SDK.ControlSamples.getControlTypes();
    html += "</body></html>";
    var theWindow = window.open("", "_blank");
    theWindow.document.open();
    theWindow.document.write(html);
    theWindow.document.close();
},

[getControlTypes 関数]

getControlTypes: function ()
{
    var html = "<table><thead><th>Control Label</th><th>Attribute Type</th>" +
       "<th>Attribute Format</th><th>Control Type</th></thead><tbody>";

    // Xrm.Page.ui.conrols.get メソッドで全てのコントロールを取得
    var controls = Xrm.Page.ui.controls.get();
    for (var i in controls)
    {
        // コントロールを 1 つ取得
        var control = controls[i];
        // コントロールのラベルを取得
        var label = control.getLabel();
        // ラベルが無い場合には、フィールド側の値を取得
        if (label == null)
        {
            var attributeName;
            try
            {
                // フィールド名を取得
                attributeName = control.getName();
                if (attributeName != "undefined")
                {
                    // フィールド名をラベルとして表示
                    label = "attribute: " + attributeName;
                }
            }
            catch (e)
            {
                label = "Control is not bound to an attribute and does not have a label.";
            }
        }

        var attributeType;
        try
        {
            // フィールドのタイプを取得
            attributeType = control.getAttribute().getAttributeType();
        }
        catch (e)
        {
            attributeType = "No Attribute";
        }
       
        var attributeFormat;        
        try
        {
            // フィールドのフォーマットを取得
            attributeFormat = control.getAttribute().getFormat();
        }
        catch (e)
        {
            attributeFormat = "No Attribute";
        }
       
        // コントロールのタイプを取得
        var controlType = control.getControlType();
        html += "<tr><td>" + label +
                "</td><td>" + attributeType +
                "</td><td>" + attributeFormat +
         "</td><td>" + controlType +
                 "</td></tr>";
    }
    html += "</tbody></table>";
    return html;
},

[showControlParents 関数]
コントロールの親コントロールを取得、表示します。

showControlParents: function ()
{
    var html = "<html><head><title>Show Control Parents</title>";
    html += "<style type=\"text/css\">body { font-family:Calibri;}";
    html += "table {border:1px solid gray; border-collapse:collapse;}";
    html += "th {text-align:left; border:1px solid gray;}";
    html += "td {border:1px solid gray;}</style>";
    html += "</head><body>";
    // コントロールの親コントロールを取得
    html += SDK.ControlSamples.getControlParents();
    html += "</body></html>";
    var theWindow = window.open("", "_blank");
    theWindow.document.open();
    theWindow.document.write(html);
    theWindow.document.close();
},

[getControlParents 関数]

getControlParents: function ()
{
    var html = "<table><thead><th>Control Label</th><th>Section Label</th>" +
       "</thead><tbody>";

    // フォーム上のすべてのコントロールを取得
    var controls = Xrm.Page.ui.controls.get();
    for (var i in controls)
    {
        // コントロールを 1 つ取得
        var control = controls[i];
        // コントロールのラベルを取得
        var controlLabel = control.getLabel();
        // getParent メソッドで親コントロールを取得し、ラベルを取得
        var sectionLabel = control.getParent().getLabel();
        if (sectionLabel == null)
        {
            sectionLabel = "No Label";
        }
        html += "<tr><td>" + controlLabel +
        "</td><td>" + sectionLabel +
                  "</td></tr>";
    }
    html += "</tbody></table>";
    return html;
},

[showIframeUrls 関数]
IFrame コントロールの情報を取得して表示します。

showIframeUrls: function ()
{
    // isIframe カスタム関数と Xrm.Page.ui.controls.get を利用して、
    // フォーム上の IFrame コントロールを全て取得
    var controls = Xrm.Page.ui.controls.get(SDK.ControlSamples.isIframe);
    if (controls.length > 0)
    {
        // URL を保持する配列を準備
        var iframeUrls = [];
        for (var i in controls)
        {
            // getSrc メソッドでソースの URL を取得
            iframeUrls.push(controls[i].getSrc());
        }
        // URL 情報を保存
        var message = "The iframes on the current form have the following urls:\n\n- " + iframeUrls.join("\n- ");
    }
    else
    {
        var message = "There are no iframe controls on the current form.";
    }

    // 保存した URL 情報を表示
    alert(message);
},

[isIframe 関数]
コントロールが iframe か確認

isIframe: function (control, index)
{
    // getControlType を利用して iframe か確認
    return control.getControlType() == "iframe";
},

[redirectAllIframes 関数]

redirectAllIframes: function ()
{
    // isIframe カスタム関数と Xrm.Page.ui.controls.get を利用して、
    // フォーム上の IFrame コントロールを全て取得
    var controls = Xrm.Page.ui.controls.get(SDK.ControlSamples.isIframe);
    if (controls.length > 0)
    {
        for (var i in controls)
        {
            var control = controls[i];
            // コントロールの名前を表示
            var controlName = control.getName();
            var newUrl = "https://www.microsoft.com";
            // setSrc メソッドで、新しい URL に変更
            control.setSrc(newUrl);
            // 元の URL を取得
            var oldUrl = control.getInitialUrl();
            alert("The source of the iframe '" + controlName + "' has been changed from '" + oldUrl + "' to '" + newUrl + "'.");
        }
    }
    else
    {
        alert("There are no iframe controls on the current form.");
    }
},

コントロールの表示関連サンプル

以下の 3 つのサンプルでは、コントロールの表示を操作しています。

toggleEnableControls サンプル関数
toggleVisibleControls サンプル関数
toggleControlLabels サンプル関数

また setFocusDemo サンプル関数では、コントロールにフォーカスを
当てるサンプルを提供します。

[toggleEnableControls 関数]
フォーム上のコントロールの有効化/無効化を切り替えます。

toggleEnableControls: function ()
{
    // フォーム上の全てのコントロールを取得します。
    var controls = Xrm.Page.ui.controls.get();
    for (var i in controls)
    {
        // コントロールを 1 件取得します。
        var control = controls[i];
        // getDiabled メソッドでコントロールが無効か確認します。
        if (control.getDisabled())
        {
            // 無効な場合は setDisabled メソッドに false を渡して有効にします。
            control.setDisabled(false);
        }
        else
        {
            // 有効な場合は setDisabled メソッドに true を渡して無効にします。
            control.setDisabled(true);
        }
    }
},

[toggleVisibleControls 関数]
上記サンプルとほぼ同じです。

toggleVisibleControls: function ()
{
    // フォーム上の全てのコントロールを取得します。
    var controls = Xrm.Page.ui.controls.get();
    for (var i in controls)
    {
        // コントロールを 1 件取得します。
        var control = controls[i];
        // getVisible メソッドでコントロールが表示されているか確認します。
        if (control.getVisible())
        {
            // 表示されている場合は非表示にします。
            control.setVisible(false);
        }
        else
        {
            // 表示されていない場合は表示します。
            control.setVisible(true);
        }
    }
},

[toggleControlLabels 関数]
コントロールで利用しているラベルに Prefix の文字列を付加する
サンプルです。関数が引数を受け取れるようになっています。

toggleControlLabels: function (prefix)
{
    // フォーム上の全てのコントロールを取得します。
    var controls = Xrm.Page.ui.controls.get();
    for (var i in controls)
    {
        // コントロールを 1 件取得します。
        var control = controls[i];
        // 現在のラベルを取得します。
        var currentLabel = control.getLabel();
        // ラベルの値に引数の Prefix の値が含まれているか確認します。
        if (currentLabel.substring(0, prefix.length) == prefix)
        {
            // 含まれているばあい、削除します。
            var newLabel = currentLabel.substring(prefix.length);
            control.setLabel(newLabel);
        }
        else
        {
            // 含まれていない場合は付与します。
            control.setLabel(prefix + currentLabel);
        }
    }
},

[setFocusDemo 関数]
コントロールの一覧を新しいウィンドウに表示して、そこに作成した
ボタンをクリックすることで、元のフォームのコントロールにフォーカスを
当てるサンプルです。

setFocusDemo: function ()
{
    var html = "<html><head><title>Set focus demo</title>";
    html += "<style type=\"text/css\">body { font-family:Calibri;}";
    html += "table {border:1px solid gray; border-collapse:collapse;}";
    html += "th {text-align:left; border:1px solid gray;}";
    html += "td {border:1px solid gray;}</style>";
    // setFocus メソッド用のスクリプトを記述
    // フィールドに複数のコントロールが紐付いている場合には
    // 初めのコントロールにフォーカスを当てる
    html += "<script type=\"text/jscript\" >";
    html += "function setFocus(name) { ";
    // controls.get メソッドでフィールドに紐付くコントロールを取得
    html += "window.opener.Xrm.Page.data.entity.attributes.get(name).controls.get(0).setFocus();";
    html += "}";
    html += "</script>";
    html += "</head><body>";
    // フォーム上のフィールドをテーブルとして記述する関数を実行
    html += SDK.ControlSamples.buildFocusDemoTable();
    html += "</body></html>";
    var theWindow = window.open("", "_blank");
    theWindow.document.open();
    theWindow.document.write(html);
    theWindow.document.close();
},

[buildFocusDemoTable 関数]
フォーム上のコントロールをテーブルとして表現します。

buildFocusDemoTable: function ()
{
    var html = "<table><thead><th>Control Label</th><th></th>" +
       "</thead><tbody>";

    // 全てのフィールドを取得
    var attributes = Xrm.Page.data.entity.attributes.get();
    for (var i in attributes)
    {
        // フィールドオブジェクトより、controls.get でコントロールを取得
        var control = attributes[i].controls.get(0);
        // コントロールが無効、非表示またはフォーカスを受け取らない場合
        // エラーになるため、コントロールの状態を確認
        if (control != null && !control.getDisabled() && control.getVisible())
        {
            var controlLabel = attributes[i].controls.get(0).getLabel();
            var attributeName = attributes[i].getName();
            html += "<tr><td>" + controlLabel +
                   "</td><td><input type=\"button\" onclick=\"setFocus('" + attributeName +
               "');\" value='Set Focus on " + controlLabel + "' /></td></tr>";
        }
    }
    html += "</tbody></table>";
    return html;
}

動作確認

1. 取引先企業のフォームを開き、カスタマイズタブをクリックします。

2. フォーム上の一番初めのオプションセットを確認します。こちらの環境では
関係内容フィールドでした。

image

3. SDK.ControlSamples.js より reverseOptions をクリック。しばらく待ちます。

image

4. 完了のメッセージが出た後、再度オプションセットを確認します。
順番が入れ替わっていることが確認できます。

image

同様のほかのサンプルも動作を確認してください。

まとめ

前回に引き続きコントロールに関連するサンプルを紹介しました。コントロールの
表示/非表示、有効/無効や iframe のソースを動的に変更できることは、フォームを
ユーザーや状況によって制御する場合にとても有用です。

ただし、コントロールの表示/非表示を操作する場合には、既定でコントロールを
非表示にしておき、OnLoad 等で表示するように検討してください。既定で表示にして
あとで非表示にする場合、スクリプトのラグで一瞬コントロールが表示される可能性が
あります。

次回もスクリプトのサンプルを紹介します。

‐ Dynamics CRM サポート 中村 憲一郎