📑

WebFOCUSのHTML5拡張グラフを開発する

2025/02/20に公開

拡張グラフを開発する

WebFOCUSのHTML5拡張グラフを自作しようと思いますが、自分で作ると言ってもゼロから書くのは厳しいので軽量の単純棒グラフをコピーして中身を読み取っていきます。

拡張機能フォルダをコピー

C:\ibi\WebFOCUS93\config\web_resource\extensions\com.ibi.simple_bar

フォルダを複製して

C:\ibi\WebFOCUS93\config\web_resource\extensions\com.shimokado.sample

フォルダを作成

※ フォルダ名は、com.会社名.機能名

不要なファイルを削除

不要なファイルを削除して最小限の構成にします。

C:\ibi\WebFOCUS93\config\web_resource\extensions\com.shimokado.sample

フォルダの中のcom.ibi.simple_bar.zipを削除します。

複製した機能が動作するように編集

このままでは、フォルダ名と実体が合っていないので複製した機能が動作するようにします。

com.ibi.simple_bar.jsをcom.shimokado.sample.jsにリネーム

com.shimokado.sample.jsの278行目、config.idの値を変更します。

com.shimokado.sample.js 278行目付近
	var config = {
		id: 'com.shimokado.sample',     // string that uniquely identifies this extension

複製した機能をアクティブにする

"C:\ibi\WebFOCUS93\config\web_resource\extensions\html5chart_extensions.json"を編集して、複製した機能を利用できるようにします。

html5chart_extensions.json
{
  "com.ibi.arc": { "enabled": false },
  "com.ibi.calendar": { "enabled": false },
  "com.ibi.calendar_traditional": { "enabled": false },
  "com.ibi.cartogram": { "enabled": false },
  "com.ibi.chord": { "enabled": false },
  "com.ibi.cluster": { "enabled": false },
  "com.ibi.compare_2_bars": { "enabled": false },
  "com.ibi.corona": { "enabled": false },
  "com.ibi.datatables": { "enabled": false },
  "com.ibi.dendrorag": { "enabled": false },
  "com.ibi.divergent": { "enabled": false },
  "com.ibi.dygraph": { "enabled": false },
  "com.ibi.forcedirected": { "enabled": false },
  "com.ibi.forcenetwork": { "enabled": false },
  "com.ibi.gantt": { "enabled": false },
  "com.ibi.gauge": { "enabled": false },
  "com.ibi.hexbinscatter": { "enabled": false },
  "com.ibi.histogram": { "enabled": false },
  "com.ibi.horizontal_comparison_bars": { "enabled": false },
  "com.ibi.kpibox": { "enabled": false },
  "com.ibi.kpiboxcustomcurrency": { "enabled": false },
  "com.ibi.kpi_distribution": { "enabled": false },
  "com.ibi.kpi_distribution_comparison": { "enabled": false },
  "com.ibi.kpi.sparkline": { "enabled": false },
  "com.ibi.kpi.sparkline2": { "enabled": false },
  "com.ibi.kpi.table": { "enabled": false },
  "com.ibi.linear_real_time": { "enabled": false },
  "com.ibi.liquid_gauge": { "enabled": false },
  "com.ibi.map.usa.choropleth": { "enabled": false },
  "com.ibi.map.world": { "enabled": false },
  "com.ibi.marker": { "enabled": false },
  "com.ibi.odometer": { "enabled": false },
  "com.ibi.orgchart": { "enabled": false },
  "com.ibi.pack": { "enabled": false },
  "com.ibi.population": { "enabled": false },
  "com.ibi.range": { "enabled": false },
  "com.ibi.ratio": { "enabled": false },
  "com.ibi.sankey": { "enabled": false },
  "com.ibi.simple_bar": { "enabled": true },
  "com.ibi.sparktables": { "enabled": false },
  "com.ibi.sunburst": { "enabled": false },
  "com.ibi.template": { "enabled": false },
  "com.ibi.timeline": { "enabled": false },
  "com.ibi.tutorial": { "enabled": false },
  "com.ibi.usmap": { "enabled": false },
  "com.ibi.kpi_box_trend": { "enabled": false },
  "com.shimokado.sample": { "enabled": true }
}

紛らわしいので以下の2機能以外はfalseにしておきます。

  • com.ibi.simple_bar
  • com.shimokado.sample

表示テキストとアイコンを編集

これでcom.ibi.simple_barとcom.shimokado.sampleは同じ動作をしますが区別できません。

グラフ選択時の表示テキストとアイコンを編集します。

"C:\ibi\WebFOCUS93\config\web_resource\extensions\com.shimokado.sample\properties.json"の内容を変種します。

properties.json
{
	"info": {
		"version": "1.0.1",
		"implements_api_version": 1.0,
		"author": "Cloud Software Group, Inc.",
		"copyright": "Cloud Software Group, Inc.",
		"url": "https://github.com/ibi/wf-extensions-chart/tree/master/com.ibi.simple_bar",
		"icons": {
			"medium": "icons/icon.png"
		}
	},

	"properties": {
		"chartHeadroom": 50,
		"external_library": "lib/d3.min.js"
	},

	"propertyAnnotations": {
		"chartHeadroom": "number",
		"external_library": "str"
	},

	"dataBuckets":  {

		"tooltip": true,
		"matrix": false,
		"data_page": false,
		"series_break": true,

		"buckets": [
			{
				"id": "value",
				"type": "measure",
				"count": {
					"min": 1,
					"max": 1
				}
			},
			{
				"id": "labels",
				"type": "dimension",
				"count": {
					"min": 0,
					"max": 1
				}
			}
		]
	},

	"translations": {
		"en": {
			"name": "Extension Chart Development",
			"description": "This is a sample for developing an extension chart.",
			"icon_tooltip": "This extension chart is a sample for developing an extension chart.",
			"value_name": "Value Bucket",
			"value_tooltip": "Drop a measure here",
			"labels_name": "Label Bucket",
			"labels_tooltip": "Drop a dimension here"
		},

		"ja": {
			"name": "開発中の拡張グラフ",
			"description": "拡張グラフを開発するためのサンプルです。",
			"icon_tooltip": "この拡張グラフは拡張グラフを開発するためのサンプルです。", 
			"value_name": "値バケット", 
			"value_tooltip": "ここにメジャーをドロップ", 
			"labels_name": "ラベルバケット", 
			"labels_tooltip": "ここにディメンションをドロップ"
		}
	}
}

変更しているのは50行目以降だけです。

アイコン画像は9行目で設定されているicons/icon.pngです。

画像サイズを変えずに適当な画像に変更しましょう。

extend

同じフォルダにあるicon.svgは要らないので消しておきます。

Apatch Tomcatを再起動して動作確認

WebFOCUSを動かしているApatch Tomcatを再起動してブラウザのキャッシュをクリアしてHTML5拡張グラフを選択します。

以降もファイルの編集結果を反映するには、Apatch Tomcatを再起動してブラウザのキャッシュもクリアしてください。

HTML5拡張グラフの選択画面が以下のようになります。
extend

中身は変更していないので実行結果は、Simple Barのままです。

extend

グラフのタイトルと作成者を変更する

表示したグラフのタイトルと、グラフ選択時の作成者名を変更します。

properties.json infoオブジェクト
	"info": {
		"version": "1.0.1",
		"implements_api_version": 1.0,
		"author": "Shimokado Masataka",
		"copyright": "Shimokado Masataka",
		"url": "https://github.com/ibi/wf-extensions-chart/tree/master/com.ibi.simple_bar",
		"icons": {
			"medium": "icons/icon.png"
		}
	},

authorとcopyrightの値を変更しています。

com.shimokado.sample.jsのタイトル文字を変更します。

com.shimokado.sample.js 変更箇所
	function preRenderCallback(preRenderConfig) {
		var chart = preRenderConfig.moonbeamInstance;

		// Example of manually loading a file in this extension's folder path and using it.
		//var info = tdgchart.util.ajax(preRenderConfig.loadPath + 'lib/extra_properties.json', {asJSON: true});
		var info = {"custom_title": "拡張グラフのサンプル"};

コメントにした65行目は、lib/extra_properties.jsonを読み込む記述です。

preRenderConfig.loadPathで自身のパスが取れるのは後々使えそうです。

要らなくなったextra_properties.jsonの中身は以下のようになっていました。

extra_properties.json
{
	"custom_title": "Simple Bar Chart Extension"
}

再度動作確認

再起動とキャッシュクリア後

extend
extend

その後のカスタマイズ

ここからはd3の記述を自由に変えてsvgを作ればいいだけですね。

そちらは、d3関連のマニュアルを参照してください。

拡張グラフ(HTML)を開発する

今度は、d3を使ったグラフではなくHTML形式で出力してみます。

拡張グラフ?と思うかもしれませんが、これが出来れば自由にHTML形式でデータを表示できるようになります。

HTMLを出力する場合の記述

編集したファイルは以下のようになります。

com.shimokado.sample.js
/* Copyright (C) 2025. Shimokado Masataka. All rights reserved. */

(function() {
	/**
	 * チャートの初期化処理
	 * @param {function} successCallback - 初期化成功時に呼び出すコールバック関数
	 * @param {object} initConfig - 初期化設定
	 */
	function initCallback(successCallback, initConfig) {
		successCallback(true);
	}

	/**
	 * データがない場合の事前レンダリングコールバック
	 * @param {object} preRenderConfig - 事前レンダリング設定
	 */
	function noDataPreRenderCallback(preRenderConfig) {
	}

	/**
	 * データがない場合のレンダリングコールバック
	 * @param {object} renderConfig - レンダリング設定
	 */
	function noDataRenderCallback(renderConfig) {
	}

	/**
	 * プリレンダリングコールバック
	 * @param {object} preRenderConfig - 事前レンダリング設定
	 */
	function preRenderCallback(preRenderConfig) {
	}
	
	/**
	 * レンダリングコールバック
	 * @param {object} renderConfig - レンダリング設定
	 * @param {object} renderConfig.moonbeamInstance - Moonbeamインスタンス
	 * @param {object} renderConfig.properties - プロパティ
	 * @param {object} renderConfig.container - コンテナ
	 * @param {object} renderConfig.data - データ
	 * @param {object} renderConfig.dataBuckets - データバケット
	 * @param {object} renderConfig.dataBuckets.labels - ラベルデータバケット
	 * @param {object} renderConfig.dataBuckets.value - 値データバケット
	 * @param {function} renderConfig.renderComplete - レンダリング完了時に呼び出すコールバック関数
	 */
	function renderCallback(renderConfig) {
		var chart = renderConfig.moonbeamInstance; // Moonbeamインスタンス
		var props = renderConfig.properties; // プロパティ
		var container = renderConfig.container; // コンテナ
		var data = renderConfig.data; // データ
		var dataBuckets = renderConfig.dataBuckets.buckets; // データバケット

		// テーブルのスタイル設定
		var fontSize = props.tableStyle ? props.tableStyle.fontSize : "12px";
		var color = props.tableStyle ? props.tableStyle.color : "#000000";

		// テーブルコンテナの作成
		var tableContainer = document.createElement('div');
		tableContainer.className = 'simple-table-container';
		container.appendChild(tableContainer);

		// テーブル要素の作成
		var tableHTML = '<table style="width:100%; font-size:' + fontSize + '; color:' + color + ';">';
		
		// ヘッダーの作成
		tableHTML += '<thead><tr>';
		tableHTML += '<th>' + dataBuckets.labels.title + '</th>';
		tableHTML += '<th>' + dataBuckets.value.title + '</th>';
		tableHTML += '</tr></thead>';

		// データ行の作成
		tableHTML += '<tbody>';
		data.forEach(function(row) {
			tableHTML += '<tr>';
			tableHTML += '<td>' + row.labels + '</td>';
			tableHTML += '<td>' + chart.formatNumber(row.value, dataBuckets.value.numberFormat || '###') + '</td>';
			tableHTML += '</tr>';
		});
		tableHTML += '</tbody></table>';

		tableContainer.innerHTML = tableHTML;

		renderConfig.renderComplete();
	}

	var config = {
		id: 'com.shimokado.sample',	// エクステンションID
		containerType: 'html',	// コンテナタイプ(html/svg)
		initCallback: initCallback,	// 拡張機能の初期化直前に呼び出される関数への参照。必要に応じてMonbeamインスタンスを設定するために使用
		preRenderCallback: preRenderCallback,  // 拡張機能のレンダリング直前に呼び出される関数への参照。preRenderConfigオブジェクトが渡されます
		renderCallback: renderCallback,  // 実際のチャートを描画する関数への参照。renderConfigオブジェクトが渡されます
		noDataPreRenderCallback: noDataPreRenderCallback, // データがない場合のレンダリング直前に呼び出される関数への参照
		noDataRenderCallback: noDataRenderCallback, // データがない場合のチャート描画関数への参照
		resources: {
			script: [], // 読み込むリソースのリスト。.jsまたは.cssファイルを指定可能
			css: [] // 読み込むリソースのリスト。.jsまたは.cssファイルを指定可能
		},
		modules: {
			dataSelection: {
				supported: true,  // データ選択を有効にする場合はtrueに設定
				needSVGEventPanel: true, // HTMLコンテナを使用するか、SVGコンテナを変更する場合はtrueに設定
				svgNode: function(arg){}  // HTMLコンテナを使用するか、SVGコンテナを変更する場合、ルートSVGノードへの参照を返す
			},
			eventHandler: {
				supported: true // イベントハンドラを有効にする場合はtrueに設定
			},
			tooltip: {
				supported: true,  // HTMLツールチップを有効にする場合はtrueに設定
				// デフォルトのツールチップコンテンツが渡されない場合に呼び出されるコールバック
				// 指定されたターゲット、ID、データに対して適切なデフォルトツールチップを定義
				// 戻り値は文字列(HTMLを含む)、HTMLノード、またはMoonbeamツールチップAPIオブジェクト
				autoContent: function(target, s, g, d) {
					return d.labels + ': ' + d.value; // 単純な文字列を返す
				}
			}
		}
	};
	// エクステンションをtdgchartエクステンションマネージャに登録
	tdgchart.extensionManager.register(config);
}());

properties.jsonも変更しました。

properties.json
{
    "info": {
        "version": "1.0.0",  
        "implements_api_version": 1.0,
        "author": "Shimokado Masataka",
        "copyright": "Shimokado Masataka",
        "url": "",
        "icons": {
            "medium": "icons/icon.png"
        }
    },

    "properties": {
        "tableStyle": {
            "fontSize": "20px",
            "color": "#663300"
        }
    },

    "propertyAnnotations": {
        "tableStyle": {
            "fontSize": "str",
            "color": "str"
        }
    },

    "dataBuckets": {
        "tooltip": true,
        "matrix": false,
        "data_page": false,
        "series_break": false,

        "buckets": [
            {
                "id": "value",
                "type": "measure",
                "count": {
                    "min": 1,
                    "max": 1
                }
            },
            {
                "id": "labels",
                "type": "dimension",
                "count": {
                    "min": 1,
                    "max": 1
                }
            }
        ]
    },

    "translations": {
        "en": {
            "name": "Simple Table",
            "description": "Display data in a simple HTML table",
            "icon_tooltip": "Simple Table",
            "value_name": "Value",
            "value_tooltip": "Drop a measure here",
            "labels_name": "Labels",
            "labels_tooltip": "Drop a dimension here"
        },
        "ja": {
            "name": "シンプルテーブル",
            "description": "データをシンプルな表で表示します",
            "icon_tooltip": "シンプルテーブル",
            "value_name": "値",
            "value_tooltip": "ここにメジャーをドロップ",
            "labels_name": "ラベル",
            "labels_tooltip": "ここにディメンションをドロップ"
        }
    }
}

実行結果

extend

HTMLで出力する時のポイント

色々と詳細に調べてみたい箇所はありますが、function renderCallback(renderConfig) {}関数の中で、以下のことが出来れば自由にHTML形式で拡張グラフを出力できるようになります。

  1. renderConfig.dataBucketsで値とラベルの項目情報を取得する
  2. renderConfig.dataでデータ値を取得する。
  3. 好きなように加工してrenderConfig.containerにappendChildする。
  4. 最後にrenderConfig.renderComplete();をコールする。

WebFOCUSがグローバルスコープに設定する変数

WebFOCUSが拡張グラフを実行時にグローバルスコープに設定している値は以下のような記述です。(長いです。。。)

丸ごと載せましたが目次で次に飛んでいいと思います。

(function() {
var script = '';
script += 'setDefaultFontName("\uFF2D\uFF33 \u30B4\u30B7\u30C3\u30AF");';
script += 'setDataRangeToExtent();';
script += 'setDecimalSeparator(".");';
script += 'setGroupingSeparator(",");';
script += 'setMonetarySeparator(",");';
script += 'setCentZero(false);';
script += 'setCurrencySymbolOverride("\u00A5");';
var chart = new tdgchart({backend:'js', allowBackendFallback:true, webappContext: '/ibi_apps', htmlKey: 'S3_17207238601F', extensionKey: 'C51459e255ed9aaf1c152572de4394cf7'});
if (tdgchart.WF_charts == undefined)
  tdgchart.WF_charts = {};
tdgchart.WF_charts['jschart_HOLD_0'] = chart;
chart.data = [];
chart.title.text = '';
chart.parsePFJString(script);
chart.set({
	"injectedRevision" : "$Revision: 1.2 $",
	"dataSetLimits": {"enabled": true},
	"catchErrors" : true
});
script = '';
script += 'setPieDepth(0);';
script += 'setPieTilt(0);';
script += 'setDepthRadius(0);';
script += 'setPlace(true);';
script += 'setCurveFitEquationDisplay(false);';
chart.parsePFJString(script);
script = '';
script += 'setFillColor(getSeries(0),new Color(#5388be));';
script += 'setFillColor(getSeries(1),new Color(#9ed675));';
script += 'setFillColor(getSeries(2),new Color(#4fa03d));';
script += 'setFillColor(getSeries(3),new Color(#fcce58));';
script += 'setFillColor(getSeries(4),new Color(#e1542b));';
script += 'setFillColor(getSeries(5),new Color(#efcca2));';
script += 'setSeriesLooping(6);';
script += 'setColorMode(4);';
script += 'setAutoColorLerpFactor(0.8);';
script += 'setTransparentBorderColor(getChartBackground(),true);';
script += 'setTransparentBorderColor(getSeries(0),true);';
script += 'setTransparentBorderColor(getFrame(),true);';
script += 'setTransparentBorderColor(getSeries(0),true);';
script += 'setTransparentBorderColor(getSeries(1),true);';
script += 'setTransparentBorderColor(getSeries(2),true);';
script += 'setTransparentBorderColor(getSeries(3),true);';
script += 'setTransparentBorderColor(getSeries(4),true);';
script += 'setTransparentBorderColor(getSeries(5),true);';
script += 'setTransparentBorderColor(getSeries(6),true);';
script += 'setTransparentBorderColor(getSeries(7),true);';
script += 'setTransparentBorderColor(getSeries(8),true);';
script += 'setTransparentBorderColor(getSeries(9),true);';
script += 'setTransparentBorderColor(getSeries(10),true);';
script += 'setTransparentBorderColor(getSeries(11),true);';
script += 'setTransparentBorderColor(getSeries(12),true);';
script += 'setTransparentBorderColor(getSeries(13),true);';
script += 'setTransparentBorderColor(getSeries(14),true);';
script += 'setTransparentBorderColor(getSeries(15),true);';
script += 'setTransparentBorderColor(getSeries(16),true);';
script += 'setTransparentBorderColor(getSeries(17),true);';
script += 'setX1MajorTickDisplay(true);';
script += 'setTickLength(getX1MajorTick(),200);';
script += 'setBorderColor(getX1MajorTick(),new Color(192,192,192));';
script += 'setTickStyle(getX1MajorTick(),3);';
script += 'setLegendPosition(2);';
script += 'setSmoothLines(false);';
script += 'setFillColor(getO1Label(),new Color(128,128,128));';
script += 'setDisplay(getO1MajorGrid(),false);';
script += 'setBorderColor(getO1MajorGrid(),new Color(128,128,128));';
script += 'setFillColor(getO1MajorGrid(),new Color(128,128,128));';
script += 'setAltFmtFrameNumColors(getO1AltFmtFrame(),5);';
script += 'setFontName(getO1Title(),"\uFF2D\uFF33 \u30B4\u30B7\u30C3\u30AF");';
script += 'setFontSizeAbsolute(getO1Title(),true);';
script += 'setFontSizeInPoints(getO1Title(),10);';
script += 'setPlaceResize(getO1Title(),0);';
script += 'setFillColor(getO1Title(),new Color(128,128,128));';
script += 'setTickLength(getY1MajorTick(),200);';
script += 'setBorderColor(getY1AxisLine(),new Color(192,192,192));';
script += 'setFillColor(getY1AxisLine(),new Color(192,192,192));';
script += 'setLineWidth(getY1AxisLine(),1);';
script += 'setDisplay(getY1ZeroLine(),true);';
script += 'setBorderColor(getY1ZeroLine(),new Color(192,192,192));';
script += 'setLineWidth(getY1ZeroLine(),1);';
script += 'setFillColor(getY1Label(),new Color(128,128,128));';
script += 'setBorderColor(getY1MajorGrid(),new Color(128,128,128));';
script += 'setFillColor(getY1MajorGrid(),new Color(128,128,128));';
script += 'setAltFmtFrameNumColors(getY1AltFmtFrame(),5);';
script += 'setScaleMustIncludeZero(getY1Axis(),true);';
script += 'setFontSizeAbsolute(getY1Title(),true);';
script += 'setFontSizeInPoints(getY1Title(),10);';
script += 'setPlaceResize(getY1Title(),0);';
script += 'setFillColor(getY1Title(),new Color(128,128,128));';
script += 'setFontName(getY1Title(),"\uFF2D\uFF33 \u30B4\u30B7\u30C3\u30AF");';
script += 'setFontName(getY1Label(),"\uFF2D\uFF33 \u30B4\u30B7\u30C3\u30AF");';
script += 'setFontSizeAbsolute(getY1Label(),true);';
script += 'setFontSizeInPoints(getY1Label(),9);';
script += 'setPlaceResize(getY1Label(),0);';
script += 'setBorderColor(getY1MajorTick(),new Color(192,192,192));';
script += 'setDisplay(getY1MajorTick(),true);';
script += 'setTickStyle(getY1MajorTick(),3);';
script += 'setDisplay(getY1MajorGrid(),false);';
script += 'setFontName(getX1Title(),"\uFF2D\uFF33 \u30B4\u30B7\u30C3\u30AF");';
script += 'setFontSizeAbsolute(getX1Title(),true);';
script += 'setFontSizeInPoints(getX1Title(),10);';
script += 'setPlaceResize(getX1Title(),0);';
script += 'setFillColor(getX1Title(),new Color(128,128,128));';
script += 'setTickLength(getY2MajorTick(),200);';
script += 'setBorderColor(getY2AxisLine(),new Color(88,88,88));';
script += 'setFillColor(getY2AxisLine(),new Color(88,88,88));';
script += 'setLineWidth(getY2AxisLine(),1);';
script += 'setDisplay(getY2ZeroLine(),true);';
script += 'setBorderColor(getY2ZeroLine(),new Color(88,88,88));';
script += 'setLineWidth(getY2ZeroLine(),1);';
script += 'setFillColor(getY2Label(),new Color(64,64,64));';
script += 'setBorderColor(getY2MajorGrid(),new Color(64,64,64));';
script += 'setFillColor(getY2MajorGrid(),new Color(64,64,64));';
script += 'setAltFmtFrameNumColors(getY2AltFmtFrame(),5);';
script += 'setScaleMustIncludeZero(getY2Axis(),true);';
script += 'setFontSizeAbsolute(getY2Title(),true);';
script += 'setFontSizeInPoints(getY2Title(),10);';
script += 'setPlaceResize(getY2Title(),0);';
script += 'setFillColor(getY2Title(),new Color(64,64,64));';
script += 'setFontName(getY2Title(),"\uFF2D\uFF33 \u30B4\u30B7\u30C3\u30AF");';
script += 'setFontName(getY2Label(),"\uFF2D\uFF33 \u30B4\u30B7\u30C3\u30AF");';
script += 'setFontSizeAbsolute(getY2Label(),true);';
script += 'setFontSizeInPoints(getY2Label(),9);';
script += 'setPlaceResize(getY2Label(),0);';
script += 'setBorderColor(getY2MajorTick(),new Color(88,88,88));';
script += 'setDisplay(getY2MajorTick(),true);';
script += 'setTickStyle(getY2MajorTick(),3);';
script += 'setDisplay(getY2MajorGrid(),false);';
script += 'setFontName(getX1Title(),"\uFF2D\uFF33 \u30B4\u30B7\u30C3\u30AF");';
script += 'setFontSizeAbsolute(getX1Title(),true);';
script += 'setFontSizeInPoints(getX1Title(),10);';
script += 'setPlaceResize(getX1Title(),0);';
script += 'setFillColor(getX1Title(),new Color(128,128,128));';
script += 'setFontName(getO1Label(),"\uFF2D\uFF33 \u30B4\u30B7\u30C3\u30AF");';
script += 'setFontSizeAbsolute(getO1Label(),true);';
script += 'setFontSizeInPoints(getO1Label(),9);';
script += 'setPlaceResize(getO1Label(),0);';
script += 'setFontName(getLegendText(),"\uFF2D\uFF33 \u30B4\u30B7\u30C3\u30AF");';
script += 'setFillColor(getLegendText(),new Color(80,80,80));';
script += 'setSquareMarkers(true);';
script += 'setUseSeriesShapes(true);';
script += 'setMarkerShape(getSeries(0),0);';
script += 'setPieFeelerTextDisplay(0);';
script += 'setFontName(getPieRingLabel(),"\uFF2D\uFF33 \u30B4\u30B7\u30C3\u30AF");';
script += 'setFontSizeAbsolute(getPieRingLabel(),true);';
script += 'setAutofit(getPieRingLabel(),false);';
script += 'setFontSizeInPoints(getPieRingLabel(),28);';
script += 'setPlaceResize(getPieRingLabel(),0);';
script += 'setDisplay(getX1MajorGrid(),false);';
script += 'setBorderColor(getO1AxisLine(),new Color(192,192,192));';
script += 'setLineWidth(getO1AxisLine(),1);';
script += 'setBorderColor(getX1AxisLine(),new Color(192,192,192));';
script += 'setLineWidth(getX1AxisLine(),1);';
script += 'setScaleMustIncludeZero(getX1Axis(),true);';
script += 'setBorderColor(getO1MajorTick(),new Color(192,192,192));';
script += 'setDisplay(getO1MajorTick(),false);';
script += 'setTickStyle(getO1MajorTick(),3);';
script += 'setTransparentFillColor(getFrame(),true);';
script += 'setPieRingSize(64);';
script += 'setDisplay(getQuadrantLine(),false);';
script += 'setFillColor(getX1Label(),new Color(128,128,128));';
script += 'setFontName(getX1Label(),"\uFF2D\uFF33 \u30B4\u30B7\u30C3\u30AF");';
script += 'setFontSizeAbsolute(getX1Label(),true);';
script += 'setFontSizeInPoints(getX1Label(),9);';
script += 'setPlaceResize(getX1Label(),0);';
script += 'setPlaceTruncateCount(getLegendText(),15);';
script += 'setZeroValueDataTextDisplay(false);';
chart.parsePFJString(script);
chart.set({
	"fill": {
		"color": "transparent"
	},
	"border": {
		"width": 1,
		"color": "transparent",
		"dash": ""
	},
	"blaProperties": {
		"areaFillEffect": "70%",
		"barGroupGapWidth": "0.4"
	},
	"bubbleMarker": {
		"maxSize": "11%"
	},
	"pieProperties": {
		"holeSize": 0,
		"totalLabel": {
			"visible": "auto",
			"font": "10pt Sans-Serif",
			"color": "#505050"
		}
	},
	"gaugeProperties": {
		"totalLabel": {
			"color": "#505050"
		},
		"secondaryRingFillColor": "#e5e5e5",
		"startAngle": 270,
		"endAngle": 270,
		"axisWidth": "25%",
		"outerBorder": {
			"fill": {
				"color": "transparent"
			},
			"width": "6%"
		}
	},
	"series": [
		{
			"series": "all",
			"dataLabels": {
				"visible": "auto",
				"font": "7.5pt Sans-Serif",
				"color": "auto"
			},
			"color": null,
			"border": {
				"width": 3
			},
			"marker": {
				"visible": false,
				"size": 10,
				"border": {
					"width": 2
				},
				"shape": "circle",
				"fillEffect": "seriesAuto"
			}
		},
		{
			"series": 0,
			"color": "#5388be"
		},
		{
			"series": 1,
			"color": "#9ed675"
		},
		{
			"series": 2,
			"color": "#4fa03d"
		},
		{
			"series": 3,
			"color": "#FCCE58"
		},
		{
			"series": 4,
			"color": "#e1542b"
		},
		{
			"series": 5,
			"color": "#efcca2"
		}
	],
	"legend": {
		"visible": "auto",
		"lineStyle": {
			"width": 1,
			"color": "transparent"
		},
		"title": {
			"visible": false,
			"font": "10pt Sans-Serif",
			"color": "#505050"
		},
		"labels": {
			"font": "7.5pt Sans-Serif",
			"color": "#505050"
		},
		"shadow": false,
		"position": "auto",
		"backgroundcolor": "transparent",
		"scroll": {
			"enabled": true,
			"handle": {
				"color": "#D1D1D1",
				"hoverColor": "#B3B3B3"
			}
		},
		"dock": {
			"enabled": true,
			"button": {
				"color": "#D1D1D1",
				"hoverColor": "#B3B3B3"
			}
		}
	},
	"colorScale": {
		"title": {
			"text": "",
			"visible": true
		},
		"colors": [
			"#D73027",
			"#FDAE61",
			"#FFFFBF",
			"#A6D96A",
			"#1A9850"
		],
		"labels": {
			"visible": true,
			"font": "7.5pt Sans-Serif",
			"color": "#505050"
		},
		"majorGrid": {
			"visible": true,
			"aboveRisers": true,
			"lineStyle": {
				"width": 1,
				"color": "rgba(255, 255, 255, 0.3)"
			},
			"ticks": {
				"length": 5,
				"visible": false,
				"style": "outer",
				"lineStyle": {
					"width": 1,
					"color": "#BABABA"
				}
			}
		}
	},
	"xaxis": {
		"mustIncludeZero": true,
		"title": {
			"visible": true,
			"font": "10pt Sans-Serif",
			"color": "#505050"
		},
		"labels": {
			"visible": true,
			"font": "9pt Sans-Serif",
			"color": "#505050",
			"excludeMin": false,
			"nestingConcatSymbol": " : ",
			"rotation": null
		},
		"labelLayout": {
			"stagger": false,
			"skip": "auto",
			"scroll": "auto",
			"truncate": "auto"
		},
		"bodyLineStyle": {
			"width": 1,
			"color": "#BABABA",
			"dash": ""
		},
		"baseLineStyle": {
			"width": 1,
			"color": "#BABABA",
			"dash": ""
		},
		"majorGrid": {
			"visible": false,
			"aboveRisers": false,
			"lineStyle": {
				"width": 1,
				"color": "#EEEEEE",
				"dash": ""
			},
			"ticks": {
				"length": 5,
				"visible": false,
				"style": "inner",
				"lineStyle": {
					"width": 1,
					"color": "#BABABA"
				}
			}
		},
		"minorGrid": {
			"visible": false,
			"count": null,
			"lineStyle": {
				"width": 1,
				"color": "#EEEEEE",
				"dash": ""
			},
			"ticks": {
				"length": 5,
				"visible": false,
				"style": "inner",
				"lineStyle": {
					"width": 1,
					"color": "#BABABA"
				}
			}
		}
	},
	"yaxis": {
		"mustIncludeZero": true,
		"title": {
			"visible": true,
			"font": "10pt Sans-Serif",
			"color": "#505050"
		},
		"labels": {
			"visible": true,
			"font": "9pt Sans-Serif",
			"color": "#505050",
			"excludeMin": false,
			"rotation": null
		},
		"bodyLineStyle": {
			"width": 1,
			"color": "#BABABA",
			"dash": ""
		},
		"baseLineStyle": {
			"width": 1,
			"color": "#BABABA",
			"dash": ""
		},
		"minorGrid": {
			"visible": false,
			"count": null,
			"lineStyle": {
				"width": 1,
				"color": "#EEEEEE",
				"dash": ""
			},
			"ticks": {
				"length": 5,
				"style": "outer",
				"visible": false,
				"lineStyle": {
					"width": 1,
					"color": "#BABABA"
				}
			}
		},
		"majorGrid": {
			"visible": false,
			"aboveRisers": false,
			"lineStyle": {
				"width": 1,
				"color": "#EEEEEE",
				"dash": ""
			},
			"ticks": {
				"length": 5,
				"visible": true,
				"style": "outer",
				"lineStyle": {
					"width": 1,
					"color": "#BABABA"
				}
			}
		}
	},
	"y2axis": {
		"mustIncludeZero": true,
		"title": {
			"visible": true,
			"font": "10pt Sans-Serif",
			"color": "#505050"
		},
		"labels": {
			"visible": true,
			"font": "9pt Sans-Serif",
			"color": "#505050",
			"excludeMin": false,
			"rotation": null
		},
		"bodyLineStyle": {
			"width": 1,
			"color": "#BABABA",
			"dash": ""
		},
		"baseLineStyle": {
			"width": 1,
			"color": "#BABABA",
			"dash": ""
		},
		"minorGrid": {
			"visible": false,
			"count": null,
			"lineStyle": {
				"width": 1,
				"color": "#EEEEEE",
				"dash": ""
			},
			"ticks": {
				"length": 5,
				"style": "outer",
				"visible": false,
				"lineStyle": {
					"width": 1,
					"color": "#BABABA"
				}
			}
		},
		"majorGrid": {
			"visible": false,
			"aboveRisers": false,
			"lineStyle": {
				"width": 1,
				"color": "#EEEEEE",
				"dash": ""
			},
			"ticks": {
				"length": 5,
				"visible": true,
				"style": "outer",
				"lineStyle": {
					"width": 1,
					"color": "#BABABA"
				}
			}
		}
	},
	"zaxis": {
		"title": {
			"text": "",
			"visible": true,
			"font": "10pt Sans-Serif",
			"color": "#505050"
		},
		"labels": {
			"visible": true,
			"font": "9pt Sans-Serif",
			"color": "#505050",
			"excludeMin": false,
			"excludeMax": "auto",
			"rotation": null
		},
		"majorGrid": {
			"visible": false,
			"ticks": {
				"visible": false
			}
		}
	},
	"mouseOverIndicator": {
		"color": "transparent",
		"border": {
			"width": 2,
			"color": "#303030"
		},
		"marker": {
			"color": "rgba(255, 255, 0, 0.88)",
			"size": 8,
			"shape": "circle",
			"rotation": 0,
			"position": "top",
			"border": {
				"width": 0,
				"color": "rgba(26, 26, 26, 0.9)",
				"dash": ""
			}
		}
	},
	"matrixProperties": {
		"rowLabels": {
			"color": "#505050",
			"font": "8pt Sans-Serif"
		},
		"colLabels": {
			"color": "#505050",
			"font": "8pt Sans-Serif"
		},
		"rowHeader": {
			"color": "#505050",
			"font": "10pt Sans-Serif"
		},
		"colHeader": {
			"color": "#505050",
			"font": "10pt Sans-Serif"
		},
		"cellBorder": {
			"width": 1,
			"color": "#AAAAAA"
		}
	},
	"dataSelection": {
		"unselectedColor": "85%",
		"selectionRect": {
			"fill": "rgba(120, 120, 180, 0.45)",
			"border": {
				"width": 1,
				"color": "rgba(120, 120, 205, 0.8)"
			}
		}
	},
	"tagcloudProperties": {
		"engine": "new",
		"font": "14pt Sans-serif"
	},
	"morphAnimation": {
		"duration": 1000
	},
	"dataGridProperties": {
		"colHeader": {
			"sorting": {
				"enabled": true
			},
			"resize": {
				"enabled": true
			}
		}
	},
	"riserCycleEndLightness": 0.8,
	"riserBevel": "none",
	"showNullGroups": false,
	"narrativeText": {
		"label": {
			"font": "11pt Arial",
			"color": "#000000",
			"align": "left"
		},
		"backgroundColor": "#FFFFFF",
		"border": {
			"width": 0,
			"color": "#000000",
			"dash": ""
		}
	},
	"extensions": {
		"com.esri.map": {
			"baseLayer": {
				"basemap": "gray"
			}
		}
	}
});
script = '';
script += 'setReportParsingErrors(false);';
script += 'setSelectionEnableMove(false);';
chart.parsePFJString(script);
chart.set({
// The following properties were generated by the Reporting Server:
data: [
  [
    [
      'ENGLAND'
     ,13
    ]
   ,[
      'FRANCE'
     ,5
    ]
   ,[
      'ITALY'
     ,10
    ]
   ,[
      'JAPAN'
     ,8
    ]
   ,[
      'W GERMANY'
     ,34
    ]
  ]
]
,series: [
  {
    series: 0
   ,label: ' '
   ,tooltip: [
      { type: 'nameValue' ,name: 'COUNTRY' ,value: '{{extension_bucket("labels",0)}}' }
     ,{ type: 'nameValue' ,name: 'SEATS' ,value: '{{extension_bucket("value",0)}}' }
    ]
  }
]
,dataArrayMap: [
  'labels'
 ,'value'
]
,dataBuckets: {
  internal_api_version: 2.0
 ,buckets: [
    {
      id: 'labels'
     ,fields: [
        { title: 'COUNTRY' ,fieldName: 'CAR.ORIGIN.COUNTRY' }
      ]
    }
   ,{
      id: 'value'
     ,fields: [
        { title: 'SEATS' ,fieldName: 'CAR.BODY.SEATS' ,numberFormat: '#' }
      ]
    }
  ]
}
});
chart.set({
"pieProperties": {
"holeSize": "0%"
},
"chartType": "com.shimokado.sample",
"agnosticSettings": {
"chartTypeFullName": "com.shimokado.sample"
}
});
var divId = 'jschart_HOLD_';
var defaultWidth = 770;
var defaultHeight = 405;
var fitWidthOnly = false;
var minHeight = 0;
var noResize = false;
window.addEventListener('resizesuspend', onManageResize);
window.addEventListener('resizeresume', onManageResize);
window.addEventListener('redraw', onDraw);
function onManageResize(event)
{
  noResize = event.type == 'resizesuspend';
}
function onDraw(event)
{
  window.onresize();
}
var drawn = false;
window.onresize = function() {
  if (noResize) return;
  var chartArray;
  if (Array.isArray(chart))
    chartArray = chart;
  else
  {
    chartArray = new Array(1);
    chartArray[0] = chart;
  }
  var numCharts = chartArray.length;
  var oldWidth = chartArray[0].width;
  var oldChartHeight = chartArray[0].height;
  var width = window.innerWidth || document.documentElement.offsetWidth;
  var height = defaultHeight;
  if (!fitWidthOnly)
    height = window.innerHeight || document.documentElement.offsetHeight;
  if (width == 0 || height == 0) {
    width = defaultWidth;
    height = defaultHeight;
  }
  var body = document.getElementsByTagName("body")[0];
  var style;
  if (body.currentStyle) // IE
    style = body.currentStyle;
  else if (window.getComputedStyle)
    style = window.getComputedStyle(body, null);
  if (style != undefined) {
    var hMargins = parseInt(style.marginLeft, 10) + parseInt(style.marginRight, 10);
    width -= hMargins;
    var vMargins = parseInt(style.marginTop, 10) + parseInt(style.marginBottom, 10);
    height -= vMargins;
  }
  var chartHeight = height / numCharts;
  if (chartHeight < minHeight)
    chartHeight = minHeight;
  if (!drawn || (oldWidth != width) || (oldChartHeight != height)) {
    for (var i = 0; i < numCharts; i++)
    {
      var chrt = chartArray[i];
      chrt.width = width;
      chrt.height = chartHeight;
      chrt.draw(divId + i);
    }
    drawn = true;
  }
};
window.onload = window.onresize;
})();

WebFOCUSがグローバルスコープに設定する変数(見どころ)

// The following properties were generated by the Reporting Server:

の後が、実際のリクエスト内容とデータの部分です。

それ以前の部分は、テーマに合わせたシリーズとかの色やグラフデザインのための物です。

色の指定など有るので、必要に応じて処理に取り込んでください。

レポートやグラフをレンダリングするのに必要なのは以下の箇所です。

renderConfigで取得できるパラメータのうち、dataとdataBucketsがあれば何とかなりそうですね。

data: [
  [
    [
      'ENGLAND'
     ,13
    ]
   ,[
      'FRANCE'
     ,5
    ]
   ,[
      'ITALY'
     ,10
    ]
   ,[
      'JAPAN'
     ,8
    ]
   ,[
      'W GERMANY'
     ,34
    ]
  ]
]
,series: [
  {
    series: 0
   ,label: ' '
   ,tooltip: [
      { type: 'nameValue' ,name: 'COUNTRY' ,value: '{{extension_bucket("labels",0)}}' }
     ,{ type: 'nameValue' ,name: 'SEATS' ,value: '{{extension_bucket("value",0)}}' }
    ]
  }
]
,dataArrayMap: [
  'labels'
 ,'value'
]
,dataBuckets: {
  internal_api_version: 2.0
 ,buckets: [
    {
      id: 'labels'
     ,fields: [
        { title: 'COUNTRY' ,fieldName: 'CAR.ORIGIN.COUNTRY' }
      ]
    }
   ,{
      id: 'value'
     ,fields: [
        { title: 'SEATS' ,fieldName: 'CAR.BODY.SEATS' ,numberFormat: '#' }
      ]
    }
  ]
}

まとめ

存在しない種類のグラフを作ることも出来ますが、HTML形式でレイアウトを統一したレポートを作成したり、

フレキシブルなカード型のデザインでお洒落なページを作ることが出来るので、一つ綺麗なものを作っておきたいですね。

Discussion