[Seasar-user:15950] [Teeda][提案]forEachにて生成されるidをかぶらないようにする

あきら [E-MAIL ADDRESS DELETED]
2008年 10月 8日 (水) 18:24:55 JST


こんにちはあきらです。

便利にTeedaを利用させてもらっていますが、idがかぶったxhtmlが
出力されるのがちょっと気になっていました

現状は
---------------------------------
<div id="testItems">
  <div id="title">title_str</div>
  <div id="note">note_str</div>
</div>
---------------------------------
上記のテンプレートの場合

---------------------------------
  <div id="title">item0_title</div>
  <div id="note">item0_note</div>

  <div id="title">item1_title</div>
  <div id="note">item1_note</div>
---------------------------------
このように出力されています。
id がかぶるので JavaScript などで処理ができなくなります。

---------------------------------
  <div id="title-0">item0_title</div>
  <div id="note-0">item0_note</div>

  <div id="title-1">item1_title</div>
  <div id="note-1">item1_note</div>
---------------------------------
そこで上記のように出力させるのはどうでしょうか?
-つきの番号であればinputなどでも大丈夫なはずです(未検証)

ネストしている場合には以下のような形になります。(改行を手で修正)
---------------------------------
<table>
  <tbody id="nameItemsItems">
    <tr id="nameItems-0">
      <td colspan="1" rowspan="1"><span id="name-0-0">String00</span></td>
      <td colspan="1" rowspan="1"><span id="name-0-1">String01</span></td>
      <td colspan="1" rowspan="1"><span id="name-0-2">String02</span></td>
    </tr>
    <tr id="nameItems-1">
      <td colspan="1" rowspan="1"><span id="name-1-0">String10</span></td>
      <td colspan="1" rowspan="1"><span id="name-1-1">String11</span></td>
      <td colspan="1" rowspan="1"><span id="name-1-2">String12</span></td>
    </tr>
  </tbody>
</table>
---------------------------------

テスト実装をしてみました
すみません、実装方法は力技なのでもう少し整理したほうがいいと思います
入力系などの影響範囲のテストもしていません、、、(testは5個エラー)

サンプル実装はとりあえず org.seasar.teeda.extension 以下への変更のみと
しています。本当はcore部分などに postId プロパティーなどを追加して設定
されていたらつけて描画の方がきれいだと思います。

後方互換性なども現在は考慮していません。
ただ id がかぶっているので、id での処理は通常していないはず。。。
omittag のような処理よりは設定ファイルで一括設定の方が後方互換性
対策はやりやすいかもしれません。

1、postId を追加
 org.seasar.teeda.extension.component.TForEach.java
 に public String postId = ""; を追加

2、描画直前に postId を付与、直後に削る
 org.seasar.teeda.extension.render.TForEachRenderer.java
 の encodeForEachChildren に手をいれます。

------------------------------------------------------------------
private void encodeForEachChildren(final FacesContext context,
    final TForEach forEach) throws IOException {
  final Object page = forEach.getPage(context);

  final BeanDesc pageBeanDesc = BeanDescFactory.getBeanDesc(page
      .getClass());
  final Object[] items = forEach.getItems(context);
  final int rowSize = items.length;

  for (int i = 0; i < rowSize; ++i) {
    final Object item = items[i];

    if (item == null) {
      continue;
    }
    final Integer savedIndex = forEach.bindRowIndex(context,
        new Integer(i));
    final Map savedValues = forEach
        .itemToPage(pageBeanDesc, page, item);
    forEach.enterRow(context, i, forEach);

    //=====================================================================
    // postIdを付与 以下追加
    for (Iterator itr = forEach.getChildren().iterator(); itr.hasNext();) {
      UIComponent child = (UIComponent) itr.next();

      // 描画物の場合IDを付与
      if( child instanceof HtmlOutputText ){
        HtmlOutputText text = (HtmlOutputText)child;
        String id = text.getId().split("-")[0];

        // 親のpostIdを取得
        String postId = "";
        Object parent = text.getParent();
        if( parent instanceof TForEach ){
            // 親がTForEachの場合のみ取得
            TForEach parent2 = (TForEach)parent;
            postId = parent2.postId;
        }

        // IDにpostIdを追加
        text.setId( id + postId + "-" + i );
      }

      // TForEachの場合IDを付与とpostIdを保存
      if( child instanceof TForEach ){
        TForEach data = (TForEach)child;
        String id = data.getId().split("-")[0];
        data.setId( id + "-" + i );
        data.postId = "-" + i;
      }
    }
    // postIdを付与 以上追加
    //=====================================================================

    super.encodeChildren(context, forEach);

    //=====================================================================
    // postIdを元に戻す 以下追加
    for (Iterator itr = forEach.getChildren().iterator(); itr.hasNext();) {
      UIComponent child = (UIComponent) itr.next();

      if( child instanceof HtmlOutputText ){
        HtmlOutputText text = (HtmlOutputText)child;
        String id = text.getId().split("-")[0];
        text.setId( id );
      }
      if( child instanceof TForEach ){
        TForEach data = (TForEach)child;
        String id = data.getId().split("-")[0];
        data.setId( id );
      }
    }
    // 元に戻す 以上追加
    //=====================================================================

    forEach.leaveRow(context, forEach);
    forEach.pageToItem(page, pageBeanDesc, item, BeanDescFactory
        .getBeanDesc(item.getClass()), savedValues);
    forEach.bindRowIndex(context, savedIndex);
  }
}
------------------------------------------------------------------

以上簡単ですが、ご検討いただければと思います。

あきら


Seasar-user メーリングリストの案内