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 java.util.ArrayList;
019import java.util.List;
020import java.util.Set;                                                                                                                   // 6.4.3.4 (2016/03/11)
021import java.util.Iterator;                                                                                                              // 6.7.7.0 (2017/03/31)
022import java.util.function.IntFunction;                                                                                  // 7.0.1.3 (2018/11/12)
023
024// import org.opengion.fukurou.system.BuildNumber;                                                              // 7.0.1.2 (2018/11/04)
025import org.opengion.hayabusa.common.HybsSystem;
026import org.opengion.hayabusa.common.HybsSystemException;
027import org.opengion.hayabusa.db.DBTableModelSorter;
028import org.opengion.hayabusa.db.DBTableModel;
029import org.opengion.hayabusa.db.DBColumn;                                                                               // 6.8.3.1 (2017/12/01)
030import org.opengion.hayabusa.io.JsChartData;                                                                    // 7.0.1.1 (2018/10/22)
031
032import org.opengion.fukurou.util.ArraySet;                                                                              // 6.4.3.4 (2016/03/11)
033import org.opengion.fukurou.util.ToString;
034import org.opengion.fukurou.util.StringUtil;                                                                    // 6.8.3.1 (2017/12/01)
035import org.opengion.fukurou.util.ColorMap;                                                                              // 7.0.1.3 (2018/11/12)
036import static org.opengion.fukurou.util.StringUtil.nval;
037
038/**
039 * JsChart は、JavascriptのjsChart用のスクリプトを出力するクラスです。
040 * 複数の JsChartData オブジェクトを合成することも、ここで行っています。
041 * ChartJSのVer3を利用しているため、標準属性以外の項目をセットする場合はoptionAttributesで行ってください。
042 *
043 * 出力されるスクリプトでは、idを指定しない場合はhybscanvas[tableId]が利用されます。
044 * 複数のグラフを同一画面で出力する場合はidかtableIdを変えてください。
045 * チャートオブジェクトはchart_[id]という名前で作成されるため、ajax等でコントロールが必要な場合は利用してください。
046 *
047 * <a href="https://www.tohoho-web.com/ex/chartjs-params.html" target="_blank" >とほほのChart.js入門</a>
048 *
049 * ChartのGlobal Configurationとして、Chart.defaults.**** が指定できる。これは本タグでは
050 * 用意していないが、グローバルなので、タグの前に個別に記述しておくことで適用される。
051 *
052 * <a href="https://www.chartjs.org/docs/latest/configuration/" target="_blank" >Configuration</a>
053 *
054 * @og.formSample
055 * ●形式:&lt;og:jsChart chartType="…" ... /&gt;
056 * ●body:あり(EVAL_BODY_BUFFERED:BODYを評価し、{$#064;XXXX} を解析します)
057 *
058 * ●Tag定義:
059 *  &lt;og:jsChart
060 *      chartType       ○【TAG】チャートの種類(type属性)を指定します[line/bar/radar/polarArea/pie/doughnut/bubble/scatter](必須)
061 *                                  horizontalBar 廃止 → indexAxis="y" 指定verticalLine 相当の表示も indexAxis="y" 指定
062 *      labelColumn     ○【TAG】ラベルのカラム名(data:labels属性)を指定します(表示名称) (必須)
063 *      id                【TAG】canvasタグのidを指定します (初期値:hybscanvas)
064 *      height            【TAG】チャート(canvasタグ)の高さを指定します (初期値:400px)
065 *      width             【TAG】チャート(canvasタグ)の幅を指定します (初期値:400px)
066 *      minLabelWidth     【TAG】ラベルのカラム(データの枠)の最小幅を指定します 8.3.1.0 (2022/10/14)
067 *      plugins           【TAG】プラグイン定義された関数を指定します(plugins) 6.9.9.2 (2018/09/18)
068 *  =================== options: 以下の属性
069 * (V3) indexAxis         【TAG】"y" を指定することで、horizontalBar や verticalLine を実現する(options:indexAxis)       8.0.0.0 (2021/08/31) 新規追加
070 *      barWidthPer       【TAG】棒線の横幅を指定します (初期値:0.8, typeがbar の場合に有効)(option:categoryPercentage)
071 *      animation         【TAG】簡易的にアニメーションのON/OFFを設定(true/false)します (初期値:null=true)(options:animation)
072 *      onClick           【TAG】チャートクリック時のイベントを指定します(options:onClick)
073 *      optOptions        【TAG】optionsの要素に、その他オプションを追加します
074 *  =================== options:scales:x: 以下の属性
075 *      xscaleType        【TAG】x軸のスケールタイプ[category/linear/time/realtime]を指定します(type[初期値:category])
076 *      xposition         【TAG】x軸の表示位置[top/right/bottom/left]を指定します (初期値:bottom)(position)
077 *      xmax              【TAG】x軸の最大値を指定します(xscaleTypeがlinearの場合に有効)(max)
078 *      xmin              【TAG】x軸の最小値を指定します(xscaleTypeがlinearの場合に有効)(min)
079 *      xlabel            【TAG】x軸のラベルを指定します(title:text)
080 *      xscaleCallback    【TAG】x軸コールバックを指定します(ticks:callback)
081 *      xbeginAtZero      【TAG】x軸を0から書き始まるかどうか(xscaleTypeがlinearの場合に有効) (beginAtZero[初期値:null(=false)])
082 *      xstepSize         【TAG】x軸のメモリ幅を指定します(xscaleTypeがlinearの場合に有効)(ticks:stepSize)
083 *      useVertStrm       【TAG】streamingの垂直スクロールを使用するかどうか[true/false]を指定します (初期値=false)(options:scales) 8.4.0.0 (2023/01/27) Add
084 *      optAxis           【TAG】その他options:scales:x のオプションを追加します
085 *      optTicks          【TAG】その他options:scales:x:ticksのオプションを追加します
086 * (V3) optTitle          【TAG】その他options:scales:x:titleのオプションを追加します 8.0.0.0 (2021/08/31) 新規追加
087 * (V3) optGrid           【TAG】その他options:scales:x:gridのオプションを追加します 8.0.0.0 (2021/08/31) 新規追加
088 *  =================== options:scales:x:time: 以下の属性(xscaleTypeがtimeの場合に有効)
089 *      timeUnit          【TAG】x軸のタイムの単位[year/quarter/month/week/day/hour/minute/second/millisecond]を指定(unit)します(指定しない場合は自動)
090 *      timeUnitStepSize  【TAG】x軸のタイムの単位幅を指定します(stepSize)
091 * (V3) timeParser        【TAG】x軸の設定するタイム(入力データ)のフォーマットを指定します ・・・ 廃止 → time.parser になったが使い方不明  8.0.0.0 (2021/08/31) 新規追加
092 *      timeLblFormat     【TAG】x軸の表示するタイムのフォーマットを指定します(time:displayFormats:year~secondまで同じ値を設定) → displayFormats
093 *      tooltipFormat     【TAG】時間のツールチップに使用するフォーマット(tooltipFormat)
094 *  =================== options:plugins: 以下の属性
095 *      title             【TAG】タイトル、またはタイトル要素を指定します(title:text)
096 *      titlePosition     【TAG】タイトルの表示位置[top/right/bottom/left]を指定します(title:position:初期値 top)
097 *      legendDisplay     【TAG】凡例を表示するか[true/false]を指定します(legend:display)
098 *      legendPosition    【TAG】凡例の表示位置[top/right/bottom/left]を指定します(legend:position)
099 *      usePointStyle     【TAG】凡例のスタイル属性を使用するかどうか[true/false]を指定します(legend:labels:usePointStyle)
100 * (V3) optPlugins        【TAG】options:pluginsの要素に、その他オプションを追加します
101 * (V3) optTooltip        【TAG】options:plugins:tooltip の要素に、その他オプションを追加します
102 * (V3) optLegend         【TAG】options:plugins:legend の要素に、その他オプションを追加します
103 *  =================== options:plugins:annotation:annotations:(CSVで指定した分のline0): 以下の属性
104 *      markValues        【TAG】y軸に横マーカーラインの設定値をCSV形式で複数指定します(yMin:値,yMax:値)
105 *      markColors        【TAG】y軸に横マーカーラインの色をCSV形式で複数指定します(borderColor)
106 *      markLbls          【TAG】y軸に横マーカーラインのラベルをCSV形式で複数指定します(未指定時はラベルを表示しません)(label:content)
107 *      markAdjust        【TAG】y軸に横マーカーラインのラベル表示位置の上(-)下(+)方向を調整します(yAdjust:初期値 -6)
108 *      xmarkLbls         【TAG】x軸に横マーカーラインのラベルをCSV形式で複数指定します(未指定時はラベルを表示しません)(label:content)
109 *      xmarkValues       【TAG】x軸に縦マーカーラインの設定値をCSV形式で複数指定します(xMin:値,xMax:値)
110 *      xmarkColors       【TAG】x軸に縦マーカーラインの色をCSV形式で複数指定します 7.0.1.1 (2018/10/22)
111 *      markWidth         【TAG】x軸,y軸全マーカーライン共通のラインの幅を指定します(borderWidth:初期値 2) 7.0.1.1 (2018/10/22)
112 *      markDash          【TAG】x軸,y軸全マーカーライン共通のラインに点線を指定([5,2]など)します:(borderDash:初期値 null) 7.0.1.1 (2018/10/22)
113 *      markFontSize      【TAG】x軸,y軸全マーカーライン共通のラベルのフォントサイズを指定します:(label:font:size:初期値 10)
114 *  =================== options:plugins:zoom: 以下の属性
115 *      useZoom           【TAG】WheelZoom処理を使用するかどうか[true/false]を指定します(options:plugins:zoom:zoom:)
116 *      useDragZoom       【TAG】DragZoom処理を使用するかどうか[true/false]を指定します(options:plugins:zoom:zoom:)
117 *  ===================
118 *      useZeroDataOmit   【TAG】データが0の場合、使用しない(除外する)かどうかを指定します[true:0データを除外する] (初期値:false)
119 *      useRenderer       【TAG】データ出力でレンデラを利用するかどうか[true/false]を指定します (初期値:false)
120 *      sortColumn        【TAG】検索結果をこのカラムでソートしなおします (初期値:null)
121 *      valueQuot         【TAG】値の前後にクオートをはさむかどうか[true/false]指定します
122 *      varColumns        【TAG】TableModelの指定のカラムをconstの配列変数として出力します 7.0.1.2 (2018/11/04)
123 *  ===================
124 *      optChart          【廃止】chartの属性に、TLDで未定義の属性を追加します                8.0.0.0 (2021/08/31) 廃止(代替えはありません)
125 *      optScaleLabel     【廃止】optTitle を使用してください(旧 scaleLabel)          8.0.0.0 (2021/08/31) 廃止
126 *      optGridLines      【廃止】optGrid を使用してください(旧 gridLines)                    8.0.0.0 (2021/08/31) 廃止
127 *      timeMax           【廃止】廃止 → xmaxを使用してください                                        8.0.0.0 (2021/08/31) 廃止
128 *      timeMin           【廃止】廃止 → xminを使用してください                                        8.0.0.0 (2021/08/31) 廃止
129 *      timeSetFormat     【廃止】廃止 → timeParserを使用してください                          8.0.0.0 (2021/08/31) 廃止
130 *  ===================
131 *      tableId           【TAG】(通常は使いません)sessionから所得する DBTableModelオブジェクトの ID
132 *      scope             【TAG】キャッシュする場合のスコープ[request/page/session/application]を指定します (初期値:session)
133 *      caseKey           【TAG】このタグ自体を利用するかどうかの条件キーを指定します (初期値:null)
134 *      caseVal           【TAG】このタグ自体を利用するかどうかの条件値を指定します (初期値:null)
135 *      caseNN            【TAG】指定の値が、null/ゼロ文字列 でない場合(Not Null=NN)は、このタグは使用されます (初期値:判定しない)
136 *      caseNull          【TAG】指定の値が、null/ゼロ文字列 の場合は、このタグは使用されます (初期値:判定しない)
137 *      caseIf            【TAG】指定の値が、true/TRUE文字列の場合は、このタグは使用されます (初期値:判定しない)
138 *      debug             【TAG】デバッグ情報を出力するかどうか[true/false]を指定します (初期値:false)
139 *  &gt;   ... Body ...
140 *  &lt;/og:jsChart&gt;
141 *
142 * ●使用例
143 *      &lt;og:jsChart
144 *          chartType      = "[line/bar/radar/polarArea/pie/doughnut/bubble/scatter]"
145 *          labelColumn    = "LDATA"
146 *          id             = "hybscanvas"
147 *          height         = "400px"
148 *          width          = "400px"
149 *          title          = "タイトル" または "{display:true,text:'タイトル',color:'blue',font:{size:15},}" 形式
150 *          titlePosition  = "top"                              [top/right/bottom/left]
151 *          xlabel         = "名称"
152 *          legendPosition = "right"                    [top/right/bottom/left]
153 *          legendDisplay  = "true"                             [true/false]
154 *          xsclaeCallback = "function(value){return value + ' 様';}"
155 *          xscaleType     = "linear"
156 *          xmax           = "1000000"
157 *          xmin           = "100000"
158 *          xstepSize      = "10000"
159 *          barWidthPer    = "0.4"
160 *      &gt;
161 *          &lt;og:jsChartData ... /&gt;
162 *      &lt;/og:jsChart&gt;
163 *
164 * @og.rev 8.0.0.0 (2021/08/31) Ver3対応 大幅見直し
165 * @og.group 画面表示
166 *
167 * @version     8.0
168 * @author      Kazuhiko Hasegawa
169 * @since       JDK11.0
170 */
171public class JsChartTag extends CommonTagSupport {
172        /** このプログラムのVERSION文字列を設定します。{@value} */
173        private static final String VERSION = "8.3.1.0 (2022/10/14)" ;
174        private static final long serialVersionUID = 831020221014L ;
175
176        private static final String IE_CHECK
177                        = "<script>{"
178                                + "let userAgent = window.navigator.userAgent.toLowerCase();"                   + CR
179                                + "if(userAgent.indexOf('msie') != -1 ||"                                                               + CR
180                                + "   userAgent.indexOf('trident') != -1 ) {"                                                   + CR
181                                + "    document.write('Internet Explorer では表示できません<br />');"    + CR
182                                + "}}</script>"                                                                                                                 + CR ;
183
184        /** chartType 引数に渡す事の出来る タイプ 折れ線 {@value} */
185        public static final String              CTYPE_LINE                      = "line";
186        /** chartType 引数に渡す事の出来る タイプ 棒線 {@value} */
187        public static final String              CTYPE_BAR                       = "bar";
188//      /** chartType 引数に渡す事の出来る タイプ 横棒線 {@value} */
189//      public static final String              CTYPE_HBAR                      = "horizontalBar";
190        /** chartType 引数に渡す事の出来る タイプ レイダー {@value} */
191        public static final String              CTYPE_RADAR                     = "radar";
192        /** chartType 引数に渡す事の出来る タイプ ポーラエリア {@value} */
193        public static final String              CTYPE_POLAR                     = "polarArea";
194        /** chartType 引数に渡す事の出来る タイプ 円 {@value} */
195        public static final String              CTYPE_PIE                       = "pie";
196        /** chartType 引数に渡す事の出来る タイプ ドーナツ {@value} */
197        public static final String              CTYPE_DOUGHNUT          = "doughnut";
198        /** chartType 引数に渡す事の出来る タイプ バブル {@value} 8.0.0.0 (2021/08/20) 追加 */
199        public static final String              CTYPE_BUBBLE                    = "bubble";
200        /** chartType 引数に渡す事の出来る タイプ 散乱図 {@value} 8.0.0.0 (2021/08/20) 追加 */
201        public static final String              CTYPE_SCATTER           = "scatter";
202
203        /** chartType 引数に渡す事の出来る タイプ リスト {@value} */
204        private static final Set<String> CTYPE_SET
205                = new ArraySet<>( CTYPE_LINE,CTYPE_BAR,CTYPE_RADAR,CTYPE_POLAR,
206                                                        CTYPE_PIE,CTYPE_DOUGHNUT,CTYPE_BUBBLE,CTYPE_SCATTER );
207
208        // 6.9.9.4 (2018/10/01) String配列から、Set に変更
209        /** chartType が円形のリスト */
210        private static final Set<String> SET_CI_TYPE    = new ArraySet<>( CTYPE_RADAR, CTYPE_POLAR, CTYPE_PIE, CTYPE_DOUGHNUT );
211
212        private static final String TYPE_CATEGORY               = "category";
213        private static final String TYPE_LINEAR                 = "linear";
214        private static final String TYPE_TIME                   = "time";
215        private static final String TYPE_REALTIME               = "realtime";           // 7.0.1.2 (2018/11/04)
216
217        private static final Set<String> SET_POSITION   = new ArraySet<>("top","right","bottom","left");
218        private static final Set<String> SET_TIMEUNIT   = new ArraySet<>("year","quarter","month","week","day","hour","minute","second","millisecond"); // 8.0.0.0 (2021/08/31)
219        private static final Set<String> SET_XSCALE             = new ArraySet<>( TYPE_CATEGORY, TYPE_TIME, TYPE_LINEAR, TYPE_REALTIME );
220        private static final Set<String> SET_BOOLEAN    = new ArraySet<>( "true", "false" );
221
222        private static final String             CANVAS_NAME             = "hybscanvas";
223
224        private static final String             MARK_DEF_ADJUST = "-6";                 // 6.8.5.0 (2018/01/09) y軸に横マーカーラインの位置調整の初期値
225
226        // 7.0.1.3 (2018/11/12) バッファキー検索処理追加
227        // 8.0.0.0 (2021/08/31) Moment.js の依存関係が切れ、openGionV8では、date-fns を使用します。
228        private static final String             TIME_FORMAT_JA  = "{year:'yyyy年',quarter:'yyyy年M月',month:'yyyy年M月',week:'M月d日',day:'M月d日',hour:'d日 h時',minute:'h時m分',second:'m分s秒'}" ;
229        private static final String             TIME_FORMAT             = "{year:'yyyy',quarter:'yyyy/M',month:'yyyy/M',week:'M/d',day:'M/d',hour:'d HH',minute:'HH:mm',second:'HH:mm:ss'}" ;
230
231        // 7.0.1.3 (2018/11/12) true/false なので、記号化します。
232        private static final boolean    USE_QUOTE               = false;
233        private static final boolean    NO_QUOTE                = true;         // IS_NUMBER か、!USE_QUOTE か、
234
235        // JSON形式をそれなりに成形するためのタブと改行
236        private static final String[]   CR_TAB = new String[10] ;
237        static {
238                final StringBuilder tabs = new StringBuilder().append( CR );
239                for( int i=0; i<CR_TAB.length; i++ ) {
240                        CR_TAB[i] = tabs.toString();
241                        tabs.append( '\t' );
242                }
243        }
244
245        private static final String WHEEL_ZOOM = "zoom:{zoom:{mode:'xy',wheel:{enabled:true,},pinch:{enabled:true,},},pan:{mode:'xy',enabled:true,},}," ;
246        private static final String DRAG_ZOOM  = "zoom:{zoom:{drag:{enabled:true,borderColor:'rgb(54,162,235)',borderWidth:1,backgroundColor:'rgba(54,162,235,0.3)',},},pan:{mode:'xy',enabled:true,modifierKey:'ctrl',},},";
247
248        // 変数宣言
249        // 6.9.8.0 (2018/05/28) FindBugs:直列化可能クラスの非 transient で非直列化可能なインスタンスフィールド
250        private final transient List<JsChartData>       jsChartData = new ArrayList<JsChartData>() ;    // 6.7.5.0 (2017/03/10) jsChartDataのリスト
251
252        private transient       JsChartData jsXAxis = new JsChartData();        // xAxes の設定用(datasetは使いません)
253
254        /** チャートタグのBODY部分に書かれた文字列 */
255        private String  chartBody                       ;
256
257        /** チャートタイプ */
258        private String  chartType                       ;
259        /** ラベルカラム */
260        private String  labelColumn                     ;
261        /** canvasタグのid */
262        private String  id                                      ;
263        /** canvasタグのheight */
264        private String  height                          = "400px";
265        /** canvasタグのwidth */
266        private String  width                           = "400px";
267        /** ラベルのカラムの最小幅 */
268        private String  minLabelWidth           ;                                                       // 8.3.1.0 (2022/10/14)
269        /** プラグイン定義された関数を指定 */
270        private String  plugins                         ;                                                       // 6.9.9.2 (2018/09/18)
271        // =================== options: 以下の属性
272        /** horizontalBarや、verticalLine を実現 */
273        private String  indexAxis                       ;                                                       // 8.0.0.0 (2021/08/31)
274        /** 棒線の横幅(パーセント) */
275        private String  barWidthPer                     = "0.8";
276        /** 簡易的なアニメーションのON/OFF */
277        private String  animation                       ;
278        /** クリックイベント */
279        private String  onClick                         ;
280        /** optionsの属性に、その他オプションを追加 */
281        private String  optOptions                      ;                                                       // 7.0.1.2 (2018/11/04)
282        // =================== options:scales:x: 以下の属性
283        /** x軸のスケールタイプ */
284        private String  xscaleType                      = TYPE_CATEGORY;
285        /** x軸の表示位置 */
286        private String  xposition                       ;                                                       // top/right/bottom/left 7.0.1.2 (2018/11/04)
287        /** streamingの垂直スクロール使用有無 */
288        private boolean useVertStrm                     ;                                                       // 初期値:false 8.4.0.0 (2023/01/27)
289        // =================== options:plugins: 以下の属性
290        /** タイトル */
291        private String  title                           ;
292        /** タイトル位置 */
293        private String  titlePosition           = "top";
294        /** 凡例表示フラグ */
295        private String  legendDisplay           ;
296        /** 凡例位置 */
297        private String  legendPosition          ;
298        /** 点のスタイル属性の使用有無 */
299        private boolean usePointStyle           ;                                                       // 初期値:false 6.8.5.0 (2018/01/09)
300        /** options:pluginsの属性に、その他オプションを追加 */
301        private String  optPlugins                      ;                                                       // 8.0.0.0 (2021/09/30)
302        /** options:plugins:tooltip の属性に、その他オプションを追加 */
303        private String  optTooltip                      ;                                                       // 8.0.0.0 (2021/09/30)
304        /** options:plugins:legend の属性に、その他オプションを追加 */
305        private String  optLegend                       ;                                                       // 8.0.0.0 (2021/09/30)
306        // =================== options:plugins:annotation:annotations: 以下の属性
307        /** y軸に横マーカーラインの設定値をCSV形式で複数指定 */
308        private String  markValues                      ;                                                       // 6.8.5.0 (2018/01/09)
309        /** y軸に横マーカーラインの色をCSV形式で複数指定 */
310        private String  markColors                      ;                                                       // 6.8.5.0 (2018/01/09)
311        /** y軸に横マーカーラインのラベルをCSV形式で複数指定 */
312        private String  markLbls                        ;                                                       // 6.8.5.0 (2018/01/09) 未指定時はラベルを表示しません
313        /** y軸に横マーカーラインのラベル表示位置の上下方向を調整 */
314        private String  markAdjust                      ;                                                       // 初期値:-6 6.8.5.0 (2018/01/09)
315        /** x軸に横マーカーラインのラベルをCSV形式で複数指定 */
316        private String  xmarkLbls                       ;                                                       // 8.0.0.0 (2021/09/30)
317        /** x軸に縦マーカーラインの設定値をCSV形式で複数指定 */
318        private String  xmarkValues                     ;                                                       // 7.0.1.1 (2018/10/22)
319        /** x軸に縦マーカーラインの色をCSV形式で複数指定 */
320        private String  xmarkColors                     ;                                                       // 7.0.1.1 (2018/10/22)
321        /** マーカーライン共通のラインの幅:borderWidth(初期値:2) */
322        private String  markWidth                       = "2";                                          // 7.0.1.1 (2018/10/22)
323        /** マーカーライン共通のラインに点線を指定([5,2]など) */
324        private String  markDash                        ;                                                       // :borderDash(初期値:null) 7.0.1.1 (2018/10/22)
325        /** マーカーライン共通のラベルのフォントサイズ:fontSize(初期値:10) */
326        private String  markFontSize            = "10";                                         // 7.0.1.1 (2018/10/22)
327        // =================== options:plugins:zoom: 以下の属性
328        /** Wheelズーム処理の使用有無 */
329        private boolean useZoom                         ;                                                       // 初期値:false 6.8.5.0 (2018/01/09)
330        /** Dragズーム処理の使用有無 */
331        private boolean useDragZoom                     ;                                                       // 初期値:false 6.8.5.0 (2018/01/09)
332        // ===================
333        /** データが0の場合、使用しない(除外する)かどうか */
334        private boolean useZeroDataOmit         ;                                                       // 6.7.7.0 (2017/03/31)
335        /** データ出力でレンデラを利用するかどうか */
336        private boolean useRenderer                     ;                                                       // 6.7.9.0 (2017/04/28)
337        /** 検索結果をこのカラムでソートし直し */
338        private String  sortColumn                      ;                                                       // 初期値:null 6.8.0.0 (2017/06/02)
339        /** 値の前後にクオートをはさむかどうか[true/false] */
340        private boolean valueQuot                       ;
341        /** TableModelの指定のカラムをconstの配列変数として出力 */
342        private String  varColumns                      ;                                                       // 7.0.1.2 (2018/11/04)
343        // ===================
344        /** テーブルid */
345        private String  tableId                         = HybsSystem.TBL_MDL_KEY;
346
347        /** Legend関連属性 */
348        private boolean useLegend                       ;                                                       // legendPosition,legendDisplay,usePointStyle のどれかがセットされれば、true
349//      / *      useVarCheck       【TAG】const定義するJavaScript変数に使用できるかどうか[true/false]指定します
350//      private boolean useVarCheck                     ;                                                       // 8.0.0.0 (2021/09/30) JavaScript変数に使用できるかどうか[true/false]指定します
351//      private String  optChart                        ;                                                       // 7.0.1.2 (2018/11/04) chartの属性に、TLDで未定義の属性を追加指定します
352
353//      private List<String> options = new ArrayList<>() ;                              // 8.0.0.0 (2021/08/31) optionsの属性に、オプションを追加設定します
354
355        /**
356         * デフォルトコンストラクター
357         *
358         * @og.rev 6.9.7.0 (2018/05/14) PMD Each class should declare at least one constructor
359         */
360        public JsChartTag() { super(); }                // これも、自動的に呼ばれるが、空のメソッドを作成すると警告されるので、明示的にしておきます。
361
362        /**
363         * タグリブオブジェクトをリリースします。
364         * キャッシュされて再利用されるので、フィールドの初期設定を行います。
365         *
366         * @og.rev 6.7.5.0 (2017/03/10) jsChartData属性の初期化もれ
367         * @og.rev 5.9.19.0 (2017/04/07) T.OTA 61200-170316-02  チャートサイズ・max・minの動的変更対応
368         * @og.rev 6.7.7.0 (2017/03/31) useZeroDataOmit属性の追加
369         * @og.rev 6.7.9.0 (2017/04/28) useRenderer 追加
370         * @og.rev 6.8.0.0 (2017/06/02) sortColumn 追加
371         * @og.rev 6.8.3.0 (2017/11/27) useEqValOmit属性の追加
372         * @og.rev 6.8.5.0 (2018/01/09) xbeginAtZero,ybeginAtZero,markValues,markColors,markLbls,markAdjust,rangeMin,rangeMax,usePointStyle属性の追加
373         * @og.rev 6.9.9.2 (2018/09/18) plugins,chartAttributes属性の追加
374         * @og.rev 6.9.9.3 (2018/09/25) xscaleType の time 属性廃止
375         * @og.rev 6.9.9.4 (2018/10/01) リニア対応,time 属性復活
376         * @og.rev 6.9.9.4 (2018/10/01) 7.0.1.0 (2018/10/15) time 属性修正、tooltipFormat属性の追加
377         * @og.rev 7.0.1.1 (2018/10/22) xmarkValues,xmarkColors属性の追加
378         * @og.rev 7.0.1.1 (2018/10/22) ylabelColor,y2label,y2labelColor属性の追加
379         * @og.rev 7.0.1.2 (2018/11/04) ylabelColor,y2label,y2labelColor属性の追加
380         * @og.rev 8.0.0.0 (2021/08/31) horizontalBar 廃止 → indexAxis="y" 指定
381         * @og.rev 8.3.1.0 (2022/10/14) ラベルのカラムの最小幅対応(minLabelWidth 属性追加)(問合・トラブル 0200009388)
382         * @og.rev 8.4.0.0 (2023/01/27) useVertStrm属性追加(chartjs-plugin-streamingのVertical Scroll不具合対応)
383         */
384        @Override
385        protected void release2() {
386                super.release2();
387                jsChartData.clear();                                                    // 6.7.5.0 (2017/03/10)
388                jsXAxis                         = new JsChartData();            // xAxes の設定用(datasetは使いません)
389
390                chartBody                       = null;                                         // 7.0.1.1 (2018/10/22) チャートタグのBODY部分に書かれた文字列
391                chartType                       = null;
392                labelColumn                     = null;
393                id                                      = null;
394                height                          = "400px";
395                width                           = "400px";
396                minLabelWidth           = null;                                         // 8.3.1.0 (2022/10/14) ラベルのカラムの最小幅
397                plugins                         = null;                                         // 6.9.9.2 (2018/09/18) プラグイン定義された関数を指定します
398                // =================== options: 以下の属性
399                indexAxis                       = null;                                         // 8.0.0.0 (2021/08/31)
400                barWidthPer                     = "0.8";
401                animation                       = null;                                         // 8.0.0.0 (2021/08/31) 簡易的なアニメーションのON/OFF
402                onClick                         = null;
403                optOptions                      = null;                                         // 7.0.1.2 (2018/11/04) optionsの属性に、その他オプションを追加指定します
404                // =================== options:scales:x: 以下の属性
405                xscaleType                      = TYPE_CATEGORY;
406                xposition                       = null;                                         // 7.0.1.2 (2018/11/04) x軸の表示位置[top/right/bottom/left]
407                useVertStrm                     = false;                                        // streamingの垂直スクロール使用有無 (初期値:false) 8.4.0.0 (2023/01/27)
408                // =================== options:plugins: 以下の属性
409                title                           = null;
410                titlePosition           = "top";
411                legendDisplay           = null;
412                legendPosition          = null;
413                usePointStyle           = false;                                        // 6.8.5.0 (2018/01/09) 点のスタイル属性を使用するかどうか
414                optPlugins                      = null;                                         // 8.0.0.0 (2021/09/30) options:pluginsの属性に、その他オプションを追加します
415                optTooltip                      = null;                                         // 8.0.0.0 (2021/09/30) options:plugins:tooltip の属性に、その他オプションを追加します
416                optLegend                       = null;                                         // 8.0.0.0 (2021/09/30) options:plugins:legend の属性に、その他オプションを追加します
417                // =================== options:plugins:annotation:annotations: 以下の属性
418                markValues                      = null;                                         // 6.8.5.0 (2018/01/09) y軸に横マーカーラインの設定値をCSV形式で複数指定します
419                markColors                      = null;                                         // 6.8.5.0 (2018/01/09) y軸に横マーカーラインの色をCSV形式で複数指定します
420                markLbls                        = null;                                         // 6.8.5.0 (2018/01/09) y軸に横マーカーラインのラベルをCSV形式で複数指定します(未指定時はラベルを表示しません)
421                markAdjust                      = null;                                         // 6.8.5.0 (2018/01/09) y軸に横マーカーラインのラベル表示位置の上下方向を調整します (初期値:-6)
422                xmarkLbls                       = null;                                         // 8.0.0.0 (2021/09/30) x軸に横マーカーラインのラベルをCSV形式で複数指定
423                xmarkValues                     = null;                                         // 7.0.1.1 (2018/10/22) x軸に縦マーカーラインの設定値をCSV形式で複数指定します
424                xmarkColors                     = null;                                         // 7.0.1.1 (2018/10/22) x軸に縦マーカーラインの色をCSV形式で複数指定します
425                markWidth                       = "2";                                          // 7.0.1.1 (2018/10/22) マーカーライン共通のラインの幅を指定します:borderWidth(初期値:2)
426                markDash                        = null;                                         // 7.0.1.1 (2018/10/22) マーカーライン共通のラインに点線を指定([5,2]など)します:borderDash(初期値:null)
427                markFontSize            = "10";                                         // 7.0.1.1 (2018/10/22) マーカーライン共通のラベルのフォントサイズを指定します:fontSize(初期値:10)
428                // =================== options:plugins:zoom: 以下の属性
429                useZoom                         = false;                                        // 6.8.5.0 (2018/01/09) ズーム処理を使用するかどうか (初期値:false)
430                useDragZoom                     = false;                                        // 6.8.5.0 (2018/01/09) ズーム処理を使用するかどうか (初期値:false)
431                // ===================
432                useZeroDataOmit         = false;                                        // 6.7.7.0 (2017/03/31) データが0の場合、使用しない(除外する)かどうか
433                useRenderer                     = false;                                        // 6.7.9.0 (2017/04/28) useRenderer 追加
434                sortColumn                      = null;                                         // 6.8.0.0 (2017/06/02) 検索結果をこのカラムでソートしなおします (初期値:null)
435                valueQuot                       = false;                                        // 7.0.1.1 (2018/10/22) 値の前後にクオートをはさむかどうか[true/false]指定します
436                varColumns                      = null;                                         // 7.0.1.2 (2018/11/04) TableModelの指定のカラムをconstの配列変数として出力します
437                // ===================
438                tableId                         = HybsSystem.TBL_MDL_KEY;
439
440                useLegend                       = false;                                        // 7.0.1.1 (2018/10/22) Legend関連属性(legendPosition,legendDisplay,usePointStyle) のどれかがセットされれば、true
441//              useVarCheck                     = false;                                        // 8.0.0.0 (2021/09/30) JavaScript変数に使用できるかどうか[true/false]指定します
442//              optChart                        = null;                                         // 7.0.1.2 (2018/11/04) chartの属性に、TLDで未定義の属性を追加指定します
443        }
444
445        /**
446         * Taglibの開始タグが見つかった時に処理する doStartTag() を オーバーライドします。
447         *
448         * @og.rev 6.7.5.0 (2017/03/10) タグの使用を決める共通属性の追加
449         *
450         * @return      後続処理の指示
451         */
452        @Override
453        public int doStartTag() {
454                if( !useTag() ) { return SKIP_BODY ; }                                                                  // 6.7.5.0 (2017/03/10)
455
456                return EVAL_BODY_BUFFERED;                                                                                              // Bodyを評価する
457        }
458
459        /**
460         * Taglibのタグ本体を処理する doAfterBody() を オーバーライドします。
461         *
462         * @og.rev 7.0.1.1 (2018/10/22) このスクリプトの中に入れたい文字があれば、登録できるようにします。
463         *
464         * @return      後続処理の指示(SKIP_BODY)
465         */
466        @Override
467        public int doAfterBody() {
468                chartBody = getBodyString();
469
470                if( chartBody != null ) {
471                        chartBody = chartBody.trim();
472                }
473
474                return SKIP_BODY ;
475        }
476
477        /**
478         * Taglibの終了タグが見つかったときに処理する doEndTag() を オーバーライドします。
479         *
480         * @og.rev 6.7.5.0 (2017/03/10) タグの使用を決める共通属性の追加
481         * @og.rev 6.9.9.4 (2018/10/01) idの振り方、データの持ち方変更
482         * @og.rev 8.0.0.0 (2021/08/31) エラーメッセージを画面に返します。
483         *
484         * @return      後続処理の指示
485         */
486        @Override
487        public int doEndTag() {
488                debugPrint();
489                if( !useTag() ) { return EVAL_PAGE ; }                  // 6.7.5.0 (2017/03/10)
490
491                id = (id==null ? tableId : id );                                // 6.9.9.4 (2018/10/01) id指定なしの場合はtableId
492
493                // jsChart出力
494                jspPrint( jsChartOutput() );
495
496                // 8.0.0.0 (2021/08/31) エラーメッセージを画面に表示する。
497                final StringBuilder errBuf = new StringBuilder( BUFFER_MIDDLE );
498                final String axisErr = jsXAxis.getErrorMessage();
499                if( !axisErr.isEmpty() ) {
500                        errBuf.append( "X軸の設定でエラーがあります" ).append( CR )
501                                        .append( axisErr ).append( CR );
502                }
503
504                // jsChartDataタグの変数宣言
505                for( int i=0; i<jsChartData.size(); i++ ) {
506                        final String dataErr = jsChartData.get(i).getErrorMessage();
507                        if( !dataErr.isEmpty() ) {
508                                errBuf.append( "Y軸[" ).append( i ) .append( "]の設定でエラーがあります" ).append( CR )
509                                                .append( dataErr ).append( CR );
510                        }
511                }
512
513                if( errBuf.length() > 0 ) {                             // 一応、設定されているかどうか確認する。
514                        errBuf.insert( 0,"<pre>" ).append( "</pre>" );
515                        jspPrint( errBuf.toString() );
516                }
517
518                return EVAL_PAGE;
519        }
520
521        /**
522         * jsChart出力用
523         * jsChartTag と jsChartData を使用して、jsChart情報を出力します。
524         *
525         * @og.rev 5.9.19.0 (2017/04/07) T.OTA 61200-170316-02  チャートサイズ・max・minの動的変更対応
526         * @og.rev 6.7.7.0 (2017/03/31) チャートデータで、ゼロ、null カラムを非表示にします。
527         * @og.rev 6.7.9.0 (2017/04/28) useRenderer 追加
528         * @og.rev 6.8.0.0 (2017/06/02) sortColumn 追加
529         * @og.rev 6.8.3.0 (2017/11/27) useZeroDataOmit属性で、nullOmit属性もセットします。
530         * @og.rev 6.8.3.0 (2017/11/27) useEqValOmit属性の追加
531         * @og.rev 6.8.3.1 (2017/12/01) 不要なデータを出力しないようにします。
532         * @og.rev 5.9.27.0 2017/12/01  T.OTA 61200-170831-04   max,minの小数点対応
533         * @og.rev 6.8.5.0 (2018/01/09) xbeginAtZero,ybeginAtZero,markValues,markColors,markLbls,markAdjust,rangeMin,rangeMax,usePointStyle属性の追加
534         * @og.rev 6.9.9.2 (2018/09/18) chart.jsが2.4.0から2.7.2にバージョンアップにより、廃止された属性対応
535         * @og.rev 6.9.9.2 (2018/09/18) plugins,chartAttributes属性の追加
536         * @og.rev 6.9.9.3 (2018/09/25) xscaleType の time 属性廃止。
537         * @og.rev 6.9.9.4 (2018/10/01) リニア対応,time 属性復活
538         * @og.rev 6.9.9.4 (2018/10/01) idの振り方、データの持ち方変更
539         * @og.rev 7.0.1.1 (2018/10/22) xmarkValues,xmarkColors属性の追加
540         * @og.rev 7.0.1.3 (2018/11/12) バッファキー検索処理追加、markColors,xmarkColors属性に、VIVID,PASTELカラー指定に対応します。
541         * @og.rev 8.0.0.0 (2021/08/31) BUBBLEとSCATTERの追加
542         * @og.rev 8.0.0.0 (2021/08/31) horizontalBar 廃止 → indexAxis="y" 指定
543         * @og.rev 8.3.1.0 (2022/10/14) ラベルのカラムの最小幅対応(minLabelWidth 属性追加)(問合・トラブル 0200009388)
544         * @og.rev 8.4.0.0 (2023/01/27) useVertStrm属性追加(chartjs-plugin-streamingのVertical Scroll不具合対応)
545         *
546         * @return jsChert用文字列
547         */
548        private String jsChartOutput() {
549//              // 各JavaScriptの変数名
550//              final String cd                 = "cd_" + id;           //chartData
551//              final String myChart    = "chart_"+id;
552
553                // JSON形式でテーブル情報を取得
554                // テーブル情報の取得
555                // 6.8.0.0 (2017/06/02) sortColumn 追加
556                DBTableModel table = (DBTableModel)getObject( tableId ) ;
557                if( StringUtil.isNotNull( sortColumn ) ) {                                                              // 6.8.5.0 (2018/01/09)
558                        final int clmNo = table.getColumnNo( sortColumn );                                      // エラーを出す
559
560                        final DBTableModelSorter temp = new DBTableModelSorter();
561                        temp.setModel( (DBTableModel)getObject( tableId ) );
562                        temp.sortByColumn( clmNo,true );                                                                        // 順方向のソート
563                        table = temp;
564                }
565
566                final int rowCount = table.getRowCount();                                                               // 6.9.2.0 (2018/03/05)
567
568                // 7.0.1.3 (2018/11/12) DBTableModelに存在しないカラムのChartDataは無視します。
569                // これは、動的にグラフを生成する場合に、カラムの増減に合わせて、JsChartDataTagを生成しなおすのが手間だからです。
570                final Iterator<JsChartData> itr = jsChartData.iterator();                               // 個々のグラフ
571                while( itr.hasNext() ) {
572                        final JsChartData jcData = itr.next();
573                        final String chtClm = jcData.getChartColumn();
574                        final int    clmNo  = table.getColumnNo( chtClm );                                      // エラーを出す
575
576                        if( clmNo < 0 ) {
577                                itr.remove();                                                                                                   // 7.0.1.3 (2018/11/12) カラムがDBTableModelに存在しない。
578                        }
579                        // ゼロデータを使用しない設定
580                        else if( useZeroDataOmit ) {
581                                // 6.8.3.1 (2017/12/01) ループ処理の判定は、ChartColumn のみでよい。
582                                boolean isRemove = true;
583                                for( int row=0; row<rowCount; row++ ) {
584                                        final String val = table.getValue( row,clmNo );
585                                        if( StringUtil.isNotNull( val ) && !"0".equals( val ) && !"0.0".equals( val ) && !"0.00".equals( val ) ) {      // 6.8.5.0 (2018/01/09)
586                                                isRemove = false;
587                                                break;                                                                                                  // 判定処理打ち切り
588                                        }
589                                }
590
591                                if( isRemove ) {
592                                        itr.remove();                                                                                           // 全てがゼロ、null カラムを削除します。
593                                }
594                        }
595                }
596
597                // 8.3.1.0 (2022/10/14) チャートの全体幅を自動設定
598                if( minLabelWidth != null ) {
599                        // 全体幅(数字のみ抽出)
600                        final int tWid = Integer.parseInt(width.replaceAll("\\D+",""));
601                        // 最小幅(数字のみ抽出) × データ行数
602                        final int mWid = Integer.parseInt(minLabelWidth.replaceAll("\\D+","")) * rowCount;
603
604                        // 全体幅 ≧ 最小幅 × データ行数 ⇒ 全体幅 に設定
605                        // 全体幅 < 最小幅 × データ行数 ⇒ 最小幅 × データ行数 が全体幅として設定
606                        width = ( tWid >= mWid ? tWid : mWid ) + "px";
607                }
608
609                // 6.8.3.1 (2017/12/01) 不要なデータを出力しないようにします。
610                final int clmSize = jsChartData.size();                                                                 // JsChartTag の 値部分のみの配列
611
612                final String[] clmNms = new String[clmSize];                                                    // 6.9.9.4 (2018/10/01) カラム名の配列
613                final int[]    clmNos = new int[clmSize];
614                final int      lblNos = table.getColumnNo( labelColumn );                               // エラーを出す
615                final DBColumn dbClm  = table.getDBColumn( lblNos );                                    // 6.9.2.0 (2018/03/05)
616
617                // jsChartDataタグの変数宣言
618                for( int j=0; j<clmSize; j++ ) {
619                        final String chtClm = jsChartData.get(j).getChartColumn();
620//                      clmNms[j] = chtClm;                                                                                                     // 6.9.9.4 (2018/10/01) カラム名の配列 8.0.0.0 (2021/09/30) Delete
621                        clmNos[j] = table.getColumnNo( chtClm );                                                        // エラーを出す
622
623                        final String clmRnm = "CLM" + j;                                                                        // 8.0.0.0 (2021/09/30) JavaScript変数名対応
624                        jsChartData.get(j).setChartColumn(clmRnm);
625                        clmNms[j] = clmRnm;
626                }
627
628                //      8.0.0.0 (2021/08/31) chartJs V3 以降は、timeもrealtimeも表示するようになった…らしい
629                final StringBuilder rtn = new StringBuilder( BUFFER_MIDDLE )
630                        .append( IE_CHECK )                                                                                                     // IE 警告
631                        .append( "<canvas class=\""     ).append( CANVAS_NAME )                                 // canvasタグの設定
632                        .append( "\" id=\""                     ).append( id            )
633                        .append( "\" width=\""          ).append( width         )
634                        .append( "\" height=\""         ).append( height        )
635                        .append( "\"><!-- --></canvas>" ).append( CR    )
636                        .append( "<script>{" ).append( CR )                                                                     // 8.0.0.0 (2021/08/31) スコープ限定の '{' を追加
637                        .append( chartBody );                                                                                           // 7.0.1.1 (2018/10/22) BODY部分の文字列の組み込み
638
639                final boolean isXcateType  = TYPE_CATEGORY.equals(      xscaleType );           // 6.9.9.4 (2018/10/01)
640                final boolean isXlinerType = TYPE_LINEAR.equals(        xscaleType );           // 6.8.5.0 (2018/01/09) xscaleType が linear かどうか
641                final boolean isXtimeType  = TYPE_TIME.equals(          xscaleType );           // 6.8.5.0 (2018/01/09) xscaleType が time かどうか
642
643                // 7.0.1.3 (2018/11/12) const 変数に設定する配列情報を、bufに追加します。
644                final DBTableModel fcTable = table;                     // ラムダ式で使えるのは、final宣言された変数のみ。根本は、Sorterを組み込んでfinalすべき。
645                final IntFunction<String> lcFunc = (row) -> {
646                                final String lval = fcTable.getValue( row,lblNos );
647                                return useRenderer && !isXlinerType
648                                                        ? StringUtil.jsonFilter( dbClm.getRendererValue(row,lval) ) : lval ;
649                };
650                setVarArray( rtn,labelColumn,rowCount,isXcateType || isXtimeType || useRenderer,lcFunc );
651
652                // 6.9.9.4 (2018/10/01) データ部の出力
653                for( int j=0; j<clmSize; j++ ) {
654                        final int clmNo = clmNos[j];            // finalしか参照できないため
655                        setVarArray( rtn,clmNms[j],rowCount,valueQuot,(row) -> fcTable.getValue( row,clmNo ) );
656                }
657
658                // x軸がlinearスケールの場合
659                // [{x:値1,y:値2},{x:値1,y:値2},・・・] 形式のデータが必要
660                if( isXlinerType ) {
661                        for( int j=0; j<clmSize; j++ ) {
662                                final String chtClm = clmNms[j];
663                                rtn.append( "const LI_" ).append( chtClm ).append( "=[];" ).append( CR );
664
665                                // 6.9.9.4 (2018/10/01) x軸がlinearスケールの場合、カラム名が、変わるので、再設定している。(超特殊処理)
666                                jsChartData.get(j).setChartColumn( "LI_" + chtClm );
667                        }
668
669                        rtn.append( "for(var i=0; i<").append( labelColumn ).append( ".length; i++){" );
670                        for( int j=0; j<clmSize; j++ ) {
671                                final String chtClm = clmNms[j];
672                                        // {x:ラベル, y:値}の形式で値を設定
673                                rtn.append( "LI_" ).append( chtClm ).append( "[i]={x:" ).append( labelColumn )
674                                        .append( "[i],y:" ).append( chtClm ).append( "[i]};" );
675                        }
676                        rtn.append( "};" ).append( CR );
677                }
678
679                // 7.0.1.2 (2018/11/04) varColumns 追加
680                final String[] varClms = StringUtil.csv2Array( varColumns );    // 独自に出力しておきたいカラム列の値
681                for( int j=0; j<varClms.length; j++ ) {
682                        final int varNos = table.getColumnNo( varClms[j] );                     // エラーを出す
683                        final boolean isNumType = table.getDBColumn( varNos ).isNumberType();                   // 6.4.6.0 (2016/05/27)
684
685                        setVarArray( rtn,varClms[j],rowCount,!isNumType,(row) -> fcTable.getValue( row,varNos ) );
686                }
687
688                // 8.0.0.0 (2021/08/31) BUBBLEとSCATTERの追加
689                // chartType が BUBBLE の場合、chtClmが x:、varColumns の最初が、y: 次が r: になる
690                // SCATTERの場合は、r: がないだけ
691                if( CTYPE_BUBBLE.equals( chartType ) || CTYPE_SCATTER.equals( chartType ) ) {
692                        if( CTYPE_BUBBLE.equals( chartType ) && varClms.length < 2 ||
693                                CTYPE_SCATTER.equals( chartType ) && varClms.length < 1 ) {
694                                        final StringBuilder errMsg = new StringBuilder( BUFFER_MIDDLE )
695                                                .append( "chartTypeが、" ).append( chartType )
696                                                .append( "の場合は、varColumns で、y: データ、r:データを指定してください。" );
697                                        throw new HybsSystemException( errMsg.toString() );
698                        }
699
700                        final String chtClm = clmNms[0];                // chartDataの1個目決め打ち
701                        rtn.append( "const LI_" ).append( chtClm ).append( "=[];" ).append( CR );
702
703                        // x軸が[{x: , y: , r: }…} のカラム名が変わるので、再設定している。(超特殊処理)
704                        jsChartData.get(0).setChartColumn( "LI_" + chtClm );
705
706                        rtn.append( "for(var i=0; i<").append( chtClm ).append( ".length; i++){" )
707                                .append( "LI_" ).append( chtClm ).append( "[i]={x:" ).append( chtClm )
708                                .append( "[i],y:" ).append( varClms[0] );
709
710                        // 切れ切れで分かりにくいかもしれないが、BUBBLEのみ、r: を出す
711                        if( CTYPE_BUBBLE.equals( chartType ) ) {
712                                rtn.append( "[i],r:" ).append( varClms[1] );
713                        }
714
715                        rtn.append( "[i]};}" ).append( CR );
716                }
717
718                // ==================================================================================
719                // 7.0.1.1 (2018/10/22) jsChartData(X軸)の設定
720                if( !SET_CI_TYPE.contains( chartType ) ) {
721                        jsXAxis.setId( "x0" );                                          // X軸のid
722                        jsXAxis.setUseTime( isXtimeType );                      // x軸の時間表示を使用するかどうか
723
724                        // 7.0.1.3 (2018/11/12) バッファキー検索処理追加
725                        if( isXtimeType && !jsXAxis.contains( JsChartData.TIME , "displayFormats" ) ) {         // キーワードが無ければ追加
726                                // ほんとはリソースに入れるべきでしょう
727                                if( "ja".equalsIgnoreCase( getLanguage() ) ) {                                          // 'ja' なら日本
728                                        jsXAxis.addTime( "displayFormats" , TIME_FORMAT_JA , NO_QUOTE );        // 標準タイムフォーマット適用。オブジェクトなので、クオートなし
729                                }
730                                else {
731                                        jsXAxis.addTime( "displayFormats" , TIME_FORMAT , NO_QUOTE );           // 標準タイムフォーマット適用。オブジェクトなので、クオートなし
732                                }
733                        }
734
735                        // x軸にリニアスケールを設定した場合(これは残す)
736                        final String xpos = xposition != null ? xposition
737                                                                                                  : isXlinerType ? "bottom"
738                                                                                                                                 : null ;       // horizontalBar 廃止
739                        jsXAxis.addAxis( "position" , xpos , USE_QUOTE );       // 文字
740
741                        rtn.append( jsXAxis.getAxis() ).append( CR );
742                }
743
744                // ==================================================================================
745                // jsChartData(Y軸)の設定
746
747                // 各JavaScriptの変数名
748                final String cd                 = "cd_" + id;           //chartData
749                final String myChart    = "chart_"+id;
750
751                // 7.0.1.1 (2018/10/22) data:dataset と、options:scales:yAxes: を変数化して出力します。
752                for( final JsChartData chData : jsChartData ) {
753                        rtn.append(  chData.getDataset( 'y' )   ).append( CR )          // 横棒線の場合は、'x'が、それ以外は、'y'
754                                .append( chData.getAxis()                       ).append( CR );
755                }
756
757                rtn.append( "const ").append( cd ).append( "={labels:" ).append( labelColumn ).append( ",datasets:[" );
758                for( final JsChartData chData : jsChartData ) {
759                        rtn.append( chData.getDatasetKey() ).append( ',' );
760                }
761                rtn.append( "]};" ).append( CR )
762                        // jsChartの生成(グローバル変数定義の var)
763                        .append( "var " ).append( myChart ).append( "=new Chart(" ).append( id )
764                        .append( ",{" )
765                        .append( CR_TAB[1] ).append( "type:'" ).append( chartType ).append( "'," )
766                        .append( CR_TAB[1] ).append( "data:"  ).append( cd ).append( ',' );
767
768                // 6.9.9.2 (2018/09/18) plugins,chartAttributes属性の追加
769                setProp( rtn, CR_TAB[1],"plugins:["  , plugins   , "]," );
770
771                rtn.append( CR_TAB[1] ).append( "options:{responsive:false," );                 // レスポンシブ OFF
772
773                // 8.0.0.0 (2021/08/31)
774                setProp( rtn, CR_TAB[2],"indexAxis:'" , indexAxis , "'," );                             // "y" を指定することで、horizontalBar や verticalLine を実現
775                setProp( rtn, CR_TAB[2],"categoryPercentage:" , barWidthPer , "," );    // 棒線の横幅
776                setProp( rtn, CR_TAB[2],"animation:" , animation , "," );                               // 簡易的なアニメーションのON/OFFを設定
777
778                // クリックイベントの設定
779                // clickLink 変数を使用する場合、内部でマスタデータを使用します。キーとして、渡しておく必要があります。
780                setProp( rtn, CR_TAB[2],"onClick:function(event,obj){",CR_TAB[3], onClick,CR_TAB[2],"}," );
781
782                // 8.0.0.0 (2021/08/31) options:plugins:
783                rtn.append( CR_TAB[2] ).append( "plugins:{" );
784
785                setProp( rtn, CR_TAB[3], optPlugins , "," );                                                    // 8.0.0.0 (2021/09/30) 属性はマージされる
786                setProp( rtn, CR_TAB[3],"tooltip:{" , optTooltip , "}," );                              // 8.0.0.0 (2021/09/30)
787
788                // タイトル属性の設定(タイトル要素も処理できるように変更))
789                if( title != null && title.length() > 0 ) {
790                        if( title.charAt(0) == '{' ) {
791                                rtn.append( CR_TAB[3] ).append( "title:" ).append( title ).append( ',' );
792                        }
793                        else if( title.charAt(0) == '[' ) {
794                                // タイトルに配列を渡すと、改行表示する。
795                                setProp( rtn, CR_TAB[3],"title:{display:true,text:",title,",position:'", titlePosition, "',}," );
796                        }
797                        else {
798                                // タイトルを文字列として処理する。
799                                setProp( rtn, CR_TAB[3],"title:{display:true,text:'",title,"',position:'", titlePosition, "',}," );
800                        }
801                }
802
803                // 凡例属性の設定(
804                if( useLegend ) {                                                                                                               // 7.0.1.1 (2018/10/22)
805                        rtn.append( CR_TAB[3] ).append( "legend:{" );
806                        setProp( rtn, optLegend  , ","  );                                                                      // 8.0.0.0 (2021/09/30) 属性はマージされる
807                        setProp( rtn, "display:"   , legendDisplay  , ","  );
808                        setProp( rtn, "position:'" , legendPosition , "'," );
809
810                        // 凡例のスタイルを、pointStyle にあわせるかどうか
811                        if( usePointStyle ) {                                                                                           // 7.0.1.1 (2018/10/22)
812                                rtn.append( "labels:{usePointStyle:true}," );
813                        }
814                        rtn.append( "}," );
815                }
816
817                // 8.0.0.0 (2021/08/31) zoom は、文法も変わり、options:plugins: 以下の属性になった。
818                // 6.8.5.0 (2018/01/09) ズーム処理を使用するかどうか
819                if( useZoom ) {         // useZoom を優先する。
820                        rtn.append( CR_TAB[3] ).append( WHEEL_ZOOM );
821                }
822                else if( useDragZoom ) {
823                        rtn.append( CR_TAB[3] ).append( DRAG_ZOOM );
824                }
825
826                // 8.0.0.0 (2021/08/31) annotation は、options:plugins: 以下の属性になった。
827                final String[] mkVals  = StringUtil.csv2Array( markValues );                    // y軸の値で、横のマーカー
828                final String[] xmkVals = StringUtil.csv2Array( xmarkValues );                   // x軸の値で、縦のマーカー
829                final int vCnt = mkVals.length;
830                final int xCnt = xmkVals.length;
831                if( vCnt > 0 || xCnt > 0 ) {
832                        rtn.append( CR_TAB[3] ).append( "annotation:{annotations:{" );          // 8.0.0.0 (2021/08/31) 配列からオブジェクトへ
833
834                        // 従来の markValues,markColors,markLbls,markAdjust 属性対応
835                        if( vCnt > 0 ) {
836                                final String[] mkLbls = StringUtil.csv2Array( markLbls          , ',' , vCnt );
837                                final String[] mkAjst = StringUtil.csv2Array( markAdjust        , ',' , vCnt , MARK_DEF_ADJUST );
838                                final String[] mkCols = colorCsv( markColors , vCnt );                  // 7.0.1.3 (2018/11/12)
839
840                                // 7.0.1.1 (2018/10/22) 'y-axis-0' → 'y0Ax' これは、JsChartData#getAxisKey() で取得できる値だが、決め打ち
841                                for( int i=0; i<vCnt; i++ ) {
842                                        rtn.append( CR_TAB[4] ).append( "yline" ).append(i).append( ":{" )      // V3で、名前付きになった。
843                                                .append( CR_TAB[5] ).append( "type:'line'," );
844                                        setProp( rtn, "borderWidth:"            , markWidth     , ","   );
845                                        setProp( rtn, "borderDash:"                     , markDash      , ","   );
846                                        setProp( rtn, "borderColor:'"           , mkCols[i] , "',"      );
847                                        setProp( rtn, CR_TAB[5],"yMin:"         , mkVals[i]     , ","   );                      // V3 → V2 で、valueから、yMin,yMax に変更
848                                        setProp( rtn,                   "yMax:"         , mkVals[i]     , ","   );
849                                        if( !mkLbls[i].isEmpty() ) {
850                                                rtn.append( CR_TAB[5] ).append( "label:{" )
851                                                        .append( CR_TAB[6] )
852                                                        .append( "enabled:'true',position:'start',backgroundColor:'rgba(0,0,0,0)'," )   // position:left → start に変更
853                                                        .append( CR_TAB[6] );
854                                                setProp( rtn, "content:'"               , mkLbls[i] , "'," );
855                                                setProp( rtn, "color:'"                 , mkCols[i] , "'," );
856                                                setProp( rtn, "yAdjust:"                , mkAjst[i]     , ","   );
857                                                setProp( rtn, CR_TAB[6],"font:{size:" , markFontSize , "},"     );      // fontSize:XX → font:{size:XX} に変更
858                                                rtn.append( CR_TAB[5] ).append( "}," );         // label:{
859                                        }
860                                        rtn.append( CR_TAB[4] ).append( "}," );         // type:
861                                }
862                        }
863
864                        // 7.0.1.1 (2018/10/22) xmarkValues,markLbls,xmarkColors属性対応
865                        if( xCnt > 0 ) {
866                                final String[] xmkLbls = StringUtil.csv2Array( xmarkLbls        , ',' , xCnt ); // 8.0.0.0 (2021/09/30)
867                                final String[] xmkCols = colorCsv( xmarkColors , xCnt );                        // 7.0.1.3 (2018/11/12)
868
869                                // 7.0.1.1 (2018/10/22) 'x-axis-0' → 'x0Ax' これは、JsChartData#getAxisKey() で取得できる値だが、決め打ち
870                                for( int i=0; i<xCnt; i++ ) {
871                                        rtn.append( CR_TAB[4] ).append( "xline" ).append(i).append( ":{" )
872                                                .append( CR_TAB[5] ).append( "type:'line'," );                          // V3で、名前付きになった。
873                                        setProp( rtn, "borderWidth:"            , markWidth     , ","   );
874                                        setProp( rtn, "borderDash:"                     , markDash      , ","   );
875                                        setProp( rtn, "borderColor:'"           , xmkCols[i] , "'," );
876                                        setProp( rtn, CR_TAB[5],"xMin:'"        , xmkVals[i] , "',"     );              // V3 → V2 で、valueから、xMin,xMax に変更
877                                        setProp( rtn,                   "xMax:'"        , xmkVals[i] , "',"     );              // カテゴリで文字列のケース有り
878                                        if( !xmkLbls[i].isEmpty() ) {                                                                   // 8.0.0.0 (2021/09/30)
879                                                rtn.append( CR_TAB[5] ).append( "label:{" )
880                                                        .append( CR_TAB[6] )
881                                                        .append( "enabled:'true',position:'end',backgroundColor:'white'," )     // position:left → start に変更
882                                                        .append( CR_TAB[6] );
883                                                setProp( rtn, "content:'"               , xmkLbls[i] , "'," );
884                                                setProp( rtn, "color:'"                 , xmkCols[i] , "'," );
885                                                setProp( rtn, CR_TAB[6],"font:{size:" , markFontSize , "},"     );      // fontSize:XX → font:{size:XX} に変更
886                                                rtn.append( CR_TAB[5] ).append( "}," );         // label:{
887                                        }
888                                        rtn.append( CR_TAB[4] ).append( "}," );         // type:
889                                }
890                        }
891                        rtn.append( CR_TAB[3] ).append( "}}," );                // annotation:{annotations:{
892                }
893                rtn.append( CR_TAB[2] ).append( "}," );         // plugins:{
894
895                // 6.9.9.2 (2018/09/18) chart.jsが2.4.0から2.7.2にバージョンアップにより、廃止された属性対応
896                // 円形以外の場合はscales属性に設定
897                if( !SET_CI_TYPE.contains( chartType ) ) {
898                        // scalesのx軸、y軸
899                        String xSe = "x:";
900                        String ySe = "y:";
901
902                        // streamingの垂直スクロールを使用する場合は、x軸とy軸を入れ替えます
903                        if( useVertStrm ) { xSe = "y:"; ySe = "x:"; }
904
905//                      rtn.append( CR_TAB[2] ).append( "scales:{x:" )
906                        rtn.append( CR_TAB[2] ).append( "scales:{" ).append( xSe )                      // 8.4.0.0 (2023/01/27) Modify
907                                .append( jsXAxis.getAxisKey() ).append( ',' );
908
909                        // 7.0.1.1 (2018/10/22) options:scales:yAxes: を変数化して出力しているので、その設定のみでよい。
910                        // 最初の一つだけ、"y:" を付ける(何か方法があるはず)。
911                        boolean isFirst = true;
912                        for( final JsChartData chData : jsChartData ) {
913                                if( chData.isUseAxis() ) {
914//                                      if( isFirst ) { rtn.append( "y:" ); isFirst=false; }
915                                        if( isFirst ) { rtn.append( ySe ); isFirst=false; }                     // 8.4.0.0 (2023/01/27) Modify
916                                        rtn.append( chData.getAxisKey() ).append( ',' );
917                                }
918                        }
919
920                        rtn.append( "}," );             // 7.0.1.1 (2018/10/22)
921                }
922
923                setProp( rtn, CR_TAB[2] , optOptions , "," );           // 7.0.1.2 (2018/11/04)
924                rtn.append( CR_TAB[1] ).append( "}," )
925                        .append( CR_TAB[0] ).append( "});" ).append( CR );
926
927                // 8.0.0.0 (2021/08/31) zoom を使った場合は、ダブルクリックで元に戻す処理を入れておく
928                if( useZoom || useDragZoom ) {
929                        rtn.append( "const cv_" ).append( id ).append( "=document.getElementById('" )
930                                .append( id ).append( "');" ).append( CR )
931                                .append( "cv_" ).append( id ).append( ".addEventListener( 'dblclick',function(){" )
932                                .append( myChart )                                                              // Chart オブジェクト
933                                .append( ".resetZoom();});" ).append( CR );
934                }
935
936                rtn.append( "}</script>" );     // 8.0.0.0 (2021/08/31) スコープ限定の '}' を追加
937
938                return rtn.toString();
939        }
940
941        /**
942         * 引数のすべての文字列が null か、長さゼロ文字列でない場合は、連結した結果を返します。
943         *
944         * @param       buf     ベースとなるStringBuilder
945         * @param       str     連結対象の文字列群(可変長引数)
946         */
947        private void setProp( final StringBuilder buf, final String... strs ) {
948                if( !StringUtil.isEmpty( strs ) ) {             // null か、長さゼロ文字列が、一つもない場合
949                        for( final String str : strs ) {
950                                buf.append( str );
951                        }
952                }
953        }
954
955        /**
956         * const 変数に設定する配列情報を、bufに追加します。
957         *
958         * const 変数名が key で、cnt分の繰返しで、IntFunction を呼びます。
959         * isQuote=trueの場合は、前後にクォーテーションをつけます。
960         *
961         * @og.rev 7.0.1.3 (2018/11/12) const 変数に設定する配列情報を、bufに追加します。
962         * @og.rev 8.0.2.1 (2021/12/10) 空文字列の場合は、クォーテーションを付けない。
963         *
964         * @param       buf             ベースとなるStringBuilder
965         * @param       key             キー
966         * @param       cnt             ループする個数(通常は行数:rowCount)
967         * @param       isQuote クォーテーションで括るかどうか [true:括る/false:括らない]
968         * @param       func    数値を引数に取る関数型インタフェース
969         */
970        private void setVarArray( final StringBuilder buf, final String key, final int cnt,
971                                                                final boolean isQuote, final IntFunction<String> func ) {
972                buf.append( "const " ).append( key ).append( "=[" );
973                for( int row=0; row<cnt; row++ ) {
974                        final String val = nval( func.apply( row ),"" );        // null 文字列が append されるのを避ける
975
976                        if( val.isEmpty() ) {                   // 8.0.2.1 (2021/12/10)
977                                buf.append( ',' );
978                        }
979                        else if( isQuote ) {
980                                buf.append( '"' ).append( val ).append( "\"," );
981                        }
982                        else {
983                                buf.append( val ).append( ',' );
984                        }
985                }
986                buf.append( "];" ).append( CR );
987        }
988
989        /**
990         * パラメータチェック用メソッド。
991         *
992         * @param       trg             ターゲット
993         * @param       set             使用可能なキーワードのSet
994         * @param       trgStr  ターゲットの名称
995         */
996        private void checkPara( final String trg, final Set<String> set, final String trgStr ) {
997                if( StringUtil.isNotNull( trg ) && !check( trg, set ) ) {                                               // 6.8.5.0 (2018/01/09)
998                        final StringBuilder errMsg = new StringBuilder( BUFFER_MIDDLE )
999                                .append( "指定の" ).append( trgStr ).append( "は指定できません。" ).append( CR )
1000                                .append( trgStr ).append( "=[" ).append( trg ).append( ']' ).append( CR )
1001                                .append( set );         // org.opengion.fukurou.util.ArraySet の toStringメソッド
1002                        throw new HybsSystemException( errMsg.toString() );
1003                }
1004        }
1005
1006//      /**
1007//       * JavaScript変数チェック用メソッド。
1008//       *
1009//       * 1文字目は数字と、特殊記号(アンダーバー(_)、ドル記号($)を除く)、をチェックします。
1010//       * 厳密には、予約文字が使えなかったりするが、簡易チェックとする。
1011//       * 前後の空白文字は除外、それ以外の特殊記号は、アンダーバー(_)に変換します。
1012//       *
1013//       * @og.rev 8.0.0.0 (2021/09/30) JavaScriptの変数名チェックと置換
1014//       *
1015//       * @param       key             チェックする変数
1016//       * @param       trgStr  変数置換後の変数
1017//       */
1018//      private String checkPara( final String key ) {
1019//              if( !useVarCheck ) { return key; }                              // useVarCheck が false の場合は、何もしない。
1020//
1021//              if( key == null || key.isEmpty() ) { return "_"; }
1022//
1023//              final StringBuilder buf = new StringBuilder(key.trim());
1024//              for( int i=0; i<buf.length(); i++ ) {
1025//                      final char ch = buf.charAt(i);
1026//                      if( i==0 && '0'<=ch && ch<='9'                  ||
1027//                              ' '<=ch && ch<='/' && '$'!=ch           ||
1028//                              ':'<=ch && ch<='@'                                      ||
1029//                              '['<=ch && ch<='`' && '_'!=ch           ||
1030//                              '{'<=ch && ch<='~' ) { buf.setCharAt( i,'_' ); }
1031//              }
1032//
1033//              return buf.toString();
1034//      }
1035
1036        /**
1037         * 色コードの配列を返すメソッドです。
1038         *
1039         * これは、普通のCSV形式のデータなら、そのまま分割します。
1040         * 配列は、lenの数だけ作成します。
1041         * nullやゼロ文字列の場合は、ColorMapのOLOR_KEYすべてを対象にします。
1042         * 1色の場合も、すべて同じ色をlen の数だけセットします。
1043         *
1044         * VIVIDとPASTEL はキーワードで、org.opengion.fukurou.util.ColorMap のビビッドカラーと
1045         * パステルカラーの配列を指定したことと同じになります。
1046         * また、色番号として、ビビッドを、(V0~V11) , パステルを、(P0~P11)
1047         * に割当てていますので、配列に分解後一旦すべてのキーワードを色番号検索に使用します。
1048         *
1049         * @og.rev 7.0.1.3 (2018/11/12) 色コードの配列を返すメソッド追加
1050         *
1051         * @param       colCsv  色コードのCSV形式文字列
1052         * @param       len             作成する配列の個数
1053         * @return      色コードに変換後の配列
1054         */
1055        private String[] colorCsv( final String colCsv, final int len ) {
1056                // 色の数を、len にあわせる必要があります。
1057                final String[] mkCols = new String[len];
1058
1059                // cols を元に、ColorMap から色配列を取得します。
1060                final String[] cols = ColorMap.getColorKeys( colCsv );
1061
1062                // 色配列に順番に割り当てますが、色が足りない場合は、初期値の色をセットします。
1063                final int min = Math.min( mkCols.length , cols.length );
1064                for( int i=0; i<min; i++ ) {
1065                        mkCols[i] = cols[i];
1066                }
1067                for( int i=min; i<mkCols.length; i++ ) {
1068                        mkCols[i] = cols[0];                                                                                            // 色コードの最初の色
1069                }
1070
1071                return mkCols ;
1072        }
1073
1074        /**
1075         * jsChartData情報をリストに追加します。
1076         *
1077         * @og.rev 6.7.5.0 (2017/03/10) リストの初期化方法を変更します。
1078         *
1079         * @param       jsData  jsChartData情報
1080         */
1081        protected void addJsChartData( final JsChartData jsData ) {
1082                jsChartData.add( jsData );
1083        }
1084
1085        /**
1086         * 登録済みのjsChartData情報の個数を返します。
1087         *
1088         * @og.rev 6.7.7.0 (2017/03/31) 新規登録
1089         *
1090         * @return      登録済みのjsChartData情報の個数
1091         */
1092        protected int getJsChartDataSize() {
1093                return jsChartData.size();
1094        }
1095
1096        /**
1097         * borderColorとbackgroundColorに色を1色しか使用できないかどうかを返します。
1098         *
1099         * chartType に応じて、色配列が使用できないタイプがあります。
1100         *    line/radar が true (1色しか使用できない)
1101         *    それ以外(bar/polarArea/pie/doughnut)が false (色配列が使用できる)
1102         *
1103         * @og.rev 7.0.1.1 (2018/10/22) 新規登録
1104         *
1105         * @return      登録済みのjsChartData情報の個数
1106         */
1107        protected boolean isOneColor() {
1108                // line/radar が true (1色しか使用できない)
1109                return CTYPE_LINE.equalsIgnoreCase( chartType ) || CTYPE_RADAR.equalsIgnoreCase( chartType );
1110        }
1111
1112        // =================================================================================
1113
1114        /**
1115         * 【TAG】チャートの種類を指定します[line/bar/radar/polarArea/pie/doughnut/bubble/scatter](必須)。
1116         *
1117         * @og.tag
1118         * コンフィグ属性の type 定義です。
1119         * なお、複合グラフ時には、この値を、"bar" にしておかないと、きちんと表示しないようです。
1120         *
1121         * 8.0.0.0 (2021/08/31)
1122         *  chartTypeが、bubbleとscatterの場合は、y:データ、r:データを varColumns で
1123         *  指定します。詳細は、varColumns の説明をご確認ください。
1124         *
1125         *  horizontalBar 廃止 → indexAxis="y" 指定 (当面は互換性の関係で残しますが、廃止予定です)
1126         *  verticalLine 相当の表示も indexAxis="y" 指定
1127         *
1128         * @og.rev 8.0.0.0 (2021/08/31) BUBBLEとSCATTERの追加
1129         *
1130         * @param       cType   チャートタイプ [line/bar/radar/polarArea/pie/doughnut/bubble/scatter]
1131         */
1132        public void setChartType( final String cType ) {
1133                chartType = nval( getRequestParameter( cType ) , null );
1134
1135                // 8.0.0.0 (2021/08/31) 互換性の関係で、少し残す。euromap63で使用中
1136                if( "horizontalBar".equalsIgnoreCase( chartType ) ) {
1137                        indexAxis = "y";
1138                        chartType = CTYPE_BAR;
1139        // いちいち表示がうるさいので、メッセージを出すのを当面やめておきます。
1140        //              final String errMsg = "chartTypeのhorizontalBarは廃止されました。代わりに、indexAxis='y'を指定してください。";
1141        //              System.err.println( errMsg );
1142                        return ;
1143                }
1144
1145                if( !check( chartType, CTYPE_SET ) ) {
1146                        final StringBuilder errMsg = new StringBuilder( BUFFER_MIDDLE )
1147                                .append( "指定のチャートタイプは実行できません。"        ).append( CR )
1148                                .append( "chartType=[" ).append( chartType ).append( ']' ).append( CR )
1149                                .append( CTYPE_SET );   // org.opengion.fukurou.util.ArraySet の toStringメソッド
1150                        throw new HybsSystemException( errMsg.toString() );
1151                }
1152        }
1153
1154        /**
1155         * 【TAG】ラベルのカラム名を指定します(表示名称) (必須)。
1156         *
1157         * @og.tag
1158         * 表示名称に使用するデータベースの検索時のカラムを指定します。
1159         *
1160         * @param       lblclm  ラベルカラム
1161         */
1162        public void setLabelColumn( final String lblclm ) {
1163                labelColumn = nval( getRequestParameter( lblclm ),labelColumn );
1164        }
1165
1166        /**
1167         * 【TAG】canvasタグのidを指定します(初期値:hybscanvas)。
1168         *
1169         * @og.tag
1170         * canvasタグのidに設定します。
1171         *
1172         * @param       id      canvasタグのid
1173         */
1174        @Override
1175        public void setId( final String id ) {
1176                this.id = nval( getRequestParameter( id ),this.id );
1177        }
1178
1179        /**
1180         * 【TAG】チャートの高さを指定します(初期値:400px)。
1181         *
1182         * @og.tag
1183         * canvasタグの高さに設定します。
1184         *
1185         * @param       hei     設定する高さ
1186         */
1187        public void setHeight( final String hei ) {
1188                height = nval( getRequestParameter( hei ),height );
1189        }
1190
1191        /**
1192         * 【TAG】チャートの幅を指定します(初期値:400px)。
1193         *
1194         * @og.tag
1195         * canvasタグの横幅を設定します。
1196         *
1197         * @param       wid     設定する横幅
1198         */
1199        public void setWidth( final String wid ) {
1200                width = nval( getRequestParameter( wid ),width );
1201        }
1202
1203        /**
1204         * 【TAG】ラベルのカラム(データの枠)の最小幅を指定します。
1205         *
1206         * @og.tag
1207         * 標準のチャートは指定の全体幅に合わせてチャートのラベルのカラムの幅が自動調整されます。
1208         * ラベルが全て表示されない場合もあります。
1209         *
1210         * minLabelWidth を指定することで、ラベルのカラムの幅の最小値指定できます。
1211         * この指定により、チャートの全体幅が自動設定されます。
1212         *
1213         * ①全体幅(width)が 最小幅(minLabelWidth)×データ数 より大きい場合は
1214         *     全体幅 がそのまま設定されます。
1215         * ②全体幅(width)が 最小幅(minLabelWidth)×データ数 より小さい場合は
1216         *     最小幅×データ数 の計算値が全体幅となります。
1217         * ③全体幅を固定にしたい場合は、minLabelWidth を指定しません。
1218         *
1219         * @og.rev 8.3.1.0 (2022/10/14) ラベルのカラムの最小幅対応(minLabelWidth 属性追加)(問合・トラブル 0200009388)
1220         *
1221         * @param       wid     ラベルのカラムの最小幅
1222         */
1223        public void setMinLabelWidth( final String wid ) {
1224                minLabelWidth = nval( getRequestParameter( wid ),minLabelWidth );
1225        }
1226
1227        /**
1228         * 【TAG】プラグイン定義された関数を指定します。
1229         *
1230         * @og.tag
1231         * コンフィグ属性の type 定義です。
1232         *
1233         * プラグインは、plugins: [pinFunc], 形式で追加されます。
1234         * この属性での指定時は、[]は、不要で、CSV形式の関数名を並べます。
1235         * 外部に、const pinFunc = { afterDatasetsDraw: function(chart, options) { ・・・ } };
1236         * 形式のプラグインを指定することで、個別に読ませることが可能です。
1237         * なお、すべてのチャートに、同一のプラグインを指定する場合は、この属性ではなく、
1238         * Chart.plugins.register({ afterDatasetsDraw: function(chart, options) { ・・・ } });
1239         * 形式で、プラグイン登録
1240         *
1241         * ※ options:plugins: 属性とは異なります。
1242         *
1243         * @og.rev 6.9.9.2 (2018/09/18) プラグイン定義された関数を指定します。
1244         *
1245         * @param       attri   追加属性の値
1246         */
1247        public void setPlugins( final String attri ) {
1248                plugins = nval( getRequestParameter( attri ),plugins );
1249        }
1250
1251        // =================== options: 以下の属性 =========================================
1252
1253        /**
1254         * 【TAG】"y" を指定することで、horizontalBar や verticalLine を実現する。
1255         *
1256         * @og.tag
1257         * options: 以下の属性
1258         *  horizontalBar が廃止され、同様の機能は、indexAxis="y" 指定で実現できます。
1259         *  verticalLine 相当の表示も indexAxis="y" 指定で実現します。
1260         *  streamingのVertical Scroll を使用するときも indexAxis="y" を指定してください。
1261         *
1262         * @og.rev 8.0.0.0 (2021/08/31) horizontalBar 廃止 → indexAxis="y" 指定
1263         *
1264         * @param       indx    軸の方向('x','y')
1265         */
1266        public void setIndexAxis( final String indx ) {
1267                indexAxis = nval( getRequestParameter( indx ),null );
1268        }
1269
1270        /**
1271         * 【TAG】棒線の横幅を指定します(初期値:0.8, typeがbarの場合に有効)。
1272         *
1273         * @og.tag
1274         * options: 以下の属性
1275         *  options:xAxes:categoryPercentage → option:categoryPercentage の 要素の属性です。
1276         *
1277         * ※ 階層変更による対応のため、chartType による属性の出力制御は廃止しました。
1278         *
1279         * @og.rev 6.9.9.3 (2018/09/25) nvalを入れて、初期値を設定します。
1280         *
1281         * @param       widthPer        棒線の横幅
1282         */
1283        public void setBarWidthPer( final String widthPer ) {
1284                barWidthPer = nval( getRequestParameter( widthPer ),barWidthPer );
1285        }
1286
1287        /**
1288         * 【TAG】簡易的にアニメーションのON/OFFを設定(true/false)します(初期値::null=true)(options:animation)。
1289         *
1290         * @og.tag
1291         * options: 以下の属性
1292         *  options:animation の 要素の属性です。
1293         *
1294         * ※ 簡易的に、false を指定すると、アニメーションが OFF になります。
1295         *    各種属性が登録できるように、文字列を自由に登録できます。
1296         *
1297         * @og.rev 8.0.0.0 (2021/08/31) optionAttributesで設定していた項目を属性追加
1298         *
1299         * @param       flag    アニメーションのON/OFFを設定(true/false)
1300         */
1301        public void setAnimation( final String flag ) {
1302                animation = nval( getRequestParameter( flag ), animation );
1303        }
1304
1305        /**
1306         * 【TAG】チャートクリック時のイベントを指定します。
1307         *
1308         * @og.tag
1309         * options: 以下の属性
1310         * 下記の値が引数として渡されます。
1311         * " onClick:function(event,obj){" +  onClick + '}'
1312         * に変換されてセットされます。
1313         *   event:イベント情報
1314         *   obj:クリックされたオブジェクトの情報
1315         *
1316         * 例)
1317         *   onClick="clickLink( event,obj,'result_sample2.jsp?command=RENEW&amp;CLM={CLM}&amp;VAL={VAL}&amp;IDX={IDX}' );"
1318         *   onClick="updatechart(obj,'SubChart');"
1319         *   onClick="clickLink( event, obj,'index.jsp?chartTitle={LBL}&amp;markValues={CLM}' , parent );"
1320         *
1321         * 基本的には、外部関数を呼び出す設定を行い、実際の動作は外部関数側で行います。
1322         *
1323         * @param       click   チャートクリック時のイベントを指定
1324         */
1325        public void setOnClick( final String click ) {
1326                onClick = nval( getRequestParameter( click ),null );
1327        }
1328
1329        /**
1330         * 【TAG】optionsの属性に、その他オプションを追加します。
1331         *
1332         * @og.tag
1333         * optionsの属性に、その他オプションを追加します。
1334         * 指定する際の、前後の『{}』は、不要です。
1335         *
1336         * <a href="https://www.tohoho-web.com/ex/chartjs-params.html#options" target="_blank" >とほほ → オプション </a>
1337         *
1338         * @og.rev 7.0.1.2 (2018/11/04) 属性名変更
1339         *
1340         * @param       attri   オプションの値
1341         */
1342        public void setOptOptions( final String attri ) {
1343                optOptions = nval( getRequestParameter( attri ),null );
1344        }
1345
1346        // =================== options:scales:x: 以下の属性 ================================
1347
1348        /**
1349         * 【TAG】x軸のスケールタイプ[category/linear/time]を指定します(初期値:category)。
1350         *
1351         * @og.tag
1352         *  8.0.0.0 (2021/08/31)
1353         *  chartTypeが、bubbleとscatterの場合は、xscaleType は、初期値:category に
1354         *  しておいてください。内部で、x: y: r: 等のデータの割り当てを行います。
1355         * options:scales:xAxes:type → options:scales:x:type の 要素の属性です。
1356         *
1357         * @og.rev 6.9.9.3 (2018/09/25) nvalを入れて、初期値を設定します。
1358         * @og.rev 7.0.1.1 (2018/10/22) JsChartDataオブジェクトを使用。
1359         *
1360         * @param       xscaleType      x軸のスケールタイプ [category/linear/time]
1361         */
1362        public void setXscaleType( final String xscaleType ) {
1363                this.xscaleType = nval( getRequestParameter( xscaleType ) , this.xscaleType );
1364
1365                // プラグインなどで独自の type を指定することがあるため、警告だけにします。
1366                try {
1367                        checkPara( this.xscaleType, SET_XSCALE, "xscaleType" );
1368                }
1369                catch( final HybsSystemException ex ) {
1370                        System.err.println( ex.getMessage() );
1371                }
1372
1373                jsXAxis.addAxis( "type" , this.xscaleType , USE_QUOTE );                // 文字
1374        }
1375
1376        /**
1377         * 【TAG】x軸の表示位置[top/right/bottom/left]を指定します(初期値:bottom)。
1378         *
1379         * @og.tag
1380         * <del>horizontalBar を指定した場合は、left になります。</del>
1381         * 8.0.0.0 (2021/08/31) horizontalBar は廃止
1382         * 初期値(null)は、下(bottom)に表示されます。
1383         * <del>options:scales:xAxes の 要素の属性です。</del>
1384         * options:scales:xAxes:position → options:scales:x:position の 要素の属性です。
1385         *
1386         * @og.rev 7.0.1.2 (2018/11/04) 新規登録
1387         *
1388         * @param       pos     x軸の表示位置 [top/right/bottom/left]
1389         */
1390        public void setXposition( final String pos ) {
1391                xposition = nval( getRequestParameter( pos ),null );
1392
1393                checkPara( xposition, SET_POSITION, "position" );
1394        }
1395
1396        /**
1397         * 【TAG】x軸の最大値を指定します(xscaleTypeがlinearの場合に有効)。
1398         *
1399         * @og.tag
1400         *  options:scales:xAxes:ticks:max → options:scales:x:max の 要素の属性です。
1401         *
1402         * @og.rev 6.9.9.3 (2018/09/25) nvalを入れて、初期値を設定します。
1403         * @og.rev 7.0.1.1 (2018/10/22) JsChartDataオブジェクトを使用。
1404         *
1405         * @param       xmax    x軸の最大値
1406         */
1407        public void setXmax( final String xmax ) {
1408                jsXAxis.addAxis( "max" , nval( getRequestParameter( xmax ),null ) , NO_QUOTE );         // 数値
1409        }
1410
1411        /**
1412         * 【TAG】x軸の最小値を指定します(xscaleTypeがlinearの場合に有効)。
1413         *
1414         * @og.tag
1415         *  options:scales:xAxes:ticks:min → options:scales:x:min の 要素の属性です。
1416         *
1417         * @og.rev 6.9.9.3 (2018/09/25) nvalを入れて、初期値を設定します。
1418         * @og.rev 7.0.1.1 (2018/10/22) JsChartDataオブジェクトを使用。
1419         *
1420         * @param       xmin    x軸の最小値
1421         */
1422        public void setXmin( final String xmin ) {
1423                jsXAxis.addAxis( "min" , nval( getRequestParameter( xmin ),null ) , NO_QUOTE );         // 数値
1424        }
1425
1426        /**
1427         * 【TAG】x軸のラベルを指定します。
1428         *
1429         * @og.tag
1430         *  options:scales:xAxes:scaleLabel:labelString → options:scales:x:title:text の 要素の属性です。
1431         *
1432         * @og.rev 6.9.9.3 (2018/09/25) nvalを入れて、初期値を設定します。
1433         * @og.rev 7.0.1.1 (2018/10/22) JsChartDataオブジェクトを使用。
1434         *
1435         * @param       xlabel  x軸のラベル
1436         */
1437        public void setXlabel( final String xlabel ) {
1438                final String lbl = nval( getRequestParameter( xlabel ),null );
1439                if( lbl != null ) {
1440                        final String scLbl = "display:true,text:'" + lbl + "'" ;                // ラストの ',' は、addAxis 側で付ける。
1441                        jsXAxis.addAxis( JsChartData.TITLE , scLbl );
1442                }
1443        }
1444
1445        /**
1446         * 【TAG】x軸コールバックを指定します。
1447         *
1448         * @og.tag
1449         * x軸のメモリ編集用スケールバックを設定します。
1450         *  options:scales:xAxes:ticks:callback → options:scales:x:ticks:callback の 要素の属性です。
1451         *  callback:function(value,index,[tick objects]) {
1452         *    return '$' + value;
1453         *  }
1454         *
1455         * @og.rev 6.9.9.3 (2018/09/25) nvalを入れて、初期値を設定します。
1456         * @og.rev 7.0.1.1 (2018/10/22) JsChartDataオブジェクトを使用。
1457         *
1458         * @param       callback        x軸コールバック
1459         */
1460        public void setXscaleCallback( final String callback ) {
1461                jsXAxis.addTicks( "callback" , nval( getRequestParameter( callback ),null ) , NO_QUOTE );       // ファンクションは、クオートしない
1462        }
1463
1464        /**
1465         * 【TAG】x軸を0から書き始まるかどうか(xscaleTypeがlinearの場合に有効)(初期値:null)。
1466         *
1467         * @og.tag
1468         * options:scales:xAxes:ticks:beginAtZero → options:scales:x:beginAtZero の 要素の属性です。
1469         *
1470         * @og.rev 6.8.5.0 (2018/01/09) 新規登録
1471         * @og.rev 7.0.1.1 (2018/10/22) JsChartDataオブジェクトを使用。
1472         *
1473         * @param       xZero   x軸のゼロ開始
1474         */
1475        public void setXbeginAtZero( final String xZero ) {
1476                final String beginAtZero = nval( getRequestParameter( xZero ),null );
1477                checkPara( beginAtZero, SET_BOOLEAN, "xbeginAtZero" );
1478                jsXAxis.addAxis( "beginAtZero" , beginAtZero , NO_QUOTE );              // 数値(boolean)
1479        }
1480
1481        /**
1482         * 【TAG】x軸のメモリ幅を指定します(xscaleTypeがlinearの場合に有効)。
1483         *
1484         * @og.tag
1485         *  options:scales:xAxes:ticks:stepSize → options:scales:x:ticks:stepSize の 要素の属性です。
1486         *
1487         * @og.rev 6.9.9.3 (2018/09/25) nvalを入れて、初期値を設定します。
1488         * @og.rev 7.0.1.1 (2018/10/22) JsChartDataオブジェクトを使用。
1489         *
1490         * @param       xstepSize       x軸のメモリ幅
1491         */
1492        public void setXstepSize( final String xstepSize ) {
1493                jsXAxis.addTicks( "stepSize" , nval( getRequestParameter( xstepSize ),null ) , NO_QUOTE );      // 数値
1494        }
1495
1496        /**
1497         * 【TAG】streamingの垂直スクロールを使用するかどうか[true/false]を指定します(初期値:false)。
1498         *
1499         * @og.tag
1500         * chartjs-plugin-streaming の Vertical Scroll(垂直スクロール) を使用するときに
1501         * indexAxis="y" と useVertStrm="true" を設定します。
1502         *
1503         * false の場合、options:scales:{x:x0Ax,y:y0Ax} となります
1504         * true  の場合、options:scales:{y:x0Ax,x:y0Ax} となります
1505         *
1506         * @og.rev 8.4.0.0 (2023/01/27) useVertStrm属性追加(chartjs-plugin-streamingのVertical Scroll不具合対応)
1507         *
1508         * @param       useVstrm        streamingの垂直スクロール使用有無 [true:使用する/false:使用しない]
1509         */
1510        public void setUseVertStrm( final String useVstrm ) {
1511                useVertStrm = nval( getRequestParameter( useVstrm ),useVertStrm );
1512        }
1513
1514        /**
1515         * 【TAG】その他options:scales:xのオプションを追加します。
1516         *
1517         * @og.tag
1518         * <del>options:scales:xAxes の 要素の属性です。</del>
1519         * options:scales:xAxes → options:scales:x の 要素の属性です。
1520         *  ※ chartJS上は、Axes(axisの複数形)と、Axis を使い分けていますが、属性は、axis で統一します。
1521         *
1522         * @og.rev 7.0.1.2 (2018/11/04) 属性の追加。
1523         *
1524         * @param       attri   その他options:scales:xAxesのオプション
1525         */
1526        public void setOptAxis( final String attri ) {
1527                jsXAxis.addAxis( JsChartData.AXIS , nval( getRequestParameter( attri ),null ) );
1528        }
1529
1530        /**
1531         * 【TAG】その他options:scales:x:ticksのオプションを追加します。
1532         *
1533         * @og.tag
1534         * <del>options:scales:xAxes:ticks の 要素の属性です。</del>
1535         * options:scales:xAxes:ticks → options:scales:x:ticks の 要素の属性です。
1536         *
1537         * @og.rev 7.0.1.2 (2018/11/04) 属性の追加。
1538         *
1539         * @param       attri   その他options:scales:xAxes:ticksのオプション
1540         */
1541        public void setOptTicks( final String attri ) {
1542                jsXAxis.addAxis( JsChartData.TICKS , nval( getRequestParameter( attri ),null ) );
1543        }
1544
1545        /**
1546         * 【TAG】その他options:scales:x:titleのオプションを追加します。
1547         *
1548         * @og.tag
1549         * <del>options:scales:xAxes:scaleLabel の 要素の属性です。</del>
1550         * options:scales:xAxes:scaleLabel → options:scales:x:title の 要素の属性です。
1551         *
1552         * @og.rev 7.0.1.2 (2018/11/04) 属性の追加。
1553         *
1554         * @param       title   options:scales:x:title要素
1555         */
1556        public void setOptTitle( final String title ) {
1557                jsXAxis.addAxis( JsChartData.TITLE , nval( getRequestParameter( title ),null ) );
1558        }
1559
1560        /**
1561         * 【TAG】その他options:scales:x:gridのオプションを追加します。
1562         *
1563         * @og.tag
1564         * <del>options:scales:xAxes:gridLines の 要素の属性です。</del>
1565         *  options:scales:xAxes:gridLines → options:scales:x:grid の 要素の属性です。
1566         *
1567         * @og.rev 7.0.1.2 (2018/11/04) 属性の追加。
1568         *
1569         * @param       grid    options:scales:x:gridの属性
1570         */
1571        public void setOptGrid( final String grid ) {
1572                jsXAxis.addAxis( JsChartData.GRID , nval( getRequestParameter( grid ),null ) );
1573        }
1574
1575        // =================== options:scales:x:time: 以下の属性 =================================
1576
1577        /**
1578         * 【TAG】x軸のタイムの単位[year/quarter/month/week/day/hour/minute/second/millisecond]を指定します。
1579         *
1580         * @og.tag
1581         * (xscaleTypeがtimeの場合に有効。指定しない場合は自動)
1582         * options:scales:x:unit
1583         *
1584         * @og.rev 6.9.9.3 (2018/09/25) xscaleType の time 属性廃止。
1585         * @og.rev 6.9.9.4 (2018/10/01) nvalを入れて、属性復活。
1586         * @og.rev 7.0.1.1 (2018/10/22) JsChartDataオブジェクトを使用。
1587         *
1588         * @param       tunit   x軸のタイムの単位 [year/quarter/month/week/day/hour/minute/second/millisecond]
1589         */
1590        public void setTimeUnit( final String tunit ) {
1591                final String timeUnit = nval( getRequestParameter( tunit ),null );
1592
1593                checkPara( timeUnit, SET_TIMEUNIT, "timeUnit" );
1594
1595                jsXAxis.addTime( "unit" , timeUnit , USE_QUOTE );       // 文字列
1596        }
1597
1598        /**
1599         * 【TAG】x軸のタイムの単位幅を指定します(xscaleTypeがtimeの場合に有効)。
1600         *
1601         * @og.tag
1602         *  options:scales:x:time:unitStepSize → options:scales:x:time:stepSize の 要素の属性です。
1603         *
1604         * @og.rev 6.9.9.3 (2018/09/25) xscaleType の time 属性廃止。
1605         * @og.rev 6.9.9.4 (2018/10/01) nvalを入れて、属性復活。
1606         * @og.rev 7.0.1.1 (2018/10/22) JsChartDataオブジェクトを使用。
1607         *
1608         * @param       tunitStepSize   x軸のタイムの単位幅
1609         */
1610        public void setTimeUnitStepSize( final String tunitStepSize ) {
1611                jsXAxis.addTime( "stepSize" , nval( getRequestParameter( tunitStepSize ),null ) , NO_QUOTE );   // 数値
1612        }
1613
1614        /**
1615         * 【TAG】x軸の設定するタイム(入力データ)のフォーマットを指定します(xscaleTypeがtimeの場合に有効)。
1616         *
1617         * @og.tag
1618         * フォーマットは、chartjs-adapter-date-fns.bundle.min.js の定義を使用します。
1619         * <a href="https://github.com/chartjs/chartjs-adapter-date-fns" target="_blank" >chartjs-adapter-date-fns</a>
1620         * <a href="https://zenn.dev/snjssk/articles/f05d1bcfeb9604#format" target="_blank" >date-fns format</a>
1621         * 例:yyyyMMddHHmmss
1622         *
1623         * 8.0.0.0 (2021/08/31)
1624         *  代わりに、options:scales:x:time.parser で指定します。
1625         *
1626         * @og.rev 6.9.9.3 (2018/09/25) xscaleType の time 属性廃止。
1627         * @og.rev 6.9.9.4 (2018/10/01) nvalを入れて、属性復活。
1628         * @og.rev 7.0.1.1 (2018/10/22) JsChartDataオブジェクトを使用。
1629         * @og.rev 8.0.0.0 (2021/08/31) timeSetFormat → timeParser 変更
1630         *
1631         * @param       tFormat x軸の設定するタイムのフォーマット処理
1632         */
1633        public void setTimeParser( final String tFormat ) {
1634                jsXAxis.addTime( "parser" , nval( getRequestParameter( tFormat ),null ) , USE_QUOTE );  // 文字列
1635        }
1636
1637        /**
1638         * 【TAG】x軸の表示するタイムのフォーマットを指定します(xscaleTypeがtimeの場合に有効)。
1639         *
1640         * @og.tag
1641         * 8.0.0.0 (2021/08/31)
1642         *   Moment.js の依存関係が切れ、openGionV8では、date-fns を使用します。
1643         *  <a href="https://date-fns.org/v2.23.0/docs/format" target="_blank" >date-fns format</a>
1644         *  ※ yyyy が、YYYY になっているが、よく分からない。
1645         *
1646         * 基本形:yyyyMMddHHmmss
1647         * options:scales:x:time:displayFormats
1648         *
1649         * <table class="plain">
1650         *   <caption>タイムのフォーマット(抜粋)</caption>
1651         *       <tr><th>Pattern        </th><th>Result examples                                        </th><th>Unit                           </th></tr>
1652         *       <tr><td>yyyy           </td><td>0044, 0001, 1900, 2017                         </td><td>Calendar year          </td></tr>
1653         *       <tr><td>M                      </td><td>1, 2, ..., 12                                          </td><td>Month (formatting)     </td></tr>
1654         *       <tr><td>MM                     </td><td>01, 02, ..., 12                                        </td><td>Month (formatting)     </td></tr>
1655         *       <tr><td>MMM            </td><td>Jan, Feb, ..., Dec                                     </td><td>Month (formatting)     </td></tr>
1656         *       <tr><td>MMMM           </td><td>January, February, ..., December       </td><td>Month (formatting)     </td></tr>
1657         *       <tr><td>d                      </td><td>1, 2, ..., 31                                          </td><td>Day of month           </td></tr>
1658         *       <tr><td>dd                     </td><td>01, 02, ..., 31                                        </td><td>Day of month           </td></tr>
1659         *       <tr><td>H                      </td><td>0, 1, 2, ..., 23                                       </td><td>Hour [0-23]            </td></tr>
1660         *       <tr><td>HH                     </td><td>00, 01, 02, ..., 23                            </td><td>                                       </td></tr>
1661         *       <tr><td>m                      </td><td>0, 1, ..., 59                                          </td><td>Minute                         </td></tr>
1662         *       <tr><td>mm                     </td><td>00, 01, ..., 59                                        </td><td>                                       </td></tr>
1663         *       <tr><td>s                      </td><td>0, 1, ..., 59                                          </td><td>Second                         </td></tr>
1664         *       <tr><td>ss                     </td><td>00, 01, ..., 59                                        </td><td>                                       </td></tr>
1665         *       <tr><td>S                      </td><td>0, 1, ..., 9                                           </td><td>Fraction of second     </td></tr>
1666         *       <tr><td>SS                     </td><td>00, 01, ..., 99                                        </td><td>                                       </td></tr>
1667         *       <tr><td>SSS            </td><td>000, 001, ..., 999                                     </td><td>                                       </td></tr>
1668         * </table>
1669         *
1670         * timeLblFormatが指定されている場合、全てのdisplayFormatsにtimeLblFormatを設定する
1671         *
1672         * @og.rev 6.9.9.3 (2018/09/25) xscaleType の time 属性廃止。
1673         * @og.rev 6.9.9.4 (2018/10/01) nvalを入れて、属性復活。
1674         * @og.rev 7.0.1.1 (2018/10/22) JsChartDataオブジェクトを使用。
1675         *
1676         * @param       tLblFormat      x軸の表示するタイムのフォーマット
1677         * @see         #setTimeParser(String)
1678         */
1679        public void setTimeLblFormat( final String tLblFormat ) {
1680                final String timeFmt = nval( getRequestParameter( tLblFormat ),null );
1681                if( timeFmt != null ) {
1682                        final StringBuilder buf = new StringBuilder( BUFFER_MIDDLE )
1683                                        .append(  "{year:'"             ).append( timeFmt )
1684                                        .append( "',quarter:'"  ).append( timeFmt )
1685                                        .append( "',month:'"    ).append( timeFmt )
1686                                        .append( "',week:'"             ).append( timeFmt )
1687                                        .append( "',day:'"              ).append( timeFmt )
1688                                        .append( "',hour:'"             ).append( timeFmt )
1689                                        .append( "',minute:'"   ).append( timeFmt )
1690                                        .append( "',second:'"   ).append( timeFmt )
1691                                        .append( "'}" );
1692
1693                        jsXAxis.addTime( "displayFormats" , buf.toString() , NO_QUOTE );        // オブジェクトなので、クオートなし
1694                }
1695        }
1696
1697        /**
1698         * 【TAG】x軸の時間のツールチップに使用するフォーマット(タイムスケール用)を指定します(xscaleTypeがtimeの場合に有効)。
1699         *
1700         * @og.tag
1701         * 8.0.0.0 (2021/08/31)
1702         *   Moment.js の依存関係が切れ、openGionV8では、date-fns を使用します。
1703         *  <a href="https://date-fns.org/v2.23.0/docs/format" target="_blank" >date-fns format</a>
1704         *
1705         * 基本形:yyyyMMddHHmmss
1706         * options:scales:x:time:tooltipFormat
1707         *
1708         * フォーマットは、timeLblFormat (内部的には、time:displayFormats)と同じ
1709         *
1710         * @og.rev 7.0.1.0 (2018/10/15) 時間のツールチップに使用するフォーマット(タイムスケール用)
1711         * @og.rev 7.0.1.1 (2018/10/22) JsChartDataオブジェクトを使用。
1712         *
1713         * @param       tipFormat       x軸の表示するタイムのフォーマット
1714         * @see         #setTimeParser(String)
1715         */
1716        public void setTooltipFormat( final String tipFormat ) {
1717                jsXAxis.addTime( "tooltipFormat" , nval( getRequestParameter( tipFormat ),null ) , USE_QUOTE ); // 文字列
1718        }
1719
1720        // =================== options:plugins: 以下の属性 =================================
1721
1722        /**
1723         * 【TAG】タイトル、またはタイトル要素を指定します。
1724         *
1725         * @og.tag
1726         * options:title:text → options:plugins:title:text の 要素の属性です。
1727         * "タイトル" または "{display:true,text:'タイトル',color:'blue',font:{size:15},}" 形式で指定します。
1728         * options:plugins:titleの属性に、その他オプションを追加するのと同じ動きになります。
1729         * 判定方法は、先頭に 『{』が存在するかどうかです。
1730         * タイトルに配列を渡すと、改行表示します。
1731         * ['タイトル','改行','するのか?'] の形式なので、先頭に 『[』が存在するか判定します。
1732         *
1733         * <pre>
1734         *   display:true/false,   初期値:false
1735         *   text   :チャートタイトル(string |,string[])
1736         *   color  :タイトルの色
1737         *   font   :{ family:フォント,size:サイズ,style:スタイル,weight:太さ,lineHeight:1行の高さ }
1738         *   padding:パディング
1739         *   align  :表示位置。'start'(開始側), 'center'(中央), 'end'(終了側)のいずれか。デフォルトは 'center'
1740         *   position:表示位置。'top'(上部), 'left'(左側), 'bottom'(下部), 'right'(右側)のいずれか。デフォルトは 'top'
1741         *   fullSize:フルサイズで表示するか否か。デフォルトは true
1742         *
1743         * </pre>
1744         *
1745         * @og.rev 6.9.9.3 (2018/09/25) nvalを入れて、初期値を設定します。
1746         * @og.rev 8.0.0.0 (2021/09/30) タイトル要素も指定できるように変更
1747         *
1748         * @param       title   タイトル
1749         */
1750        public void setTitle( final String title ) {
1751                this.title = nval( getRequestParameter( title ),this.title );
1752        }
1753
1754        /**
1755         * 【TAG】タイトルの表示位置[top/right/bottom/left]を指定します(初期値:top)。
1756         *
1757         * @og.tag
1758         *  options:title:position → options:plugins:title:position の 要素の属性です。
1759         * title 属性に、タイトル要素({…}書式)を設定した場合は、positionは無効です。
1760         *
1761         * <a href="https://www.tohoho-web.com/ex/chartjs-params.html#title" target="_blank" >とほほ → チャートタイトル </a>
1762         *
1763         * @og.rev 6.9.9.3 (2018/09/25) nvalを入れて、初期値を設定します。
1764         *
1765         * @param       position        タイトルの表示位置 [top/right/bottom/left]
1766         */
1767        public void setTitlePosition( final String position ) {
1768                titlePosition = nval( getRequestParameter( position ),titlePosition );
1769
1770                checkPara( titlePosition, SET_POSITION, "titlePosition" );
1771        }
1772
1773        /**
1774         * 【TAG】凡例を表示するか[true/false]を指定します。
1775         *
1776         * @og.tag
1777         * options:legend:display → options:plugins:legend:display の 要素の属性です。
1778         *
1779         * @og.rev 6.9.9.3 (2018/09/25) nvalを入れて、初期値を設定します。
1780         *
1781         * @param       display 凡例を表示するか [true/false]
1782         */
1783        public void setLegendDisplay( final String display ) {
1784                legendDisplay = nval( getRequestParameter( display ),legendDisplay );
1785
1786                if( legendDisplay != null ) {
1787                        checkPara( legendDisplay, SET_BOOLEAN, "legendDisplay" );
1788                        useLegend = true;
1789                }
1790        }
1791
1792        /**
1793         * 【TAG】凡例の表示位置[top/right/bottom/left]を指定します(初期値:top)。
1794         *
1795         * @og.tag
1796         *  options:legend:position → options:plugins:legend:position の 要素の属性です。
1797         *
1798         * @og.rev 6.9.9.3 (2018/09/25) nvalを入れて、初期値を設定します。
1799         *
1800         * @param       position        凡例の表示位置 [top/right/bottom/left]
1801         */
1802        public void setLegendPosition( final String position ) {
1803                legendPosition = nval( getRequestParameter( position ),legendPosition );
1804
1805                if( legendPosition != null ) {
1806                        checkPara( legendPosition, SET_POSITION, "legendPosition" );
1807                        useLegend = true;
1808                }
1809        }
1810
1811        /**
1812         * 【TAG】凡例のスタイル属性を使用するかどうか[true/false]を指定します(初期値:false)。
1813         *
1814         * @og.tag
1815         * 凡例のスタイルを、jsChartDataタグのpointStyle属性で指定した形状に変更します。
1816         * 複数データの場合、片方だけ指定したい場合は、usePointStyle="true" にしておき、
1817         * 指定したいほうだけ、jsChartDataタグ側で、pointStyle属性を設定してください。
1818         * <del>options:legend:labels属性のusePointStyle です。</del>
1819         * options:legend:labels:usePointStyle → options:plugins:legend:labels:usePointStyle の 要素の属性です。
1820         *
1821         * @og.rev 6.8.5.0 (2018/01/09) 新規登録
1822         *
1823         * @param       usePstyle       凡例のスタイル属性を使用するかどうか [true:使用する/false:使用しない]
1824         */
1825        public void setUsePointStyle( final String usePstyle ) {
1826                final String useStyle = nval( getRequestParameter( usePstyle ),null );
1827
1828                if( useStyle != null ) {
1829                        usePointStyle = Boolean.parseBoolean( useStyle );
1830                        useLegend = true;               // パラメータの設定が行われた場合のみ、設定します。
1831                }
1832        }
1833
1834        /**
1835         * 【TAG】options:pluginsの要素に、その他オプションを追加します。
1836         *
1837         * @og.tag
1838         * options:pluginsの要素に、その他オプションを追加します
1839         * 指定する際の、前後の『{}』は、不要です。
1840         * plugins には、legend(凡例),title(タイトル),tooltip(ツールチップ),decimation(間引き),filler(塗りつぶし)
1841         * の属性を指定できるが、元々のこれらを単独で設定できる属性も持っており、
1842         * データ的にはマージされますが、同じキーを指定した場合にどのような動きになるかは保証できません。
1843         *
1844         * <a href="https://www.tohoho-web.com/ex/chartjs-params.html#plugins" target="_blank" >とほほ → プラグイン </a>
1845         *
1846         * @og.rev 8.0.0.0 (2021/09/30) 新規追加
1847         *
1848         * @param       attri   plugins要素
1849         */
1850        public void setOptPlugins( final String attri ) {
1851                optPlugins = nval( getRequestParameter( attri ),null );
1852        }
1853
1854        /**
1855         * 【TAG】options:plugins:tooltipの要素に、その他オプションを追加します。
1856         *
1857         * @og.tag
1858         * options:plugins:tooltipの属性に、その他オプションを追加します
1859         * 指定する際の、前後の『{}』は、不要です。
1860         * tooltip には、多数の要素が設定可能なので、外部で定義したオブジェクトを
1861         * 指定するのが良いと思います。
1862         *
1863         * <a href="https://www.tohoho-web.com/ex/chartjs-params.html#tooltip" target="_blank" >とほほ → ツールチップ </a>
1864         *
1865         * @og.rev 8.0.0.0 (2021/09/30) 新規追加
1866         *
1867         * @param       attri   tooltip要素
1868         */
1869        public void setOptTooltip( final String attri ) {
1870                optTooltip = nval( getRequestParameter( attri ),null );
1871        }
1872
1873        /**
1874         * 【TAG】options:plugins:legendの要素に、その他オプションを追加します。
1875         *
1876         * @og.tag
1877         * options:plugins:legendの属性に、その他オプションを追加します
1878         * 指定する際の、前後の『{}』は、不要です。
1879         * legend には、多数の要素が設定可能なので、外部で定義したオブジェクトを
1880         * 指定するのが良いと思います。
1881         *
1882         * legend 関係の属性として、legendDisplay、legendPosition、usePointStyle を定義しています。
1883         * optLegend属性を設定した場合、これらの属性とマージされるため、同じキーワードが存在した場合の
1884         * 動作は、不明です。
1885         *
1886         * <a href="https://www.tohoho-web.com/ex/chartjs-params.html#legend" target="_blank" >とほほ → 凡例(レジェンド) </a>
1887         *
1888         * @og.rev 8.0.0.0 (2021/09/30) 新規追加
1889         *
1890         * @param       attri   legend要素
1891         */
1892        public void setOptLegend( final String attri ) {
1893                optLegend = nval( getRequestParameter( attri ),null );
1894                if( optLegend != null ) {
1895                        useLegend = true;
1896                }
1897        }
1898
1899        // =================== options:plugins:annotation:annotations: 以下の属性 ==========
1900
1901        /**
1902         * 【TAG】y軸に横マーカーラインの設定値をCSV形式で複数指定します。
1903         *
1904         * @og.tag
1905         * X軸に平行に固定値の線を引きます。線の値を、CSV形式で指定します。
1906         * annotation:annotations オプションに名前付きで設定した中に yMin,yMax を定義します。
1907         * 以前は、value に値をセットしていましたが、,yMin:値,yMax:値 にセットします。
1908         *
1909         * 8.0.0.0 (2021/08/31)
1910         *      chartjs-plugin-annotation を使用します。
1911         *      配列ではなく、名前付きの設定になります。(下記の例では、ymark0:)
1912         *  options::plugins:annotation:annotations:ymark0:{
1913         *      type:'line',                    ← 固定です。
1914         *      borderWidth:2,                  ← markWidthの値(ライン共通 初期値="2")
1915         *      borderDash:[5,2],               ← markDashの値(ライン共通  初期値=null)
1916         *      yMin:値,yMax:値,                ← markValuesの値
1917         *      borderColor: '#FF0000',         ← markColorsの値
1918         *      label:{
1919         *          enabled:'true',position:'start',    ← 固定です。
1920         *          backgroundColor:'rgba(0,0,0,0)',    ← 固定です。
1921         *          font:{ size:10 },                   ← markFontSizeの値(ライン共通  初期値=10)
1922         *          content:'基準値',       ← markLblsの値
1923         *          yAdjust:-6,             ← markAdjustの値
1924         *          color:'#FF0000',        ← markColorsの値
1925         *          … ,
1926         *      },
1927         *  },
1928         *
1929         * @og.rev 6.8.5.0 (2018/01/09) 新規登録
1930         * @og.rev 8.0.0.0 (2021/08/31) chartJs V3 で大きく変更されています。
1931         *
1932         * @param       mkVals  y軸に横マーカーラインの設定値(CSV形式)
1933         */
1934        public void setMarkValues( final String mkVals ) {
1935                markValues = nval( getRequestParameter( mkVals ) , markValues );
1936        }
1937
1938        /**
1939         * 【TAG】y軸に横マーカーラインの色をCSV形式で複数指定します。
1940         *
1941         * @og.tag
1942         * annotation:annotations オプションに名前付きで設定した中に borderColor を定義します。
1943         *
1944         * X軸に平行に固定値の線を引きます。線の色を、CSV形式で指定します。
1945         * markValues が指定されており、markColorsが指定されていない場合は、青色(BLUE)になります。
1946         * 色指定に、VIVID,PASTEL を使えるようにします。
1947         *
1948         * 詳細は、markValues の説明をご確認願います。
1949         *
1950         * @og.rev 6.8.5.0 (2018/01/09) 新規登録
1951         * @og.rev 7.0.1.3 (2018/11/12) 色指定に、VIVID,PASTEL を使えるようにします。
1952         *
1953         * @param       mkCols  y軸に横マーカーラインの色(CSV形式)
1954         * @see #setMarkValues(String)
1955         */
1956        public void setMarkColors( final String mkCols ) {
1957                markColors = nval( getRequestParameter( mkCols ) , markColors );
1958        }
1959
1960        /**
1961         * 【TAG】y軸に横マーカーラインのラベルをCSV形式で複数指定します。
1962         *
1963         * @og.tag
1964         * annotation:annotations オプションに名前付きで設定した中に
1965         * label:content を定義します。
1966         *
1967         * label 属性の enabled:'true',position:'start',backgroundColor:'rgba(0,0,0,0)',
1968         * font:{ size:10 } は固定で、color は、markColors 属性で指定した
1969         * y軸に横マーカーラインの色を使用します。
1970         * 色指定に、VIVID,PASTEL を使えるようにします。
1971         *
1972         * 詳細は、markValues の説明をご確認願います。
1973         *
1974         * @og.rev 6.8.5.0 (2018/01/09) 新規登録
1975         *
1976         * @param       mklbls  y軸に横マーカーラインのラベル(CSV形式)
1977         * @see #setMarkValues(String)
1978         */
1979        public void setMarkLbls( final String mklbls ) {
1980                markLbls = nval( getRequestParameter( mklbls ) , markLbls );
1981        }
1982
1983        /**
1984         * 【TAG】y軸に横マーカーラインのラベル表示位置の上下方向を調整します(初期値:-6)。
1985         *
1986         * @og.tag
1987         * annotation:annotations オプションに名前付きで設定した中に
1988         * label:yAdjust を定義します。
1989         *
1990         * これは、ラインに対するラベルの位置を表します。+で、下側、-で上側に表示します。
1991         * 初期値は、-6 で、ラインの上側に来るように調整しています。
1992         *
1993         * 詳細は、markValues の説明をご確認願います。
1994         *
1995         * @og.rev 6.8.5.0 (2018/01/09) 新規登録
1996         *
1997         * @param       mkAjst  y軸に横マーカーラインのラベル表示位置の上下方向調整
1998         * @see #setMarkValues(String)
1999         */
2000        public void setMarkAdjust( final String mkAjst ) {
2001                markAdjust = nval( getRequestParameter( mkAjst ) , markAdjust );
2002        }
2003
2004        /**
2005         * 【TAG】x軸に横マーカーラインのラベルをCSV形式で複数指定します。
2006         *
2007         * @og.tag
2008         * annotation:annotations オプションに名前付きで設定した中に
2009         * label:content を定義します。
2010         *
2011         * label 属性の enabled:'true',position:'end',backgroundColor:'white',
2012         * font:{ size:10 } は固定で、color は、markColors 属性で指定した
2013         * x軸に横マーカーラインの色を使用します。
2014         * 色指定に、VIVID,PASTEL を使えるようにします。
2015         *
2016         * 詳細は、xmarkValues の説明をご確認願います。
2017         *
2018         * @og.rev 8.0.0.0 (2021/09/30) 新規追加
2019         *
2020         * @param       mklbls  x軸に横マーカーラインのラベル(CSV形式)
2021         * @see #setMarkValues(String)
2022         */
2023        public void setXmarkLbls( final String mklbls ) {
2024                xmarkLbls = nval( getRequestParameter( mklbls ) , xmarkLbls );
2025        }
2026
2027        /**
2028         * 【TAG】x軸に縦マーカーラインの設定値をCSV形式で複数指定します。
2029         *
2030         * @og.tag
2031         * annotation:annotations オプションに名前付きで設定した中に xMin,xMax を定義します。
2032         *
2033         * Y軸に平行に固定値の縦線を引きます。線の値を、CSV形式で指定します。
2034         * 以前は、value に値をセットしていましたが、,xMin:値,xMax:値 にセットします。
2035         *
2036         * type:'line',borderWidth:2,scaleID:'x0Ax', 固定です。
2037         *      chartjs-plugin-annotation を使用します。
2038         *      配列ではなく、名前付きの設定になります。(下記の例では、xmark0:)
2039         *
2040         *  options:plugins:annotation:annotations:xmark0:{
2041         *      type:'line',                    ← 固定です。
2042         *      borderWidth:2,                  ← markWidthの値(ライン共通 初期値="2")
2043         *      borderDash:[5,2],               ← markDashの値(ライン共通  初期値=null)
2044         *      xMin:値,xMax:値,                ← xmarkValuesの値
2045         *      borderColor:'#FF0000',          ← xmarkColorsの値
2046         *  },
2047         *
2048         * @og.rev 7.0.1.1 (2018/10/22) xmarkValues,xmarkColors属性の追加
2049         *
2050         * @param       mkVals  x軸に縦マーカーラインの設定値(CSV形式)
2051         * @see #setMarkValues(String)
2052         */
2053        public void setXmarkValues( final String mkVals ) {
2054                xmarkValues = nval( getRequestParameter( mkVals ) , xmarkValues );
2055        }
2056
2057        /**
2058         * 【TAG】x軸に縦マーカーラインの色をCSV形式で複数指定します。
2059         *
2060         * @og.tag
2061         * annotation:annotations オプションに名前付きで設定した中に borderColor を定義します。
2062         *
2063         * Y軸に平行に固定値の縦線を引きます。線の色を、CSV形式で指定します。
2064         * xmarkValues が指定されており、xmarkColorsが指定されていない場合は、青色(BLUE)になります。
2065         *
2066         * @og.rev 7.0.1.1 (2018/10/22) xmarkValues,xmarkColors属性の追加
2067         * @og.rev 7.0.1.3 (2018/11/12) 色指定に、VIVID,PASTEL を使えるようにします。
2068         *
2069         * @param       mkCols  x軸に縦マーカーラインの色(CSV形式)
2070         * @see #setXmarkValues(String)
2071         */
2072        public void setXmarkColors( final String mkCols ) {
2073                xmarkColors = nval( getRequestParameter( mkCols ) , xmarkColors );
2074        }
2075
2076        /**
2077         * 【TAG】x軸,y軸全マーカーライン共通のラインの幅を指定します:borderWidth(初期値:2)。
2078         *
2079         * @og.tag
2080         * annotation:annotations オプションに名前付きで設定した中に borderWidth を定義します。
2081         *
2082         * この値は、x軸,y軸関係なく、マーカーラインの順番も関係なく、共通設定になります。
2083         *
2084         * @og.rev 7.0.1.1 (2018/10/22) markWidth,markDash,markFontSize属性の追加
2085         *
2086         * @param       width   マーカーライン共通のラインの幅
2087         * @see #setMarkValues(String)
2088         */
2089        public void setMarkWidth( final String width ) {
2090                markWidth = nval( getRequestParameter( width ) , markWidth );
2091        }
2092
2093        /**
2094         * 【TAG】x軸,y軸全マーカーライン共通のラインに点線を指定([5,2]など)します:borderDash(初期値:null)。
2095         *
2096         * @og.tag
2097         * annotation:annotations オプションに名前付きで設定した中に borderDash を定義します。
2098         *
2099         * この値は、x軸,y軸関係なく、マーカーラインの順番も関係なく、共通設定になります。
2100         * markDash="[5,2]" とすれば、線の長さが5px , 線と線の間が2px になります。
2101         *
2102         * @og.rev 7.0.1.1 (2018/10/22) markWidth,markDash,markFontSize属性の追加
2103         *
2104         * @param       dash    マーカーライン共通のラインの点線の形状
2105         * @see #setMarkValues(String)
2106         */
2107        public void setMarkDash( final String dash ) {
2108                markDash = nval( getRequestParameter( dash ) , markDash );
2109        }
2110
2111        /**
2112         * 【TAG】x軸,y軸全マーカーライン共通のラベルのフォントサイズを指定します:label:font:size(初期値:10)。
2113         *
2114         * @og.tag
2115         * annotation:annotations オプションに名前付きで設定した中に
2116         * label:font:size を定義します。
2117         *
2118         * この値は、x軸,y軸関係なく、マーカーラインの順番も関係なく、共通設定になります。
2119         *
2120         * @og.rev 7.0.1.1 (2018/10/22) markWidth,markDash,markFontSize属性の追加
2121         *
2122         * @param       size    マーカーライン共通のフォントサイズ
2123         * @see #setMarkValues(String)
2124         */
2125        public void setMarkFontSize( final String size ) {
2126                markFontSize = nval( getRequestParameter( size ) , markFontSize );
2127        }
2128
2129        // =================== options:plugins:zoom: 以下の属性 ==================================
2130
2131        /**
2132         * 【TAG】WheelZoom処理を使用するかどうか[true/false]を指定します(初期値:false)。
2133         *
2134         * @og.tag
2135         * plugins:zoom に、zoom:{wheel,pinch} と pan を定義します。(chartJs V3 の変更点)
2136         * これは、chartjs-plugin-zoom.js を使用します。
2137         * マウスホイールで、zoom処理、右クリックで移動(pan)します。
2138         * ダブルクリックで元の状態に戻します。
2139         * useDragZoom と同時指定した場合は、useZoom が優先されます。
2140         *
2141         * 初期値は、false:使用しないです。
2142         *
2143         * <ul>
2144         *   <li>zoom:{mode:'xy',wheel:{enabled:true,},pinch:{enabled:true,},},</li>
2145         *   <li>pan:{mode:'xy',enabled:true,},</li>
2146         *   <li>canvasをクリックでzoomリセット   </li>
2147         * </ul>
2148         *
2149         *  options:plugins:zoom:{
2150         *      zoom:{mode:'xy',wheel:{enabled:true,},pinch:{enabled:true,},},
2151         *      pan:{mode:'xy',enabled:true,},
2152         *  },
2153         *
2154         * @og.rev 6.8.5.0 (2018/01/09) 新規登録
2155         *
2156         * @param       flag    WheelZoom処理を使用するかどうか [true:使用する/false:使用しない]。
2157         */
2158        public void setUseZoom( final String flag ) {
2159                useZoom = nval( getRequestParameter( flag ) , useZoom );
2160        }
2161
2162        /**
2163         * 【TAG】DragZoom処理を使用するかどうか[true/false]を指定します(初期値:false)。
2164         *
2165         * @og.tag
2166         * plugins:zoom に zoom:{drag} と pan:{modifierKey: 'ctrl',} を定義します。(chartJs V3 の変更点)
2167         * これは、chartjs-plugin-zoom.js を使用します。
2168         * 右クリックで範囲指定で、zoom処理、CTRLボタンを押しながら、右クリックで移動(pan)します。
2169         * ダブルクリックで元の状態に戻します。
2170         * useDragZoom と同時指定した場合は、useZoom が優先されます。
2171         *
2172         * 初期値は、false:使用しないです。
2173         *
2174         * <ul>
2175         *   <li>zoom:{drag:{enabled:true,borderColor:'rgb(54,162,235)',borderWidth:1,backgroundColor:'rgba(54,162,235,0.3)'},},</li>
2176         *   <li>pan:{mode:'xy',enabled:true,modifierKey: 'ctrl',},</li>
2177         *   <li>canvasをクリックでzoomリセット   </li>
2178         * </ul>
2179         *
2180         *  options:plugins:zoom:{
2181         *      zoom:{drag:{enabled:true,borderColor:'rgb(54,162,235)',borderWidth:1,backgroundColor:'rgba(54,162,235,0.3)'},},
2182         *      pan:{mode:'xy',enabled:true,modifierKey: 'ctrl',},
2183         *  },
2184         *
2185         * @og.rev 6.8.5.0 (2018/01/09) 新規登録
2186         *
2187         * @param       flag    DragZoom処理を使用するかどうか [true:使用する/false:使用しない]。
2188         */
2189        public void setUseDragZoom( final String flag ) {
2190                useDragZoom = nval( getRequestParameter( flag ) , useDragZoom );
2191        }
2192
2193        //========================================================================================
2194
2195        /**
2196         * 【TAG】すべてのデータが0の場合、使用しないかどうか[true:除外する/false:除外しない]を指定します(初期値:false)。
2197         *
2198         * @og.tag
2199         * JSON データを作成して、JsChartに渡しますが、このフラグを true に設定すると
2200         * 0 または、null(空文字列)のデータを出力しません。 6.8.3.0 (2017/11/27)
2201         * グラフ系で、0 が、ありえない値として設定されている場合に、使用すると、
2202         * 出力するデータ量を抑えることが出来ます。
2203         *
2204         * @og.rev 6.7.7.0 (2017/03/31) useZeroDataOmit属性の追加
2205         *
2206         * @param       useZeroOmit     データが0の場合の使用可否 [true:除外する/false:除外しない]
2207         */
2208        public void setUseZeroDataOmit( final String useZeroOmit ) {
2209                useZeroDataOmit = nval( getRequestParameter( useZeroOmit ) , useZeroDataOmit );
2210        }
2211
2212        /**
2213         * 【TAG】JSON出力で、値出力にレンデラを利用するかどうか[true/false]を指定します(初期値:false)。
2214         *
2215         * @og.tag
2216         * JSONのデータのレンデラー変換を行うかどうか。
2217         * 数値部分にはレンデラー変換は行いません。ラベル文字に行います。
2218         * 指定しない場合は使用しない(false)です。
2219         *
2220         * @og.rev 6.7.9.0 (2017/04/28) useRenderer 追加
2221         *
2222         * @param       usernd  レンデラーを利用するかどうか [true/false]
2223         */
2224        public void setUseRenderer( final String usernd ) {
2225                useRenderer = nval( getRequestParameter( usernd ) , useRenderer );
2226        }
2227
2228        /**
2229         * 【TAG】検索結果をこのカラムでソートし直します(初期値:null)。
2230         *
2231         * @og.tag
2232         * query で検索した結果を、JsChartで利用する場合、チャート上のソート順と、
2233         * リストや、別のチャートでの表示準が異なる場合に、このカラムで、ソートしなおします。
2234         * 通常は、labelColumn と同じ値でソートすることで、X軸の順番に表示されます。
2235         *
2236         * @og.rev 6.8.0.0 (2017/06/02) sortColumn 追加
2237         *
2238         * @param       sortClm このカラムでソートし直す
2239         */
2240        public void setSortColumn( final String sortClm ) {
2241                sortColumn = nval( getRequestParameter( sortClm ) , sortColumn );
2242        }
2243
2244        /**
2245         * 【TAG】値の前後にクオートをはさむかどうか[true/false]指定します(初期値:false)。
2246         *
2247         * @og.tag
2248         * 以前は、yscaleType="category" のときに、値が、文字列のため、クオートで囲う判断をしていました。
2249         * その属性は、JsChartDataTag に移ったため、新たなパラメータを用意します。
2250         * 将来的に、自動判定にするか、JsChartDataTag から情報を取得するかもしれません。
2251         *
2252         * @og.rev 7.0.1.1 (2018/10/22) 新規登録
2253         *
2254         * @param       flag    値の前後にクオートをはさむかどうか [true/false]
2255         */
2256        public void setValueQuot( final String flag ) {
2257                valueQuot = nval( getRequestParameter( flag ),valueQuot );
2258        }
2259
2260        /**
2261         * 【TAG】TableModelの指定のカラム(CSV形式)をconstの配列変数として出力します。
2262         *
2263         * @og.tag
2264         * これは、指定のカラムのデータをJavaScriptのconst変数定義で配列として出力します。
2265         * labelColumn や、JsChartDataTag の chartColumn と同じ方法です。
2266         *
2267         * 例えば、TableModelを、sortColumn でソートすると、JsChartDataTag の pointBGColor
2268         * の配列順も変わりますので、ソートされた状態で出力したいことがあると思います。
2269         *
2270         * 8.0.0.0 (2021/08/31)
2271         *  chartTypeが、bubble の場合、
2272         *    x:は、jsChartData の chartColumn
2273         *    y:は、varColumns で指定した1番目のカラム
2274         *    r:は、varColumns で指定した2番目のカラム
2275         *  scatter の場合は、y:の1番目のカラムのみ使用します。
2276         *
2277         * @og.rev 7.0.1.2 (2018/11/04) 新規登録
2278         * @og.rev 8.0.0.0 (2021/08/31) BUBBLEとSCATTERの追加
2279         *
2280         * @param       clms    指定のカラム(CSV形式)をconstの配列変数として出力
2281         */
2282        public void setVarColumns( final String clms ) {
2283                varColumns = nval( getRequestParameter( clms ) , varColumns );
2284        }
2285
2286//      /**
2287//       * 【TAG】const定義するJavaScript変数に使用できるかどうか[true/false]指定します。
2288//       *
2289//       * @og.tag
2290//       * const定義するJavaScript変数に使用できる文字は、決まっています。
2291//       *
2292//       * 1文字目は数字と、特殊記号(アンダーバー(_)、ドル記号($)を除く)、をチェックします。
2293//       * 厳密には、予約文字が使えなかったりするが、簡易チェックとする。
2294//       * 前後の空白文字は除外、それ以外の特殊記号は、アンダーバー(_)に変換します。
2295//       * 初期値[false]
2296//       *
2297//       * @og.rev 8.0.0.0 (2021/09/30) 新規登録
2298//       *
2299//       * @param       flag    JavaScript変数に使用できるかどうか[true/false]指定
2300//       */
2301//      public void setUseVarCheck( final String flag ) {
2302//              useVarCheck = nval( getRequestParameter( flag ) , useVarCheck );
2303//      }
2304
2305        //========================================================================================
2306
2307        /**
2308         * 【TAG】(通常は使いません)sessionから所得する DBTableModelオブジェクトの ID。
2309         *
2310         * @og.tag
2311         * (通常は使いません)sessionから所得する DBTableModelオブジェクトの ID。
2312         *
2313         * @og.rev 6.9.9.3 (2018/09/25) nvalを入れて、初期値を設定します。
2314         *
2315         * @param       tableId テーブルID
2316         */
2317        public void setTableId( final String tableId ) {
2318                this.tableId = nval( getRequestParameter( tableId ) , this.tableId );
2319        }
2320
2321        /**
2322         * このオブジェクトの文字列表現を返します。
2323         * 基本的にデバッグ目的に使用します。
2324         *
2325         * @return      このクラスの文字列表現
2326         */
2327        @Override
2328        public String toString() {
2329                final StringBuilder buf = new StringBuilder( BUFFER_MIDDLE )
2330                                .append( "X_AXIS=" ).append( jsXAxis ).append( CR );
2331
2332                jsChartData.forEach( js -> buf.append( "Y_AXIS=" ).append( jsXAxis ).append( CR ) );
2333
2334                return ToString.title( this.getClass().getName() )
2335                        .println( "VERSION"                             , VERSION                               )
2336                        .println( "id"                                  , id                                    )
2337                        .println( "tableId"                             , tableId                               )
2338                        .println( "chartType"                   , chartType                             )
2339                        .println( "width"                               , width                                 )
2340                        .println( "height"                              , height                                )
2341                        .println( "barWidthPer"                 , barWidthPer                   )
2342                        .println( "title"                               , title                                 )
2343                        .println( "titlePosition"               , titlePosition                 )
2344                        .println( "legendPosition"              , legendPosition                )
2345                        .println( "legendDisplay"               , legendDisplay                 )
2346                        .println( "xscaleType"                  , xscaleType                    )
2347                        .println( "optOptions"                  , optOptions                    )       // 7.0.1.2 (2018/11/04)
2348//                      .println( "optChart"                    , optChart                              )       // 7.0.1.2 (2018/11/04)
2349                        .fixForm().println()
2350                        .println( buf ).toString();
2351        }
2352}