JavaScriptとCSSでタブ

本当はS2JSF用のコンポーネントを書いていたのだが、JavaScriptだけでも便利に使えそうなので途中からJavaScriptオンリーで。ソースは出来るだけFlexに近い書き方になるようにしてみた。

IEの場合は setAttribute('onclick', function(){hoge();}, false) のように第2引数を文字列でなくFunctionオブジェクトにしなきゃいけない部分で四苦八苦。ちょっとやられたって感じ。その分、公開してもそんなに恥ずかしくないようなものが出来たと思うんで気にしない。と言ってもtabnavigatorのネストは考慮に入れてないからやっぱまだダサいソースだ。
ソース量も長すぎ。また時間みてリファクタリングしよ。

Flex Samples ExplorerみたいにJavaScriptのサンプルエクスプローラー作ろうかな。

<html xmlns:m="http://www.seasar.org/maya">

<head>
<meta http-equiv="Content-Type" content="text/html; charset=Windows-31j">
<title>Tab Navigator</title>
<style type="text/css">
.CanvasLabelWithLeftBorder {
  padding: 0.2em 1em 0.2em 1em;
  border: silver 1px solid;
  white-space: nowrap;
  cursor: pointer;
}
.CanvasLabelNonLeftBorder {
  padding: 0.2em 1em 0.2em 1em;
  border: silver 1px solid;
  border-left-width: 0px;
  white-space: nowrap;
  cursor: pointer;
}
.CanvasLabelOpenning {
  background:transparent;
  border-bottom:1px solid silver;
}
.CanvasLabelLast {
  background:transparent;
  border-bottom:1px solid silver;
  width:100%;
}
</style>
<script language="JavaScript" type="text/javascript">
<!--
function strongTab(ele){
  if(ele.style.borderBottomWidth != '0px'){
    ele.style.background = '#fafafa';
  }
}
function normalTab(ele){
  if(ele.style.borderBottomWidth != '0px'){
    ele.style.background = '#f0f0f0';
  }
}
function createTab() {
  var tabNum = 0;
  var tabnavi;
  var tabTable;
  var tabTBody;
  var tabCurrentRow;
  var tabCurrentCell;
  var firstCanvas;
  var divEle = document.getElementsByTagName('DIV');
  for (i = 0; i < divEle.length; i++) {
    if (divEle[i].className=="TabNavigator") {
      tabnavi = divEle[i];
      tabTable = document.createElement("TABLE");
      tabTable.setAttribute("CELLSPACING","0",false);
      tabTable.cellspacing="0";
      tabTBody = document.createElement("TBODY");
      tabCurrentRow=document.createElement("TR");
    }
    if (divEle[i].className=="Canvas" && tabnavi != null) {
      tabCurrentCell=document.createElement("TD");
      if(tabNum>0){
        tabCurrentCell.className="CanvasLabelNonLeftBorder";
      }else{
        tabCurrentCell.className="CanvasLabelWithLeftBorder";
        firstCanvas=divEle[i];
      }
      if(navigator.appName=="Microsoft Internet Explorer"){
        tabCurrentCell.setAttribute("ONCLICK",function(){openTab(this);},false);
        tabCurrentCell.setAttribute("ONMOUSEOVER",function(){strongTab(this);},false);
        tabCurrentCell.setAttribute("ONMOUSEOUT",function(){normalTab(this);},false);
      }else{
        tabCurrentCell.setAttribute("ONCLICK","openTab(this)",false);
        tabCurrentCell.setAttribute("ONMOUSEOVER","strongTab(this)",false);
        tabCurrentCell.setAttribute("ONMOUSEOUT","normalTab(this)",false);
      }
      cellText=document.createTextNode(divEle[i].title);
      tabCurrentCell.appendChild(cellText);
      tabCurrentRow.appendChild(tabCurrentCell);
      tabNum++;
    }
  }
  tabCurrentCell=document.createElement("TD");
  tabCurrentCell.className="CanvasLabelLast";
  cellText=document.createTextNode(" ");
  tabCurrentCell.appendChild(cellText);
  tabCurrentRow.appendChild(tabCurrentCell);
  tabTBody.appendChild(tabCurrentRow);
  tabTable.appendChild(tabTBody);
  tabnavi.insertBefore(tabTable,firstCanvas);
  //タブコンテンツの初期化
  for (i = 0; i < divEle.length; i++) {
    if (divEle[i].className=="Canvas") {
      divEle[i].style.visibility = "hidden";
      divEle[i].style.position = "absolute";
    }
  }
}
function openTab(ele){
  var tabNum = 0;
  var contentsNum = 0;
  var tabEle = document.getElementsByTagName('TD');
  for (i = 0; i < tabEle.length; i++) {
    if (tabEle[i].className=="CanvasLabelNonLeftBorder" || tabEle[i].className=="CanvasLabelWithLeftBorder") {
      tabEle[i].style.background  = '#f0f0f0';
      tabEle[i].style.borderBottomColor = 'silver';
      tabEle[i].style.borderBottomWidth = '1px';
      tabEle[i].style.padding = '0.2em 1em 0.2em 1em';
      if(tabEle[i]==ele) {
        contentsNum=tabNum;
      }
      tabNum++;
    }
  }
  ele.style.background = 'transparent';
  ele.style.borderBottomWidth = '0px';
  ele.style.padding = '0.3em 1em 0.1em 1em';
  openContents(contentsNum);
  return tabNum;
}
function openContents(num){
  var contentsNum = 0;
  var divEle = document.getElementsByTagName('DIV');
  for (i = 0; i < divEle.length; i++) {
    if (divEle[i].className=="Canvas") {
      if(contentsNum==num){
        divEle[i].style.visibility = "visible";
        divEle[i].style.position = "";
      }else{
        divEle[i].style.visibility = "hidden";
        divEle[i].style.position = "absolute";
      }
      contentsNum++;
    }
  }
}
function init(element){
  //タブの生成
  createTab();
  //タブのオープン
  var eleTd = document.getElementsByTagName('TD');
  var eleDiv = document.getElementsByTagName('DIV');
  if(element != null){
    var contentsNum=0;
    for (var i = 0; i < eleDiv.length; i++) {
      if (eleDiv[i].className=="Canvas") {
        if(eleDiv[i]==element) break;
        contentsNum++;
      }
    }
    var tabNum=0;
    for (var i = 0; i < eleTd.length; i++) {
      if (eleTd[i].className=="CanvasLabelWithLeftBorder" || eleTd[i].className=="CanvasLabelNonLeftBorder") {
        if(tabNum++ == contentsNum){
          openTab(eleTd[i]);
          break;
        }
      }
    }
  }else{
    for (var i = 0; i < eleTd.length; i++) {
      if (eleTd[i].className=="CanvasLabelWithLeftBorder" || eleTd[i].className=="CanvasLabelNonLeftBorder") {
        openTab(eleTd[i]);
        break;
      }
    }
  }
}
// -->
</script>
</head>

<body onload="init()">

<h1>Tab Navigator</h1>

<div class="TabNavigator" style="width:400; height:100;">
  <div class="Canvas" title="Tab 1">
    <h2>タブ1コンテンツ</h2>
  </div class="Canvas">
  <div class="Canvas" title="Tab 2">
    <h2>タブ2コンテンツ</h2>
  </div class="Canvas">
  <div class="Canvas" title="Tab 3">
    <h2>タブ3コンテンツ</h2>
  </div class="Canvas">
</div class="TabNavigator">

<hr/>

<h2>Html source</h2>

<pre>
&lt;html xmlns:m="http://www.seasar.org/maya">
&lt;head>
  &lt;meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
  &lt;script language="javascript" type="text/javascript" src="js/tabnavigator.js"/>
&lt;/head>
&lt;body onload="init()">
  &lt;div class="TabNavigator" style="width:250; height:100;">
    &lt;div class="Canvas" title="Tab 1">
      &lt;h2>タブ1コンテンツ&lt;/h2>
    &lt;/div class="Canvas">
    &lt;div class="Canvas" title="Tab 2">
      &lt;h2>タブ2コンテンツ&lt;/h2>
    &lt;/div class="Canvas">
    &lt;div class="Canvas" title="Tab 3">
      &lt;h2>タブ3コンテンツ&lt;/h2>
    &lt;/div class="Canvas">
  &lt;/div class="TabNavigator">
&lt;/body>
&lt;/html>
</pre>

<hr/>

<h2>Flex source</h2>

<pre>
&lt;?xml version="1.0" encoding="utf-8"?>
&lt;mx:Application xmlns:mx="http://www.macromedia.com/2003/mxml">
  &lt;mx:TabNavigator width="250" height="200">
    &lt;mx:Canvas label="Tab 1">
    &lt;/mx:Canvas>
    &lt;mx:Canvas label="Tab 2">
    &lt;/mx:Canvas>
    &lt;mx:Canvas label="Tab 3">
    &lt;/mx:Canvas>
  &lt;/mx:TabNavigator>
&lt;/mx:Application>
</pre>

</body>

</html>