    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 static org.opengion.fukurou.util.StringUtil.nval;
    019
    020import java.io.IOException;
    021import java.io.ObjectInputStream;
    022import java.io.ObjectOutputStream;
    023
    024import org.opengion.fukurou.util.Options;
    025import org.opengion.hayabusa.common.HybsSystem;
    026
    027/**
    028 * フォームの入力欄などで入力候補となるデータリストを定義するHTML拡張タグです。
    029 * HTML5 から、新たに追加された要素です。
    030 *
    031 * データリスト内の選択肢は、optionタグ、queryOptionタグによって指定します。
    032 * データリスト の id 属性は、フォームの list 属性と同じキーを指定する事で関連付けします。
    033 *
    034 * @og.formSample
    035 * ●形式：&lt;og:datalist id="…" /&gt;
    036 * ●body：あり(EVAL_BODY_INCLUDE:BODYをインクルードし、{&#064;XXXX} は解析しません)
    037 *
    038 * ●Tag定義：
    039 *   &lt;og:datalist
    040 *       id               ○【TAG】入力候補を表示するフォームの list 属性に設定する id (必須)
    041 *       caseKey            【TAG】このタグ自体を利用するかどうかの条件キーを指定します(初期値:null)
    042 *       caseVal            【TAG】このタグ自体を利用するかどうかの条件値を指定します(初期値:null)
    043 *       caseNN             【TAG】指定の値が、null/ゼロ文字列 でない場合(Not Null=NN)は、このタグは使用されます(初期値:true)
    044 *       caseNull           【TAG】指定の値が、null/ゼロ文字列 の場合は、このタグは使用されます(初期値:true)
    045 *       debug              【TAG】デバッグ情報を出力するかどうか[true/false]を指定します(初期値:false)
    046 *   &gt;   ... Body ...
    047 *   &lt;/og:datalist&gt;
    048 *
    049 * ●使用例
    050 * &lt;og:input type="text" name="tokyo" autocomplete="on" list="tokyo.sel" /&gt;
    051 *
    052 *  &lt;og:datalist id="tokyo.sel" &gt;
    053 *      &lt;og:option value="渋谷" /&gt;
    054 *      &lt;og:option value="新宿" /&gt;
    055 *      &lt;og:option value="池袋" /&gt;
    056 *  &lt;/og:datalist&gt;&lt;
    057 *
    058 * @og.group 【HTML5】選択データ制御
    059 * @og.rev 5.7.1.0 (2013/12/06) 新規追加
    060 *
    061 * @version  6.0
    062 * @author       Kazuhiko Hasegawa
    063 * @since    JDK5.0,
    064 */
    065public class DatalistTag extends CommonTagSupport implements OptionAncestorIF {
    066        //* このプログラムのVERSION文字列を設定します。   {@value} */
    067        private static final String VERSION = "5.7.6.2 (2014/05/16)" ;
    068
    069        private static final long serialVersionUID = 576220140516L ;
    070
    071        private transient Options option        = new Options();
    072
    073        private String id       = null;         // フォームと関連付けるid
    074
    075        /**
    076         * Taglibの開始タグが見つかったときに処理する doStartTag() を オーバーライドします。
    077         *
    078         * @return      後続処理の指示( EVAL_BODY_INCLUDE )
    079         */
    080        @Override
    081        public int doStartTag() {
    082                if( useTag() ) {
    083                        return EVAL_BODY_INCLUDE ;      // Body インクルード( extends TagSupport 時)
    084                }
    085                return SKIP_BODY ;                              // Body を評価しない
    086        }
    087
    088        /**
    089         * Taglibの終了タグが見つかったときに処理する doEndTag() を オーバーライドします。
    090         *
    091         * @og.rev 5.7.6.2 (2014/05/16) IEのHTML5機能が無効の場合、INDBMENU を作成します。
    092         *
    093         * @return      後続処理
    094         */
    095        @Override
    096        public int doEndTag() {
    097                debugPrint();           // 4.0.0 (2005/02/28)
    098                // 5.2.2.0 (2010/11/01) caseKey 、caseVal 属性対応
    099                if( useTag() ) {
    100                        StringBuilder rtn = new StringBuilder( HybsSystem.BUFFER_MIDDLE );
    101
    102                        // 5.7.6.2 (2014/05/16) IEのHTML5機能が無効の場合の処理
    103                        String ieHTML5 = (String)getSessionAttribute( HybsSystem.IE_HTML5_KEY );
    104                        if( "FALSE".equalsIgnoreCase( ieHTML5 ) ) {
    105                                String inName = id.endsWith( ".sel" ) ? id.substring( 0,id.length()-4 ) : id ;
    106
    107                                rtn.append("<select id='").append( id )
    108                                        .append( "' style='position:absolute;' onChange='selChanged(this);' >" )
    109                                        .append( option.getOption() )
    110                                        .append( "</select>" )
    111                                        .append( "<script type='text/javascript'>makeInputMenu('" )
    112                                        .append( inName ).append( "');</script>" );
    113                        }
    114                        else {
    115                                // display:none は、datalist の optionのBODY部が、HTML5 以外では表示されてしまうため。
    116                                rtn.append("<div style='display:none;'>" )
    117                                        .append("<datalist id='").append( id ).append( "' >" )
    118                                        .append( option.getOption() )
    119                                        .append( "</datalist>" )
    120                                        .append( "</div>" );
    121                        }
    122
    123                        jspPrint( rtn.toString() );
    124                }
    125                return EVAL_PAGE ;
    126        }
    127
    128        /**
    129         * タグリブオブジェクトをリリースします。
    130         * キャッシュされて再利用されるので、フィールドの初期設定を行います。
    131         *
    132         */
    133        @Override
    134        protected void release2() {
    135                super.release2();
    136                option  = new Options();
    137                id              = null;
    138        }
    139
    140        /**
    141         * データリストの選択項目を追加します。
    142         *
    143         * datalist タグのBODY要素の OptionTag よりアクセスされます。
    144         *
    145         * @param       opt      オプションタグ文字列
    146         */
    147        public void addOption( final String opt ) {
    148                option.add( opt );
    149        }
    150
    151        /**
    152         * 【HTML】要素に対して固有の名前(id)をつける場合に設定します。
    153         *
    154         * @og.tag
    155         * データリスト の id 属性は、フォームの list 属性と同じキーを指定する事で関連付けします。
    156         *
    157         * ※
    158         * 内部事情で、inputタグ(columnタグ)の list属性 に設定するキーも、id属性に設定するキーも、
    159         * inputタグ(columnタグ)の name属性＋".sel" を標準的に使用してください。
    160         *
    161         * @param   id 固有の名前
    162         */
    163        @Override
    164        public void setId( final String id ) {
    165                this.id = nval( getRequestParameter( id ), null );
    166        }
    167
    168        /**
    169         * 値を外部から取り出します。
    170         *
    171         * OptionTag で、value を取り出して、内部の値と同じ場合は、選択状態にします。
    172         *
    173         * @og.rev 3.5.4.0 (2003/11/25) 新規作成
    174         *
    175         * @return      内部に設定された値
    176         */
    177        public String getValue() {
    178                // ここでは、何もしません。
    179                return null;
    180        }
    181
    182        /**
    183         * 複数選択可能時に全選択を設定するかどうかを返します。
    184         *
    185         * これは、上位入れ子のタグの OptionTag で、multipleAll を取り出して、
    186         * true であれば、全選択に設定します。
    187         *
    188         * @og.rev 3.8.0.9 (2005/10/17) 新規作成
    189         *
    190         * @return      全選択:true / 通常:false
    191         */
    192        public boolean isMultipleAll() {
    193                // ここでは、何もしません。
    194                return false;
    195        }
    196
    197        /**
    198         * パラメーター変換({&#064;XXXX}の置き換えをしない状態のパラメーターをセットします。
    199         *
    200         * @og.rev 5.1.7.0 (2010/06/01) 新規作成(動的プルダウン実装見直し)
    201         * @og.rev 5.5.4.0 (2012/07/02) 予約語対応
    202         *
    203         * @param   param パラメーター
    204         */
    205        public void setRawParam( final String param ) {
    206                // ここでは、何もしません。
    207        }
    208
    209        /**
    210         * シリアライズ用のカスタムシリアライズ書き込みメソッド
    211         *
    212         * @serialData 一部のオブジェクトは、シリアライズされません。
    213         *
    214         * @param       strm    ObjectOutputStreamオブジェクト
    215         * @throws IOException  シリアライズに関する入出力エラーが発生した場合
    216         */
    217        private void writeObject( final ObjectOutputStream strm ) throws IOException {
    218                strm.defaultWriteObject();
    219        }
    220
    221        /**
    222         * シリアライズ用のカスタムシリアライズ読み込みメソッド
    223         *
    224         * ここでは、transient 宣言された内部変数の内、初期化が必要なフィールドのみ設定します。
    225         *
    226         * @serialData 一部のオブジェクトは、シリアライズされません。
    227         *
    228         * @param       strm    ObjectInputStreamオブジェクト
    229         * @see #release2()
    230         * @throws IOException  シリアライズに関する入出力エラーが発生した場合
    231         * @throws ClassNotFoundException       クラスを見つけることができなかった場合
    232         */
    233        private void readObject( final ObjectInputStream strm ) throws IOException , ClassNotFoundException {
    234                strm.defaultReadObject();
    235                option = new Options();
    236        }
    237
    238        /**
    239         * このオブジェクトの文字列表現を返します。
    240         * 基本的にデバッグ目的に使用します。
    241         *
    242         * @return このクラスの文字列表現
    243         */
    244        @Override
    245        public String toString() {
    246                return org.opengion.fukurou.util.ToString.title( this.getClass().getName() )
    247                                .println( "VERSION"             ,VERSION                )
    248                                .println( "id"                  ,id                             )
    249                                .println( "Other..."    ,getAttributes().getAttribute() )
    250                                .fixForm().toString() ;
    251        }
    252}