1

私はJenkins Builderを書いています。ビルド構成ページの構成用のゼリースクリプトには、フォームがロードされたときに実行したいJavascriptがいくつかあり、サーバールックアップを行い、ユーザーを支援するための情報を取得しますこれは、ユーザーがフォームの値を変更したときにも実行されます。

以前はthis、関数onchangeまたはonkeyup属性に渡すことで、フォーム要素への参照を取得していました。ただし、フォームが変更されていない場合でも、スクリプトを実行したいと考えています。

フォーム要素に ID 属性を設定できることはわかっていますが、ユーザーがこのビルダーを使用して 2 つのビルド ステップをビルドに追加すると、うまくいきません。

ビルダークラスでランダムIDを生成しようとしましたが、それを使用して要素のIDを作成し、それをゼリーファイルのJavascriptに書き込んで、それらの要素を見つけられるようにしましたが、ユーザーが保存するため、ユーザーがジョブを保存せずにこのビルダーの 2 つのインスタンスを追加すると機能しません。

<j:jelly xmlns:j="jelly:core" xmlns:st="jelly:stapler" xmlns:d="jelly:define" xmlns:l="/lib/layout" xmlns:t="/lib/hudson" xmlns:f="/lib/form">
  <f:entry title="Entry 1">
    <f:textbox field="field1" id="${instance.id}-field1" onchange="fieldChanged('${instance.id}-field1')"/>
  </f:entry>
  <script type="text/javascript">
    function fieldChanged(elementId) {
      ...
    }

    fieldChanged('${instance.id}-field1');
  </script>
</j:jelly>

この種のことを行う方法に関する規則はありますか? 独自の要素を参照できる同じゼリー ファイルの複数のインスタンスをサポートするために、Jenkins/jelly に組み込まれているものはありますか?

4

2 に答える 2

1

以下のこの解決策はうまくいくように見えますが、まだうまくいきません.

ビルダー クラスに、Editor という内部クラスを追加しました。

com.example.MyBuilder(.Editor):

...
public static class Editor {
    private final String id;

    public Editor(final String id) {
        this.id = id;
    }

    public String getId() {
        return id;
    }
}
...

次に、記述子 Java クラスで、一意の ID を持つこれらのいずれかを作成する JavaScript 関数を提供します。

com.example.MyBuilder.DescriptorImpl:

    private int lastEditorId = 0;

    @JavaScriptMethod
    public synchronized Editor createEditor() {
        return new Editor(String.valueOf(lastEditorId++));
    }

次に、ゼリー ファイルでそのメソッドを呼び出し、返されたオブジェクトを に渡し、st:include新しいゼリー ファイルをロードしてフィールドをレンダリングします。

com/example/MyBuilder/config.jelly:

<st:include page="editor.jelly" it="${descriptor.createEditor()}" />

(これは要素内にある必要があるように見えますが、f:entryまたはおそらく他の要素ですが、私は試していません。それ以外の場合、このビルダーの新しいビルドステップがジョブ構成に追加されたときに含まれないようです。)

最後に、フィールドをレンダリングする新しいeditor.jellyファイルを作成します (渡されるオブジェクトのタイプが であるため、Editorクラスを反映した名前のフォルダーにある必要があります)。itst:includeEditor

com/example/MyBuilder/Editor/editor.jelly:

<j:jelly xmlns:j="jelly:core" xmlns:st="jelly:stapler" xmlns:d="jelly:define" xmlns:l="/lib/layout" xmlns:t="/lib/hudson" xmlns:f="/lib/form">
<l:ajax>
    <f:entry title="Field">
        <f:textbox field="field" id="field-${it.id}"/>
        <p id="message-${it.id}"></p>
    </f:entry>
    <script>
        setTimeout(function(){
            var field = document.getElementById('field-${it.id}');
            var p = document.getElementById('message-${it.id}');
            p.textContent = "Initial value: "+field.value;
        }, 50);
    </script>
</l:ajax>
</j:jelly>

(への呼び出しsetTimeoutは、新しいビルド ステップを追加するときに、スクリプトが実行されるまでに要素が DOM に追加されていないため、スクリプトの実行を少し遅らせる必要があるためです)。

ただし、これにより、f:entry要素とビルダー クラスの同等のフィールドとの間のリンクが壊れてしまいます。これについてどうすればよいかわかりません。したがって、これは不完全な答えです。

編集:テスト中にフィールドをビルダークラスに追加するのを忘れていたため、要素が機能したかどうかf:entryはわかりません。これが (少なくとも 1 つの理由) データが保存されなかった理由です。これを試したときにこのフィールドから。ただし、現在、他の回答のソリューションを使用しているため、機能するかどうかをテストするために戻っていません。

于 2015-03-04T00:57:08.420 に答える
1

j:set私の他の答えよりも簡単な解決策があります。

com.example.MyBuilder.DescriptorImpl:

private int lastEditorId = 0;
...
@JavaScriptMethod
public synchronized String createEditorId() {
    return String.valueOf(lastEditorId++);
}

com/example/MyBuilder/config.jelly:

...
<j:set var="editorId" value="${descriptor.createEditorId()}" />
<f:entry title="Field">
    <f:textbox field="field" id="field-${editorId}"/>
    <p id="message-${editorId}"></p>
</f:entry>
<script>
    setTimeout(function(){
        var field = document.getElementById('field-${editorId}');
        var p = document.getElementById('message-${editorId}');
        p.textContent = "Initial value: "+field.value;
    }, 50);
</script>

(への呼び出しsetTimeoutは、新しいビルド ステップを追加するときに、スクリプトが実行されるまでに要素が DOM に追加されていないため、スクリプトの実行を少し遅らせる必要があるためです)。

于 2015-03-04T13:15:06.907 に答える