001/* 002 * Copyright (c) 2009 The openGion Project. 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, 013 * either express or implied. See the License for the specific language 014 * governing permissions and limitations under the License. 015 */ 016package org.opengion.hayabusa.taglib; 017 018import org.opengion.fukurou.system.OgBuilder ; // 6.4.4.1 (2016/03/18) 019 020import org.opengion.fukurou.util.TagBuffer; 021import org.opengion.fukurou.util.XHTMLTag; 022import org.opengion.fukurou.util.ToString; // 6.1.1.0 (2015/01/17) 023import org.opengion.hayabusa.common.HybsSystemException; 024import org.opengion.hayabusa.db.DBTableModel; 025import org.opengion.hayabusa.db.DBTableModelUtil; 026 027import static org.opengion.fukurou.util.StringUtil.nval; 028 029import java.io.IOException; 030import java.io.ObjectInputStream; 031import java.util.ArrayList; 032import java.util.List; 033import java.util.Locale; 034import java.util.Arrays; // 6.4.3.4 (2016/03/11) 035import java.util.stream.Collectors; // 6.4.3.4 (2016/03/11) 036 037/** タブ形式のリンクを表示するタグです。 038 * 039 * このタグ形式の実態は、リンクのリストであるため、実の画面の表示はターゲットを指定して 040 * 別フレームで行う必要があります。 041 * 042 * タブの指定方法については、listType属性の指定により、クエリ発行(DB)により動的に生成する 043 * パターンと、タグ指定(TAG)により、静的に生成するパターンがあります。 044 * listType属性に何も指定されていない場合は、Body部分に記述された内容により、自動判定されます。 045 * ("SELECT"で始まっている場合はDB、それ以外はTAGとして処理) 046 * 047 * ①listType属性が"DB"の場合 048 * 検索された各カラムは、その順番により次の意味を持ちます。 049 * [第1カラム] タブの名前 : リンク時のキー情報、後述のopenTabName属性のキーとしても使用 ※必須 050 * [第2カラム] タブの表示名称 : タブの表示名称 指定がない場合は、第1カラムが表示名称となります。 051 * [第3カラム] タブのリンク先URL : タブのリンク先URL 指定がない場合は、href属性の値が適用されます。 052 * [第4カラム] タブのクラス属性 : 個別のタブに付加されるクラス属性 指定がない場合は、unselClass属性の値が適用されます。 053 * [第5カラム] タブのロールズ : タブのロールズを指定します。ユーザーロールズと一致しない指定した場合は、タブが表示されなくなります。 054 * [第6カラム] タブの選択可否 : タブの選択可否を'true'or'false'で指定します。falseを指定した場合は、タブが表示されなくなります。 055 * (ロールズで選択不可になっている場合は、この値は無視されます) 056 * 各カラムの値は[カラム名]=[値]の形で、リンク先のJSPに引数として渡されます。 057 * また、リンク先のJSPについては、href属性で指定します。 058 * 059 * ②listType属性が"TAG"の場合 060 * tabListタグを記述し、個別にタブを定義します。 061 * 制御可能な項目は、①DBの場合と同等です。 062 * タブの名前を定義するname属性は、tabListタグで必ず定義する必要があります。 063 * lbl属性が指定されていない場合は、name属性のラベル名称を取得します。 064 * タブのリンク先JSP及び、クラス属性については、tabListタグで指定がない場合、tabListタグの値が適用されます。 065 * 066 * [共通設定] 067 * 初期設定では、第1番目の"有効な"タブが自動的に開かれます。(="true") 068 * 各タブの表示方法で、選択不可能なタブが存在している場合は、それらを読み飛ばした上で、"有効な"タブを 069 * 検索します。 070 * また、自動で開くタブは、openTabName属性で指定可能であり、これに変数を定義することで、 071 * 画面リロード時も、開いていたタブを再度選択された状態で表示することが可能です。 072 * 073 * 7.4.1.0 (2021/04/23) 074 * openTab = false を指定すると、自動でオープンしません。 075 * 076 * 選択したタブ及び非選択のタブの枠線や、背景色等を変更する場合は、custom.cssでクラスを定義し、 077 * 変更して下さい。 078 * 079 * タブの表示方向(水平方向 or 垂直方向)については、orientation属性で変更することが可能です。 080 * (初期値は、水平方向) 081 * 水平方向にした場合は、listCount属性により強制的に一定数のタブを表示する毎に、改行を挿入することができます。 082 * 083 * このタグを使用する場合は、headタグで必ずuseTabLink="true"を指定してJavaScriptをロードして下さい。 084 * 085 * 各属性は、{@XXXX} 変数が使用できます。 086 * これは、ServletRequest から、XXXX をキーに値を取り出し、この変数に割り当てます。 087 * つまり、このXXXXをキーにリクエストすれば、この変数に値をセットすることができます。 088 * 089 * @og.formSample 090 * ●形式:<og:tabLink href="…" … /> 091 * ●body:あり(EVAL_BODY_BUFFERED:BODYを評価し、{@XXXX} を解析します) 092 * 093 * ●Tag定義: 094 * <og:tabLink 095 * listType 【TAG】タブの一覧をどこから取得するかを指定します(初期値:AUTO) 096 * href 【TAG】リンク先のJSPを指定します(初期値:result.jsp) 097 * target 【TAG】リンクのターゲットを指定します(初期値:RESULT) 098 * openTab 【TAG】リンク表示にタブリンクを自動で開くかどうか[true/false]を指定します(初期値:true[=開く]) 099 * openTabName 【TAG】最初に開くタブリンクの名前を指定します 100 * constKeys 【TAG】次画面に渡す定数パラメーターのキーを指定します 101 * constVals 【TAG】次画面に渡す定数パラメーターの値を指定します 102 * listCount 【TAG】1行辺りに表示するタブの数を指定します(初期値:10) 103 * selClass 【TAG】選択タブのクラスを指定します(初期値:selTab) 104 * unselClass 【TAG】非選択タブのクラスを指定します(初期値:unselTab) 105 * orientation 【TAG】タブの方向、横型(Horizontal)か縦型(Vertical)を指定します(初期値:横型) 106 * width 【TAG】タブリンクの幅を % 、px 、または "auto" で指定します 107 * height 【TAG】タブの高さを、% 、px 、または "auto" で指定します 108 * onClick 【HTML】JavaScriptのイベント onClick を設定します(初期値::onClick="changeTab( this, 'selTab' );") 7.4.1.0 (2021/04/23) 109 * caseKey 【TAG】このタグ自体を利用するかどうかの条件キーを指定します(初期値:null) 7.4.1.0 (2021/04/23) 110 * caseVal 【TAG】このタグ自体を利用するかどうかの条件値を指定します(初期値:null) 7.4.1.0 (2021/04/23) 111 * caseNN 【TAG】指定の値が、null/ゼロ文字列 でない場合(Not Null=NN)は、このタグは使用されます(初期値:判定しない) 7.4.1.0 (2021/04/23) 112 * caseNull 【TAG】指定の値が、null/ゼロ文字列 の場合は、このタグは使用されます(初期値:判定しない) 7.4.1.0 (2021/04/23) 113 * caseIf 【TAG】指定の値が、true/TRUE文字列の場合は、このタグは使用されます(初期値:判定しない) 7.4.1.0 (2021/04/23) 114 * debug 【TAG】デバッグ情報を出力するかどうか[true/false]を指定します(初期値:false) 115 * > ... Body ... 116 * </og:tabLink> 117 * 118 * ●使用例 119 * ①DBからタブリストを取得する場合 120 * 121 * Body部分に記述されたクエリよりタブ一覧を生成します。 122 * 123 * <og:tabLink 124 * listType = "DB" タブの一覧をどこから取得するか 125 * href = "result.jsp" リンク先のJSP 126 * target = "RESULT" リンクターゲット 127 * openTab = "[true/false]" タブ表示後にタブを自動で開く 128 * openTabName = "{@PN} 自動で開くタブの名前 129 * constKeys = "KEY1" 次画面に固定で渡すキー一覧 130 * constVals = "{@VAL1}" 次画面に固定で渡す値一覧 131 * listCount = "10" 1行辺りに表示するタブの数 132 * selClass = "selTab" 選択タブのクラス 133 * unselClass = "unselTab" 非選択タブのクラス 134 * width = "100px" タブリンクの幅 135 * height = "50px" タブリンクの高さ 136 * > 137 * select PN,HINM,'tabClass','query.jsp','ADMIN','false' from XX01 where PN = '{@PN}' order by PN 138 * </og:tabLink> 139 * 140 * ②tabListタグからタブリストを生成する場合 141 * 142 * tabListタグよりタブ一覧を生成します。 143 * 144 * <og:tabLink 145 * listType = "DB" タブの一覧をどこから取得するか 146 * href = "result.jsp" リンク先のJSP 147 * target = "RESULT" リンクターゲット 148 * openTab = "[true/false]" タブ表示後にタブを自動で開く 149 * openTabName = "{@PN} 自動で開くタブの名前 150 * constKeys = "KEY1" 次画面に固定で渡すキー一覧 151 * constVals = "{@VAL1}" 次画面に固定で渡す値一覧 152 * listCount = "10" 1行辺りに表示するタブの数 153 * selClass = "selTab" 選択タブのクラス 154 * unselClass = "unselTab" 非選択タブのクラス 155 * width = "100px" タブリンクの幅 156 * height = "50px" タブリンクの高さ 157 * > 158 * <og:tabList name="TAB1" href="result1.jsp" keys="PN,CDK" vals="ABC,V" /> 159 * <og:tabList name="TAB2" href="result2.jsp" keys="PN,CDK" vals="BCD,W" /> 160 * <og:tabList name="TAB3" href="result3.jsp" keys="PN,CDK" vals="CDE,X" /> 161 * </og:tabLink> 162 * 163 * @og.group 画面表示 164 * 165 * @version 0.9.0 2008/09/26 166 * @author Nakamura 167 * @since JDK1.4, 168 */ 169public class TabLinkTag extends CommonTagSupport { 170 private static final String VERSION = "7.4.1.0 (2021/04/23)" ; 171 private static final long serialVersionUID = 741020210423L ; 172 173 /** リストのulタグのclass属性 */ 174 private static final String UL_TAG_START = "<ul class=\"tabList\">"; 175 private static final String UL_TAG_END = "</ul>"; 176 177 /** タブ表示を入れ替えるためのJavaScript関数 */ 178 private static final String CHANGE_TAB_SCRIPT = "changeTab"; 179 private static final String INITIAL_TAB_SCRIPT = "initialTabSelect"; 180 181 /** 自動で開くタブに付加されるID */ 182 private static final String FIRST_TAB_ID = "firstTab"; 183 184 /** リスト取得タイプのEnum */ 185 private enum LIST_TYPE { AUTO, DB, TAG }; 186// private static enum LIST_TYPE { AUTO, DB, TAG }; 187 188 /** 内部変数 */ 189 private String query ; 190 private transient List<TabData> tabData = new ArrayList<>(); 191 192 /** タグで設定する属性 */ 193 private LIST_TYPE type = LIST_TYPE.AUTO; 194 private String href = "result.jsp"; 195 private String target = "RESULT"; 196 private boolean openTab = true; 197 private String openTabName ; 198 private String[] constKeys ; 199 private String[] constVals ; 200 private int listCount = 10; 201 private String selClass = "selTab"; 202 private String unselClass = "unselTab"; 203 private boolean isHorizontal = true; 204 private String width = "auto"; 205 private String height = "auto"; 206 private String onClick = CHANGE_TAB_SCRIPT; // 7.4.1.0 (2021/04/23) 207 208 /** 209 * デフォルトコンストラクター 210 * 211 * @og.rev 6.4.2.0 (2016/01/29) PMD refactoring. Each class should declare at least one constructor. 212 */ 213 public TabLinkTag() { super(); } // これも、自動的に呼ばれるが、空のメソッドを作成すると警告されるので、明示的にしておきます。 214 215 /** 216 * Taglibの開始タグが見つかったときに処理する doStartTag() を オーバーライドします。 217 * 218 * @og.rev 7.4.1.0 (2021/04/23) caseKey,caseVal,caseNN,caseNull,caseIf 属性を追加 219 * 220 * @return 後続処理の指示( EVAL_BODY_BUFFERED ) 221 */ 222 @Override 223 public int doStartTag() { 224 // 7.4.1.0 (2021/04/23) caseKey,caseVal,caseNN,caseNull,caseIf 属性を追加 225 if( !useTag() ) { return SKIP_BODY ; } 226 227 return EVAL_BODY_BUFFERED ; // Body を評価する 228 } 229 230 /** 231 * Taglibのタグ本体を処理する doAfterBody() を オーバーライドします。 232 * 233 * @og.rev 6.3.1.1 (2015/07/10) BodyString,BodyRawStringは、CommonTagSupport で、trim() します。 234 * 235 * @return 後続処理の指示(SKIP_BODY) 236 */ 237 @Override 238 public int doAfterBody() { 239 query = getBodyString(); 240 return SKIP_BODY ; 241 } 242 243 /** 244 * Taglibの終了タグが見つかったときに処理する doEndTag() を オーバーライドします。 245 * 246 * @og.rev 4.3.5.0 (2008/02/01) 処理及び内部構造を大幅に見直し 247 * @og.rev 7.4.1.0 (2021/04/23) caseKey,caseVal,caseNN,caseNull,caseIf 属性を追加 248 * 249 * @return 後続処理の指示 250 */ 251 @Override 252 public int doEndTag() { 253 debugPrint(); 254 255 // 7.4.1.0 (2021/04/23) caseKey,caseVal,caseNN,caseNull,caseIf 属性を追加 256 if( !useTag() ) { return EVAL_PAGE ; } 257 258// final int rtnCode = EVAL_PAGE; // 7.4.1.0 (2021/04/23) 書き換えてないので、直接指定します。 259 260 // 種別の自動判定処理 261 if( type == LIST_TYPE.AUTO ) { 262 if( query == null || query.isEmpty() ) { 263 type = LIST_TYPE.TAG; 264 } 265 else { 266 if( query.toUpperCase( Locale.JAPAN ).indexOf( "SELECT" ) >= 0 ) { 267 type = LIST_TYPE.DB; 268 } 269 else { 270 type = LIST_TYPE.TAG; 271 } 272 } 273 } 274 275 if( type == LIST_TYPE.DB ) { 276 makeTabsFromQuery(); 277 } 278 else if( type == LIST_TYPE.TAG ) { 279 makeTabsFromTag(); 280 } 281 282 // リンク一覧が何も設定されていない場合は、処理しない 283 if( ! tabData.isEmpty() ) { 284 makeTag(); 285 } 286 287// return rtnCode ; 288 return EVAL_PAGE ; // 7.4.1.0 (2021/04/23) 289 } 290 291 /** 292 * タグリブオブジェクトをリリースします。 293 * キャッシュされて再利用されるので、フィールドの初期設定を行います。 294 * 295 * @og.rev 7.4.1.0 (2021/04/23) タブをクリックした際のJavaScriptを外部から設定できるようにします。 296 */ 297 @Override 298 protected void release2() { 299 super.release2(); 300 query = null; 301 tabData = new ArrayList<>(); 302 type = LIST_TYPE.AUTO; 303 href = "result.jsp"; 304 target = "RESULT"; 305 openTab = true; 306 openTabName = null; 307 constKeys = null; 308 constVals = null; 309 listCount = 10; 310 selClass = "selTab"; 311 unselClass = "unselTab"; 312 isHorizontal = true; 313 width = "auto"; 314 height = "auto"; 315 onClick = CHANGE_TAB_SCRIPT; // 7.4.1.0 (2021/04/23) 316 } 317 318 /** 319 * DBからタブリンクの一覧を作成します。 320 * DBTableModelが作成されない(行数が0の場合)は、リンク一覧は生成されません。 321 * 322 * @og.rev 6.3.9.1 (2015/11/27) 3項演算子を || or && で簡素化できる(PMD)。 323 */ 324 private void makeTabsFromQuery() { 325 final DBTableModel table = DBTableModelUtil.makeDBTable( query, new String[0], getResource(), getApplicationInfo() ); 326 if( table == null || table.getRowCount() == 0 ) { 327 return; 328 } 329 330 // 6.3.9.1 (2015/11/27) 初期値設定の簡素化 331 final boolean isSetLabel = table.getColumnCount() > 1; 332 final boolean isSetHref = table.getColumnCount() > 2; 333 final boolean isSetClazz = table.getColumnCount() > 3; 334 final boolean isSetRoles = table.getColumnCount() > 4; 335 final boolean isSetVisible = table.getColumnCount() > 5; 336 337 final int rowCount = table.getRowCount(); 338 final String key = table.getColumnName( 0 ); 339 // 6.3.9.1 (2015/11/27) visible=true以外は処理しないので、先に求める。 340 for( int row=0; row<rowCount; row++ ) { 341 final boolean visible = ( !isSetRoles || getUser().isAccess( table.getValue( row, 4 ) ) ) && 342 ( !isSetVisible || Boolean.valueOf( table.getValue( row, 5 ) ) ); 343 344 if( visible ) { 345 final String value = table.getValue( row, 0 ); 346 final String label = ( isSetLabel ? nval( table.getValue( row, 1 ), value ) : value ); 347 String newHref = ( isSetHref ? nval( table.getValue( row, 2 ), href ) : href ); 348 // 第1カラムのカラム名とその値はリンクの引数に含める 349 newHref = XHTMLTag.addUrlEncode( newHref, XHTMLTag.urlEncode( key, value ) ); 350 351 final String clazz = ( isSetClazz ? nval( table.getValue( row, 3 ), unselClass ) : unselClass ); 352 353 tabData.add( new TabData( newHref, value, label, clazz, visible ) ); 354 } 355 } 356 } 357 358 /** 359 * タブリストからタブリンクの一覧を作成します。 360 * (予めaddTagメソッドにより、リンク一覧が登録されているため、ここでは何も処理しません) 361 * 362 * @see #addTag( String, String, String, String, boolean, String[], String[] ) 363 */ 364 private void makeTabsFromTag() { 365 // 何もありません。(PMD エラー回避) 366 } 367 368 /** 369 * 子タグであるタブリストタグからタブ情報をセットします。 370 * 371 * @param hr 画面URL 372 * @param name タブの名前 373 * @param label タブの表示名称 374 * @param clz 非選択状態のタブに付加するclass名 375 * @param visible タブが選択可能 [true:可能/false:不可能] 376 * @param keys リンク先のJSPに渡すキー一覧 377 * @param vals リンク先のJSPに渡す値一覧 378 */ 379 protected void addTag( final String hr, final String name, final String label, final String clz 380 ,final boolean visible, final String[] keys, final String[] vals ) { 381 String newHref = nval( hr, href ); 382 if( keys != null && keys.length > 0 ) { 383 newHref = XHTMLTag.addUrlEncode( newHref, XHTMLTag.urlEncode( keys, vals ) ); 384 } 385 386 if( visible ) { // visible=falseの場合は表示しない 387 tabData.add( new TabData( newHref, name, nval( label, getLabel( name ) ), nval( clz, unselClass ), visible ) ); 388 } 389 } 390 391 /** 392 * リンク一覧からHTMLタグを作成します。 393 * 394 * @og.rev 5.0.2.0 (2009/11/01) openTab属性がfalseの場合でも、openTabNameに指定されたタブに色付けする。 395 * @og.rev 5.1.4.0 (2010/03/01) FF対応&FirstTabのID付加に関するバグを修正 396 * @og.rev 6.4.4.1 (2016/03/18) StringBuilderの代わりに、OgBuilderを使用する。 397 * @og.rev 7.4.1.0 (2021/04/23) openTab=false の場合は、自動でオープンしません。 398 */ 399 private void makeTag() { 400 final OgBuilder buf = new OgBuilder().appendCR(); 401 402 boolean isExistFirst = false; 403 for( int idx=0; idx<tabData.size(); idx++ ) { 404 final TabData tab = tabData.get( idx ); 405 406 if( idx % listCount == 0 ) { 407 buf.appendIfCR( idx > 0 , UL_TAG_END ) // if 408 .appendCR( UL_TAG_START ); 409 } 410 411 // openTabNameが定義されていない場合は、1番目の有効なタブを開く 412 // 5.1.4.0 (2010/03/01) バグ修正 413 if( !isExistFirst && tab.visible 414 && ( openTabName == null || openTabName.isEmpty() || openTabName.equals( tab.name ) ) ) { 415 // 7.4.1.0 (2021/04/23) 選択タブのクラスをセットします。 416 final TabData tab2 = tab.copyTab( selClass ); 417 418// buf.append( tab.makeLiTag( idx, true ) ); 419 buf.append( tab2.makeLiTag( idx, true ) ); 420 isExistFirst = true; 421 } 422 else { 423 buf.append( tab.makeLiTag( idx, false ) ); 424 } 425 } 426 // 7.4.1.0 (2021/04/23) openTab=false の場合は、自動でオープンしません。 427 buf.appendCR( UL_TAG_END ) 428// .appendIf( openTab || openTabName != null && openTabName.length() > 0 // 6.9.7.0 (2018/05/14) PMD Useless parentheses. 429 .appendIf( openTab && openTabName != null && openTabName.length() > 0 // 6.9.7.0 (2018/05/14) PMD Useless parentheses. 430 // 8.1.0.0 (2021/12/28) HTML5 準拠に見直し(<script> type属性削除) 431// , "<script type=\"text/javascript\">addEvent(window,\"load\", function() { " 432 , "<script>addEvent(window,\"load\", function() { " 433 , INITIAL_TAB_SCRIPT 434 , "(" , String.valueOf( openTab ) , "); } );</script>" ); 435 436 jspPrint( buf.toString() ); 437 } 438 439 /** 440 * Tabデータ を管理している 内部クラス 441 * 442 * タブの情報を管理するための簡易的な、内部クラスです。 443 */ 444 private final class TabData { 445 // 引数として初期設定される変数 446 private final String href; 447 private final String name; 448 private final String label; 449 private final String clazz; 450 // 現状の実装では、visible=falseは渡ってきませんが、将来的にdisableの状態で 451 // 表示したい場合等に対応するため残しておきます。 452 private final boolean visible; 453 454 /** 455 * コンストラクタ 456 * 457 * @param hr 画面URL 458 * @param nm タブの名前 459 * @param lbl タブの表示名称 460 * @param clz 非選択状態のタブに付加するclass名 461 * @param vsb タブが選択可能 [true:可能/false:不可能] 462 */ 463 public TabData( final String hr, final String nm, final String lbl, final String clz, final boolean vsb ) { 464 href = hr; 465 name = nm; 466 label = lbl; 467 clazz = clz; 468 visible = vsb; 469 } 470 471 /** 472 * class名違いの新しいTabDataを作成します。 473 * 474 * 通常、選択状態のクラス名を付ける場合に、使用します。 475 * 476 * @param clz タブに付加するclass名 477 * @return class名違いの新しいTabData 478 */ 479 public TabData copyTab( final String clz ) { 480 return new TabData( href,name,label,clz,visible ); 481 } 482 483 /** 484 * liタグの部分の文字列を生成します。 485 * 486 * @og.rev 6.4.4.1 (2016/03/18) StringBuilderの代わりに、OgBuilderを使用する。 487 * 488 * @param idx 生成したタブのインデックス番号 489 * @param isFirst 始めの有効なタブかどうか[true:始め/false:それ以外] 490 * @return liタグ文字列 491 * @og.rtnNotNull 492 */ 493 private String makeLiTag( final int idx, final boolean isFirst ) { 494 return new OgBuilder() 495 .append( "<li class=\"" , clazz , "\"" 496 , " style=\"" 497 , " width: " , width , ";" 498 , " height: " , height , ";" ) 499 .appendIf( isHorizontal , " float: left;" ) 500 .appendIf( isHorizontal && ( idx % listCount == 0 ) // if-if なので、少し無駄かも 501 , " clear: left; margin-left: " 502 , String.valueOf( (idx/listCount) * 10 ) 503 , "px;" ) 504 .appendCR( " \">" , makeLinkTag( isFirst ) , "</li>" ) 505 .toString(); 506 } 507 508 /** 509 * aタグの部分の文字列を生成します。 510 * タブが選択不可能な状態の場合は、タブの表示文字列をそのまま返します。 511 * 512 * @og.rev 4.3.6.4 (2009/05/01) 戻るボタンがでない問題への対応 513 * @og.rev 7.4.1.0 (2021/04/23) タブをクリックした際のJavaScriptを外部から設定できるようにします。 514 * 515 * @param isFirst 始めの有効なタブかどうか[true:始め/false:それ以外] 516 * @return liタグ文字列 517 * @og.rtnNotNull 518 */ 519 private String makeLinkTag( final boolean isFirst ) { 520 String newHref = XHTMLTag.addUrlEncode( href, XHTMLTag.urlEncode( constKeys, constVals ) ); 521 // 4.3.6.4 (2009/05/01) 522 // タブ画面から遷移した時に、タブの読込により、画面IDが消えてしまい 523 // 戻るボタンがでない不具合への対応 524 newHref = XHTMLTag.addUrlEncode( newHref, "GAMENID=" + getGUIInfoAttri( "KEY" ) ); 525 526 // 7.4.1.0 (2021/04/23) タブをクリックした際のJavaScriptを外部から設定できるようにします。 527 if( CHANGE_TAB_SCRIPT.equals( onClick ) ) { // つまり、デフォルトのまま 528 onClick = CHANGE_TAB_SCRIPT + "( this, \"" + selClass + "\" );" ; 529 } 530 531 // 6.1.1.0 (2015/01/17) TagBufferの連結記述 532 return new TagBuffer( "a" ) 533 .add( "href" , newHref ) 534 .add( "name" , name ) 535 .add( "target" , target ) 536// .add( "onClick" , CHANGE_TAB_SCRIPT + "( this, \"" + selClass + "\" );" ) 537 .add( "onClick" , onClick , onClick != null ) // 7.4.1.0 (2021/04/23) null 以外は追加する。 538 .add( "id" , FIRST_TAB_ID , isFirst ) 539 .addBody( label ) 540 .makeTag(); 541 } 542 } 543 544 /** 545 * 【TAG】タブの一覧をどこから取得するか[AUTO/DB/TAG]を指定します(初期値:AUTO)。 546 * 547 * @og.tag 548 * タブの一覧をどこから取得するかを指定します。 549 * 現状の実装では、クエリを発行して一覧を生成する「DB」と、子タグである 550 * tabListタグを列挙してタブを定義する「TAG」が実装されています。 551 * 552 * また、「AUTO」と指定した場合は、Body部分の内容に応じて自動的に判定されます。 553 * 初期値は、「AUTO」です。 554 * 555 * @og.rev 6.4.3.4 (2016/03/11) CSV形式の文字連結を、stream 経由で行います。 556 * 557 * @param tp 取得方法 [AUTO/DB/TAG] 558 */ 559 public void setListType( final String tp ) { 560 final String typeStr = nval( getRequestParameter( tp ), null ); 561 try { 562 type = LIST_TYPE.valueOf( typeStr ); 563 } 564 catch( final IllegalArgumentException ex ) { 565 final String errMsg = Arrays.stream( LIST_TYPE.values() ) 566 .map( obj -> obj.name() ) 567 .collect( Collectors.joining( "," , "listType は " , " から選んでください。" ) ); // 連結文字 , 最初 , 最後 568 throw new HybsSystemException( errMsg, ex ); 569 } 570 } 571 572 /** 573 * 【TAG】リンク先のJSPを指定します(初期値:result.jsp)。 574 * 575 * @og.tag 576 * リンク先のJSPを指定します。 577 * このタブリンクは、あくまで「タブの形をしたリンク」なので、 578 * target属性と合わせてセットする必要があります。 579 * 初期値は、「result.jsp」です。 580 * 581 * @param hr リンク先のJSP 582 */ 583 public void setHref( final String hr ) { 584 href = nval( getRequestParameter( hr ), href ); 585 } 586 587 /** 588 * 【TAG】リンクのターゲットを指定します(初期値:RESULT)。 589 * 590 * @og.tag 591 * リンクのターゲットを指定します。 592 * このタブリンクは、あくまで「タブの形をしたリンク」なので、 593 * target属性を設定し、別のフレームに実画面を表示するようにします。 594 * 初期値は、「RESULT」です。 595 * 596 * @param tgt リンクターゲット 597 */ 598 public void setTarget( final String tgt ) { 599 target = nval( getRequestParameter( tgt ), target ); 600 } 601 602 /** 603 * 【TAG】リンク表示にタブリンクを自動で開くかどうか[true/false]を指定します(初期値:true[=開く])。 604 * 605 * @og.tag 606 * リンク表示にタブリンクを自動で開くかを指定します。 607 * openTabName属性が指定されていない場合、自動で開くタブは 608 * 「1番目に表示されたタブリンク」です。 609 * 指定されている場合は、その名前を持つ「1番目」のタブが自動で開かれます。 610 * タブが選択不可能な状態の場合は、「1番目」の条件から除外されます。 611 * 初期値は、「true(開く)」です。 612 * 613 * 7.4.1.0 (2021/04/23) 614 * openTab = false を指定すると、自動でオープンしません。 615 * 616 * @param flag 自動タブオープン [true:自動で開く/false:開かない] 617 */ 618 public void setOpenTab( final String flag ) { 619 openTab = nval( getRequestParameter( flag ), openTab ); 620 } 621 622 /** 623 * 【TAG】最初に開くタブリンクの名前を指定します。 624 * 625 * @og.tag 626 * 最初に開くタブリンクのキーを指定します。 627 * 628 * @param name 初期表示タブ名前 629 */ 630 public void setOpenTabName( final String name ) { 631 openTabName = nval( getRequestParameter( name ), openTabName ); 632 } 633 634 /** 635 * 【TAG】次画面に渡す定数パラメーターのキーを指定します。 636 * 637 * @og.tag 638 * 次画面に渡す定数パラメーターのキーを指定します。 639 * キーはCSV形式で複数指定が可能です。 640 * パラメーターの値は、constVals属性の数と一致している必要があります。 641 * 642 * @param keys 定数キー (CSV形式) 643 * @see #setConstVals( String ) 644 */ 645 public void setConstKeys( final String keys ) { 646 constKeys = getCSVParameter( keys ); 647 } 648 649 /** 650 * 【TAG】次画面に渡す定数パラメーターの値を指定します。 651 * 652 * @og.tag 653 * 次画面に渡す定数パラメーターの値を指定します。 654 * 値はCSV形式で複数指定が可能です。 655 * パラメーターの値は、constKeys属性の数と一致している必要があります。 656 * 657 * @param vals 定数値 (CSV形式) 658 * @see #setConstKeys( String ) 659 */ 660 public void setConstVals( final String vals ) { 661 constVals = getCSVParameter( vals ); 662 } 663 664 /** 665 * 【TAG】1行辺りに表示するタブの数を指定します(初期値:10)。 666 * 667 * @og.tag 668 * 1行辺りに表示するタブの数を指定します。 669 * 1行辺りのタブの数がこの設定を超えると、自動的に折り返します。 670 * また、折り返し毎に、左に10pxのマージンを設けます。 671 * 初期値は、10です。 672 * この属性は、orientationがHorizontal(水平方向)の場合のみ有効です。 673 * 674 * @param cnt 1行タブ数 675 */ 676 public void setListCount( final String cnt ) { 677 listCount = nval( getRequestParameter( cnt ), listCount ); 678 } 679 680 /** 681 * 【TAG】選択タブのクラスを指定します(初期値:selTab)。 682 * 683 * @og.tag 684 * タブが選択されている状態にある場合の、タブ部分のクラス名を指定します。 685 * このクラス名を変更する場合は、そのクラスをcustom/custom.css等で再定義して下さい。 686 * 初期値は、selTabです。 687 * 688 * @param cls 選択タブのクラス名 689 */ 690 public void setSelClass( final String cls ) { 691 selClass = nval( getRequestParameter( cls ), selClass ); 692 } 693 694 /** 695 * 【TAG】非選択タブのクラスを指定します(初期値:unselTab)。 696 * 697 * @og.tag 698 * タブが選択されていない状態にある場合の、タブ部分のクラス名を指定します。 699 * このクラス名を変更する場合は、そのクラスをcustom/custom.css等で再定義して下さい。 700 * 初期値は、unselTabです。 701 * 702 * @param cls 選択タブのクラス名 703 */ 704 public void setUnselClass( final String cls ) { 705 unselClass = nval( getRequestParameter( cls ), unselClass ); 706 } 707 708 /** 709 * 【TAG】タブの方向[Horizontal(or H):横型/Vertical(or V):縦型]を指定します(初期値:Horizontal:横型)。 710 * 711 * @og.tag 712 * タブは、上にタブが並ぶ横型と左にタブが並ぶ縦型があります。 713 * この属性では、横型は、Horizontal 、縦型は、Vertical を指定します。 714 * 指定は、文字列の最初の一文字を見ているだけですので、HかVでも構いません。 715 * 716 * 縦型(Vertical)にした場合、各タブ要素は、フレームサイズの幅に合わせて 717 * 最大で表示されます。幅を固定する場合は、width属性を指定して下さい。 718 * 719 * 初期値は、横型(Horizontal) です。 720 * 721 * @param ori タブの方向 [Horizontal(or H):横型/Vertical(or V):縦型] 722 */ 723 public void setOrientation( final String ori ) { 724 final String ori2 = nval( getRequestParameter( ori ),null ); 725 if( ori2 != null && ori2.length() > 0 ) { 726 final char ch = ori2.toUpperCase(Locale.JAPAN).charAt(0); 727 if( ch == 'H' ) { isHorizontal = true; } 728 else if( ch == 'V' ) { isHorizontal = false; } 729 else { 730 final String errMsg = "orientation の指定は、H(orizontal) または、V(ertical) です。" 731 + " orientation=" + ori2 ; // 5.1.8.0 (2010/07/01) errMsg 修正 732 throw new HybsSystemException( errMsg ); 733 } 734 } 735 } 736 737 /** 738 * 【TAG】タブリンクの幅を % 、px 、または "auto" で指定します(初期値:auto)。 739 * 740 * @og.tag 741 * 初期値は、"auto"(自動設定) です。 742 * autoの場合、横型表示では、文字の幅に合わせて自動的に調整され、 743 * 縦型表示の場合は、フレームサイズに合わせて拡大して表示されます。 744 * 745 * @param wh 幅 (% 、px 、または "auto" ) 746 */ 747 public void setWidth( final String wh ) { 748 width = nval( getRequestParameter( wh ),width ); 749 } 750 751 /** 752 * 【TAG】タブの高さを、% 、px 、または "auto" で指定します(初期値:auto)。 753 * 754 * @og.tag 755 * タブの高さを、% 、px 、または "auto" で指定します 756 * 初期値は、"auto"(自動設定) です。 757 * 758 * @param ht 高さ (% 、px 、または "auto" ) 759 */ 760 public void setHeight( final String ht ) { 761 height = nval( getRequestParameter( ht ),height ); 762 } 763 764 /** 765 * 【HTML】JavaScriptのイベント onClick を設定します(初期値::onClick="changeTab( this, 'selTab' );")。 766 * 767 * @og.tag 768 * onClick をセットします。 769 * 初期値は、選択タブをクリックしたタブの色を新しく選択されたタブの色と入れ替えます。 770 * ゼロ文字列を指定すると、onClick を何も指定しないことになります。 771 * 初期値::onClick="changeTab( this, 'selTab' );" 772 * 773 * @og.rev 7.4.1.0 (2021/04/23) タブをクリックした際のJavaScriptを外部から設定できるようにします。 774 * 775 * @param scrpt onClickイベント 776 */ 777 public void setOnClick( final String scrpt ) { 778 // ゼロ文字列を指定すると、null になります。 779 onClick = nval( getRequestParameter( scrpt ),null ); 780 } 781 782 /** 783 * シリアライズ用のカスタムシリアライズ読み込みメソッド 784 * 785 * ここでは、transient 宣言された内部変数の内、初期化が必要なフィールドのみ設定します。 786 * 787 * @og.rev 5.1.8.0 (2010/07/01) tabData の初期化処理 追加 788 * @serialData 一部のオブジェクトは、シリアライズされません。 789 * 790 * @param strm ObjectInputStreamオブジェクト 791 * @see #release2() 792 * @throws IOException シリアライズに関する入出力エラーが発生した場合 793 * @throws ClassNotFoundException クラスを見つけることができなかった場合 794 */ 795 private void readObject( final ObjectInputStream strm ) throws IOException, ClassNotFoundException { 796 strm.defaultReadObject(); 797 tabData = new ArrayList<>(); 798 } 799 800 /** 801 * このオブジェクトの文字列表現を返します。 802 * 基本的にデバッグ目的に使用します。 803 * 804 * @return このクラスの文字列表現 805 * @og.rtnNotNull 806 */ 807 @Override 808 public String toString() { 809 return ToString.title(this.getClass().getName() ) 810 .println( "VERSION" , VERSION ) 811 .println( "listType" , type.toString() ) 812 .println( "href" , href ) 813 .println( "target" , target ) 814 .println( "openTab" , openTab ) 815 .println( "openTabName" , openTabName ) 816 .println( "constKeys" , constKeys ) 817 .println( "constVals" , constVals ) 818 .println( "listCount" , listCount ) 819 .println( "selClass" , selClass ) 820 .println( "unselClass" , unselClass ) 821 .println( "isHorizontal" , isHorizontal ) 822 .println( "width" , width ) 823 .println( "height" , height ) 824 .println( "Other...", getAttributes().getAttribute() ).fixForm().toString(); 825 } 826}