CSSを使ってのデザイン指定 その2

CSSを使ってデザイン要素の指定にトライしてみよう、の第2弾。

やりたいこと

データソースを貼り付けると、簡単に見出しと入力項目の表ができるけど、このデザインを以下のようにしてみたい。 TABLEのデザイン指定

基本的には、以下の3ステップ。

TABLEにスタイルを設定

TABELにスタイルを設定する。名前は後でCSSにつける名前にあわせる。 本来は、その表の用途を示すような名前にすべき(用途別にデザインを設定するので)。

TABLEのスタイル設定

ソースコード上は、<xp:table styleClass="myTable">のように設定される。

さらに、1列目だけセルの背景色を変えたいので、1列目と2列目を区別できるように、<col>もつけておく。<col>は<xp:table>の後ろに入れる。

  <xp:table styleClass="myTable">
      <col class="odd" />
      <col class="even" />
      <xp:tr>
  

CSSを作成

CSSをそのアプリのリソースの中に作成する。 CSSは以下のように記述する。

  table.myTable {
    border-collapse: collapse;
    border: 2px #000000 solid;
    margin: 20px;
  }
  table.myTable td {
    border-collapse: collapse;
    border: 1px #000000 solid;
    border-style:inset;
    padding: 2px;
  }
  table.myTable col.odd{
    background-color: #FFF8D0;
  }
  table.myTable input {
    width: 80%;
  }
  

最後に、CSSをリソースとしてXPageに組み込めばいい。 これで目的のデザイン変更ができる。

でも結局

背景色が設定できたので、見出し部の文字を右寄せにしたい。 それなら、CSSのcol.oddに"text-align: right;"を追加すればよさそう。

  table.myTable col.odd{
    background-color: #FFF8D0;
    text-align: right;
  }
  

だが、残念ながら、<col>で設定できる属性には限りがあるので、右寄せはできない(ブラウザで挙動が違うらしい)。 結局、見出しは<xp:td> → <th> に変えないとだめっぽい。ちょっとつらい作業を行って、見出し部を<th>に変えた後、CSSに以下の設定を追加する。

  table.myTable th {
    border-collapse: collapse;
    border: 1px #000000 solid;
    border-style:inset;
    padding: 2px;
    background-color: #FFF8D0;
    text-align: right;
  }
  

このつらい変更作業をサポートするスクリプトを書いてみた。 TABLEのコードを抜き出し、以下のスクリプトで処理すると、<LABEL>を含む<XP:TD>を<TH>に書き換えてくれる。 この条件を変えれば、いろいろできるだろう。

  require "rexml/document"
  include REXML
  
  def analize_cdatas(cdatas)
    lines = []
    cdatas.each {|cdata|
      lines.push "<![CDATA["
  
      code_str = cdata.to_s
      if code_str =~ /^\#\{javascript\:(.+)\}$/m
        js_code_str = $1
  
        lines.push "  #\{javascript:"
        js_code_str.split(/\n/).each {|oneline|
          oneline.gsub!(/\t/, "  ")
          lines.push "    #{oneline}"
        }
        lines.push "  }"
      else
        lines.push "  #{cdata.to_s}"
      end
      lines.push "]]>"
    }
    lines
  end
  
  def modify_element(element, level)
  
    # 子要素がlabelならTD->THに変更
    element.each_element { |subelem|
      if ((element.expanded_name == "xp:td") and 
        (subelem.expanded_name == "xp:label"))
        element.name = "TH"
      end
    }
    element.each_element { |subelem|
      modify_element(subelem, level + 1)
    }
  end
  
  def show_element(element, level)
    sp = '  ' * level
  
    if element.has_attributes?
      attr_list = []
      element.attributes.each {|name, value|
        attr_list.push "#{name}=\"#{value}\""
      }
      @output_list.push "#{sp}<#{element.expanded_name} #{attr_list.join(' ')}>"
    else
      @output_list.push "#{sp}<#{element.expanded_name}>"
    end
    current_output_lineno = @output_list.size
    # この要素がCDATAセクションを持っているか
    if element.cdatas.size > 0
      cdata_lines = analize_cdatas(element.cdatas)
      cdata_lines.each {|oneline|
        @output_list.push "#{sp}  #{oneline}"
      }
    end
    element.each_element { |subelem|
      show_element(subelem, level + 1)
    }
  
    # 出力行数が増えてないなら、開始タグと終了タグの間に挟むべきものがないということ
    if current_output_lineno == @output_list.size
      last_output = @output_list.pop
      last_output.gsub!(/\>$/, " />")   # <xp:tag....> → <xp:tag.... />
      @output_list.push last_output
    else
      @output_list.push "#{sp}</#{element.expanded_name}>"
    end
  end
  
  @output_list = []
  filename = ARGV.shift
  doc = Document.new File.new(filename)
  xml_decl = doc.xml_decl   # XML宣言
  if xml_decl.to_s != ""
    @output_list.push xml_decl.to_s
  end
  modify_element(doc.root, 0)
  
  show_element(doc.root, 0)
  @output_list.each {|oneline|
    puts oneline
  }