グリッド

FlexGridは、高速で柔軟なJavaScriptデータグリッドコントロールです。コアグリッドモジュールには、最も一般的な機能がすべて含まれています。また、さらにグリッドをカスタマイズするための拡張機能と柔軟なAPIも含まれています。

このサンプルでは、FlexGridソートグループ化検索フィルターデータマップセルテンプレートスパークラインカスタムエディタExcelエクスポートPDFエクスポート検証詳細行などの多くの機能を紹介しています。

データ項目の数を変更してみて、非常に大規模なデータセットであってもグリッドが高速のままであることを確認してください。FlexGridは、行と列を自動的に仮想化することにより、このレベルのパフォーマンスを実現します。

import 'bootstrap.css'; import '@mescius/wijmo.styles/wijmo.css'; import './styles.css'; //// import '@mescius/wijmo.touch'; import * as wjcCore from '@mescius/wijmo'; import * as wjcGrid from '@mescius/wijmo.grid'; import * as wjcGridFilter from '@mescius/wijmo.grid.filter'; import * as wjcGridSearch from '@mescius/wijmo.grid.search'; import * as wjcGridGroupPanel from '@mescius/wijmo.grid.grouppanel'; import * as wjcInput from '@mescius/wijmo.input'; import { CellMaker, SparklineMarkers } from '@mescius/wijmo.grid.cellmaker'; import { KeyValue, Country, DataService } from './data'; import { ExportService } from './export'; //// class App { constructor(dataSvc, exportSvc) { this._itemsCount = 500; this._lastId = this._itemsCount; this._dataSvc = dataSvc; this._exportSvc = exportSvc; // initializes data maps this._productMap = this._buildDataMap(this._dataSvc.getProducts()); this._countryMap = new wjcGrid.DataMap(this._dataSvc.getCountries(), 'id', 'name'); this._colorMap = this._buildDataMap(this._dataSvc.getColors()); // initializes cell templates this._historyCellTemplate = CellMaker.makeSparkline({ markers: SparklineMarkers.High | SparklineMarkers.Low, maxPoints: 25, label: 'price history', }); this._ratingCellTemplate = CellMaker.makeRating({ range: [1, 5], label: 'rating' }); // initializes data size document.getElementById('itemsCount').addEventListener('change', (e) => { const value = e.target.value; this._itemsCount = wjcCore.changeType(value, wjcCore.DataType.Number); this._handleItemsCountChange(); }); // initializes export const btnExportToExcel = document.getElementById('btnExportToExcel'); this._excelExportContext = new ExcelExportContext(btnExportToExcel); btnExportToExcel.addEventListener('click', () => { this._exportToExcel(); }); document.getElementById('btnExportToPdf').addEventListener('click', () => { this._exportToPdf(); }); // initializes the grid this._initializeGrid(); // initializes items source this._itemsSource = this._createItemsSource(); this._theGrid.itemsSource = this._itemsSource; } close() { const ctx = this._excelExportContext; this._exportSvc.cancelExcelExport(ctx); } _initializeGrid() { // creates the grid this._theGrid = new wjcGrid.FlexGrid('#theGrid', { autoGenerateColumns: false, allowAddNew: true, allowDelete: true, allowPinning: wjcGrid.AllowPinning.SingleColumn, newRowAtTop: true, showMarquee: true, selectionMode: wjcGrid.SelectionMode.MultiRange, validateEdits: false, columns: [ { binding: 'id', header: 'ID', width: 70, isReadOnly: true }, { binding: 'date', header: '日付', format: 'd', isRequired: false, width: 130, editor: new wjcInput.InputDate(document.createElement('div'), { format: 'd', isRequired: false }) }, { binding: 'countryId', header: '国', dataMap: this._countryMap, width: 145, cellTemplate: (ctx) => { const dataItem = ctx.row.dataItem; if (wjcCore.isUndefined(dataItem) || dataItem === null) { return ''; } const country = this._getCountry(ctx.item); return `<span class="flag-icon flag-icon-${country.flag}"></span> ${country.name}`; } }, { binding: 'price', header: '金額', format: 'c', isRequired: false, width: 100 }, { binding: 'history', header: '履歴', width: 180, align: 'center', allowSorting: false, cellTemplate: this._historyCellTemplate }, { binding: 'change', header: '変化量', align: 'right', width: 115, cellTemplate: (ctx) => { const dataItem = ctx.row.dataItem; if (wjcCore.isUndefined(dataItem) || dataItem === null) { return ''; } const cls = this._getChangeCls(ctx.value); const value = this._formatChange(ctx.value); return `<span class="${cls}">${value}</span>`; } }, { binding: 'rating', header: 'レーティング', width: 180, align: 'center', cssClass: 'cell-rating', cellTemplate: this._ratingCellTemplate }, { binding: 'time', header: '時刻', format: 'HH:mm', isRequired: false, width: 95, editor: new wjcInput.InputTime(document.createElement('div'), { format: 'HH:mm', isRequired: false }) }, { binding: 'colorId', header: '色', dataMap: this._colorMap, width: 145, cellTemplate: (ctx) => { const dataItem = ctx.row.dataItem; if (wjcCore.isUndefined(dataItem) || dataItem === null) { return ''; } const color = this._getColor(ctx.item); return `<span class="color-tile" style="background: ${['Black', 'White', 'Red', 'Green', 'Blue'][ctx.item.colorId]}"></span> ${color.value}`; } }, { binding: 'productId', header: '商品', dataMap: this._productMap, width: 145 }, { binding: 'discount', header: '値引', format: 'p0', width: 130 }, { binding: 'active', header: '有効', width: 100 } ] }); // create the grid search box new wjcGridSearch.FlexGridSearch('#theSearch', { placeholder: 'フィルター', grid: this._theGrid, cssMatch: '' }); // adds Excel-like filter new wjcGridFilter.FlexGridFilter(this._theGrid, { filterColumns: [ 'id', 'date', 'time', 'countryId', 'productId', 'colorId', 'price', 'change', 'discount', 'rating', 'active' ] }); // adds group panel new wjcGridGroupPanel.GroupPanel('#theGroupPanel', { placeholder: 'ここに列をドラッグするとグループを作成します', grid: this._theGrid }); } _getCountry(item) { const country = this._countryMap.getDataItem(item.countryId); return country ? country : Country.NotFound; } _getColor(item) { const color = this._colorMap.getDataItem(item.colorId); return color ? color : KeyValue.NotFound; } _getChangeCls(value) { if (wjcCore.isNumber(value)) { if (value > 0) { return 'change-up'; } if (value < 0) { return 'change-down'; } } return ''; } _formatChange(value) { if (wjcCore.isNumber(value)) { return wjcCore.Globalize.formatNumber(value, 'c'); } if (!wjcCore.isUndefined(value) && value !== null) { return wjcCore.changeType(value, wjcCore.DataType.String); } return ''; } _exportToExcel() { const ctx = this._excelExportContext; if (!ctx.exporting) { this._exportSvc.startExcelExport(this._theGrid, ctx); } else { this._exportSvc.cancelExcelExport(ctx); } } _exportToPdf() { this._exportSvc.exportToPdf(this._theGrid, { countryMap: this._countryMap, colorMap: this._colorMap, historyCellTemplate: this._historyCellTemplate }); } _createItemsSource() { const data = this._dataSvc.getData(this._itemsCount); const view = new wjcCore.CollectionView(data, { getError: (item, prop) => { const displayName = this._theGrid.columns.getColumn(prop).header; return this._dataSvc.validate(item, prop, displayName); } }); view.collectionChanged.addHandler((s, e) => { // initializes new added item with a history data if (e.action === wjcCore.NotifyCollectionChangedAction.Add) { e.item.history = this._dataSvc.getHistoryData(); e.item.id = this._lastId; this._lastId++; } }); return view; } _disposeItemsSource(itemsSource) { if (itemsSource) { itemsSource.collectionChanged.removeAllHandlers(); } } // build a data map from a string array using the indices as keys _buildDataMap(items) { const map = []; for (let i = 0; i < items.length; i++) { map.push({ key: i, value: items[i] }); } return new wjcGrid.DataMap(map, 'key', 'value'); } _handleItemsCountChange() { this._disposeItemsSource(this._itemsSource); this._lastId = this._itemsCount; this._itemsSource = this._createItemsSource(); this._theGrid.itemsSource = this._itemsSource; } } // class ExcelExportContext { constructor(btn) { this._exporting = false; this._progress = 0; this._preparing = false; this._btn = btn; } get exporting() { return this._exporting; } set exporting(value) { if (value !== this._exporting) { this._exporting = value; this._onPropertyChanged(); } } get progress() { return this._progress; } set progress(value) { if (value !== this._progress) { this._progress = value; this._onPropertyChanged(); } } get preparing() { return this._preparing; } set preparing(value) { if (value !== this._preparing) { this._preparing = value; this._onPropertyChanged(); } } _onPropertyChanged() { wjcCore.enable(this._btn, !this._preparing); if (this._exporting) { const percent = wjcCore.Globalize.formatNumber(this._progress, 'p0'); this._btn.textContent = `キャンセル (${percent} 完了)`; } else { this._btn.textContent = 'Excelにエクスポート'; } } } // document.readyState === 'complete' ? init() : window.onload = init; // function init() { const dataSvc = new DataService(); const exportSvc = new ExportService(); const app = new App(dataSvc, exportSvc); window.addEventListener('unload', () => { app.close(); }); }
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <title>MESCIUS Wijmo FlexGrid Overview</title> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <!-- SystemJS --> <script src="https://cdnjs.cloudflare.com/ajax/libs/systemjs/0.21.5/system.src.js" integrity="sha512-skZbMyvYdNoZfLmiGn5ii6KmklM82rYX2uWctBhzaXPxJgiv4XBwJnFGr5k8s+6tE1pcR1nuTKghozJHyzMcoA==" crossorigin="anonymous"></script> <script src="systemjs.config.js"></script> <script> System.import('./src/app'); </script> </head> <body> <div class="container-fluid"> <!-- filter/navigation --> <div class="row"> <!-- search box --> <div class="toolbar-item col-sm-3 col-md-5"> <div id="theSearch"></div> </div> <!-- data size --> <div class="toolbar-item col-sm-3 col-md-3"> <div class="input-group"> <span class="input-group-addon">データ数:</span> <select id="itemsCount" class="form-control"> <option value="5">5</option> <option value="50">50</option> <option value="500" selected>500</option> <option value="5000">5,000</option> <option value="50000">50,000</option> <option value="100000">100,000</option> </select> </div> </div> <!-- Excelにエクスポート --> <div class="toolbar-item col-sm-3 col-md-2"> <button id="btnExportToExcel" class="btn btn-default btn-block">Excelにエクスポート</button> </div> <!-- PDFにエクスポート --> <div class="toolbar-item col-sm-3 col-md-2"> <button id="btnExportToPdf" class="btn btn-default btn-block">PDFにエクスポート</button> </div> </div> <!-- the grid --> <div id="theGroupPanel"></div> <div id="theGrid"></div> </div> </body> </html>
import * as wjcCore from '@mescius/wijmo'; import { RequiredValidator, MinNumberValidator, MinDateValidator, MaxNumberValidator, MaxDateValidator } from './validation'; // export class KeyValue { } KeyValue.NotFound = { key: -1, value: '' }; // export class Country { } Country.NotFound = { id: -1, name: '', flag: '' }; // export class DataService { constructor() { this._products = ['ウィジェット', 'ガジェット', 'ツール']; this._colors = ['黒', '白', '赤', '緑', '青']; this._countries = [ { id: 0, name: 'アメリカ', flag: 'us' }, { id: 1, name: 'ドイツ', flag: 'de' }, { id: 2, name: 'イギリス', flag: 'gb' }, { id: 3, name: '日本', flag: 'jp' }, { id: 4, name: 'イタリア', flag: 'it' }, { id: 5, name: 'ギリシャ', flag: 'gr' } ]; this._validationConfig = { 'date': [ new RequiredValidator(), new MinDateValidator(new Date('2000-01-01T00:00:00')), new MaxDateValidator(new Date('2100-01-01T00:00:00')) ], 'time': [ new RequiredValidator(), new MinDateValidator(new Date('2000-01-01T00:00:00')), new MaxDateValidator(new Date('2100-01-01T00:00:00')) ], 'productId': [ new RequiredValidator(), new MinNumberValidator(0, `{0}は{1}(${this._products[0]})より小さくすることはできません`), new MaxNumberValidator(this._products.length - 1, `{0}は{1}(${this._products[this._products.length - 1]})より大きくすることはできません`) ], 'countryId': [ new RequiredValidator(), new MinNumberValidator(0, `{0}は{1}(${this._countries[0].name})より小さくすることはできません`), new MaxNumberValidator(this._countries.length - 1, `{0}は{1}(${this._countries[this._countries.length - 1].name})より大きくすることはできません`) ], 'colorId': [ new RequiredValidator(), new MinNumberValidator(0, `{0}は{1}(${this._colors[0]})より小さくすることはできません`), new MaxNumberValidator(this._colors.length - 1, `{0}は{1}(${this._colors[this._colors.length - 1]})より大きくすることはできません`) ], 'price': [ new RequiredValidator(), new MinNumberValidator(0, `金額を負の値にすることはできません`) ] }; } getCountries() { return this._countries; } getProducts() { return this._products; } getColors() { return this._colors; } getHistoryData() { return this._getRandomArray(25, 100); } getData(count) { const data = []; const dt = new Date(); const year = dt.getFullYear(); const itemsCount = Math.max(count, 5); // add items for (let i = 0; i < itemsCount; i++) { const item = this._getItem(i, year); data.push(item); } // set invalid data to demonstrate errors visualization data[1].price = -2000; data[2].date = new Date('1970-01-01T00:00:00'); data[4].time = undefined; data[4].price = -1000; return data; } validate(item, prop, displayName) { const validators = this._validationConfig[prop]; if (wjcCore.isUndefined(validators)) { return ''; } const value = item[prop]; for (let i = 0; i < validators.length; i++) { const validationError = validators[i].validate(displayName, value); if (!wjcCore.isNullOrWhiteSpace(validationError)) { return validationError; } } } _getItem(i, year) { const date = new Date(year, i % 12, 25, i % 24, i % 60, i % 60); const countryIndex = this._getRandomIndex(this._countries); const productIndex = this._getRandomIndex(this._products); const colorIndex = this._getRandomIndex(this._colors); const item = { id: i, date: date, time: new Date(date.getTime() + Math.random() * 30 * (24 * 60 * 60 * 1000)), countryId: this._countries[countryIndex].id, productId: productIndex, colorId: colorIndex, price: wjcCore.toFixed(Math.random() * 10000 + 5000, 2, true), change: wjcCore.toFixed(Math.random() * 1000 - 500, 2, true), history: this.getHistoryData(), discount: wjcCore.toFixed(Math.random() / 4, 2, true), rating: this._getRating(), active: i % 4 == 0, size: Math.floor(100 + Math.random() * 900), weight: Math.floor(100 + Math.random() * 900), quantity: Math.floor(Math.random() * 10), description: "すべてのソフトウェア製品とサービスにおいて、お客様の目標達成を支援することに重点を置いています。お客様のビジネス目標を完全に理解し、品質に重点を置き、最高の倫理基準を遵守するという私たちの主要な原則は、私たちが行うすべての基礎となります。" }; return item; } _getRating() { return Math.ceil(Math.random() * 5); } _getRandomIndex(arr) { return Math.floor(Math.random() * arr.length); } _getRandomArray(len, maxValue) { const arr = []; for (let i = 0; i < len; i++) { arr.push(Math.floor(Math.random() * maxValue)); } return arr; } }
@import 'https://cdnjs.cloudflare.com/ajax/libs/flag-icon-css/3.1.0/css/flag-icon.css'; body { font-size: 1.5em; font-family: -apple-system, BlinkMacSystemFont, "Segoe UI Light", Roboto, Oxygen-Sans, Ubuntu, Cantarell, "Helvetica Neue", sans-serif; } .toolbar-item { margin-bottom: 6px; } .wj-flexgridsearch { width: 100%; } .wj-flexgrid { height: 330px; } .wj-flexgrid .wj-cell { padding: 7px; border: none; } .wj-cell.wj-state-invalid:not(.wj-header)::after { top: -14px; border: 14px solid transparent; border-right-color: red; } .flag-icon { box-shadow: 1px 1px 4px rgba(0, 0, 0, 0.4); } .color-tile { display: inline-block; position: relative; width: 1em; height: 1em; border-radius: 50%; box-shadow: 1px 1px 4px rgba(0, 0, 0, 0.4); vertical-align: middle; } .change-up { color: darkgreen; } .change-up:after { content: '\25b2'; margin-left: 0.5em; } .change-down { color: darkred; } .change-down:after { content: '\25bc'; margin-left: 0.5em; } .cell-rating { font-size: 12px; } .wj-flexgrid .wj-detail { padding: 4px 16px; } .wj-detail h3 { margin: 10px 0; }
import * as wjcCore from '@mescius/wijmo'; import * as wjcGrid from '@mescius/wijmo.grid'; import * as wjcGridPdf from '@mescius/wijmo.grid.pdf'; import * as wjcGridXlsx from '@mescius/wijmo.grid.xlsx'; import * as wjcPdf from '@mescius/wijmo.pdf'; import * as wjcXlsx from '@mescius/wijmo.xlsx'; import { KeyValue, Country } from './data'; // const ExcelExportDocName = 'FlexGrid.xlsx'; const PdfExportDocName = 'FlexGrid.pdf'; const FakeColumn = new wjcGrid.Column(); const FakeRow = new wjcGrid.Row(); // class Fonts { } Fonts.ZapfDingbatsSm = new wjcPdf.PdfFont('zapfdingbats', 8, 'normal', 'normal'); Fonts.ZapfDingbatsLg = new wjcPdf.PdfFont('zapfdingbats', 16, 'normal', 'normal'); Fonts.Ipaexg = new wjcPdf.PdfFont('ipaexg'); // export class IExcelExportContext { } // export class ExportService { startExcelExport(flex, ctx) { if (ctx.preparing || ctx.exporting) { return; } ctx.exporting = false; ctx.progress = 0; ctx.preparing = true; wjcGridXlsx.FlexGridXlsxConverter.saveAsync(flex, { includeColumnHeaders: true, includeStyles: false, formatItem: this._formatExcelItem.bind(this) }, ExcelExportDocName, () => { console.log('Excelエクスポートが完了しました'); this._resetExcelContext(ctx); }, err => { console.error(`Excelエクスポートが失敗しました: ${err}`); this._resetExcelContext(ctx); }, prg => { if (ctx.preparing) { ctx.exporting = true; ctx.preparing = false; } ctx.progress = prg / 100.; }, true); console.log('Excelエクスポートが開始されました'); } cancelExcelExport(ctx) { wjcGridXlsx.FlexGridXlsxConverter.cancelAsync(() => { this._resetExcelContext(ctx); }); } exportToPdf(flex, options) { wjcGridPdf.FlexGridPdfConverter.export(flex, PdfExportDocName, { embeddedFonts: [{ source: 'https://demo.mescius.jp/wijmo/sample/fonts/ipaexg.ttf', name: 'ipaexg' }], maxPages: 100, exportMode: wjcGridPdf.ExportMode.All, scaleMode: wjcGridPdf.ScaleMode.ActualSize, documentOptions: { pageSettings: { layout: wjcPdf.PdfPageOrientation.Landscape }, header: { declarative: { text: '\t&[Page] / &[Pages]' } }, footer: { declarative: { text: '\t&[Page] / &[Pages]' } } }, styles: { cellStyle: { font: { family: 'ipaexg' }, backgroundColor: '#ffffff', borderColor: '#c6c6c6' }, altCellStyle: { backgroundColor: '#f9f9f9' }, groupCellStyle: { backgroundColor: '#dddddd' }, headerCellStyle: { backgroundColor: '#eaeaea' }, // Highlight Invalid Cells errorCellStyle: { backgroundColor: 'rgba(255, 0, 0, 0.3)' } }, customCellContent: false, formatItem: (e) => this._formatPdfItem(e, options) }); } _formatExcelItem(e) { const panel = e.panel; if (panel.cellType !== wjcGrid.CellType.Cell) { return; } // highlight invalid cells if (panel.grid._getError(panel, e.row, e.col)) { const fill = new wjcXlsx.WorkbookFill(); fill.color = '#ff0000'; e.xlsxCell.style.fill = fill; } } _resetExcelContext(ctx) { ctx.exporting = false; ctx.progress = 0; ctx.preparing = false; } _formatPdfItem(e, options) { const panel = e.panel; if (panel.cellType !== wjcGrid.CellType.Cell) { return; } switch (panel.columns[e.col].binding) { case 'countryId': this._formatPdfCountryCell(e, options.countryMap); break; case 'colorId': this._formatPdfColorCell(e, options.colorMap); break; case 'change': this._formatPdfChangeCell(e); break; case 'history': /*** Version #1: get grid cell produced before by a cell template ***/ // const cell = e.getFormattedCell(); // this._formatPdfHistoryCell(e, cell); /*** Version #2: create fake cell from a cell template ***/ const history = e.panel.getCellData(e.row, e.col, false); const cell = this._createCellFromCellTemplate(options.historyCellTemplate, history); this._formatPdfHistoryCell(e, cell); break; case 'rating': this._formatPdfRatingCell(e); break; } } _formatPdfCountryCell(e, countryMap) { e.drawBackground(e.style.backgroundColor); // check whether country exists const countryName = e.data; if (this._isCountryExist(countryName, countryMap)) { // bound rectangle of cell's content area const contentRect = e.contentRect; // draw flag image const image = e.canvas.openImage(`resources/${['us', 'germany', 'uk', 'japan', 'italy', 'greece'][countryMap.getKeyValue(countryName)]}.png`); const imageTop = contentRect.top + (contentRect.height - image.height) / 2; e.canvas.drawImage(image, contentRect.left, imageTop); // draw country name e.canvas.drawText(countryName, contentRect.left + image.width + 3, e.textTop, { font: Fonts.Ipaexg }); } // cancel standard cell content drawing e.cancel = true; } _formatPdfColorCell(e, colorMap) { e.drawBackground(e.style.backgroundColor); // check whether color exists const colorName = e.data; if (this._isColorExist(colorName, colorMap)) { // bound rectangle of cell's content area const contentRect = e.contentRect; // draw color indicator const imageHeight = Math.min(10, contentRect.height); const imageWidth = 1.33 * imageHeight; const imageTop = contentRect.top + (contentRect.height - imageHeight) / 2; e.canvas.paths .rect(contentRect.left, imageTop, imageWidth, imageHeight) .fillAndStroke(wjcCore.Color.fromString(['Black', 'White', 'Red', 'Green', 'Blue'][colorMap.getKeyValue(colorName)]), wjcCore.Color.fromString('gray')); // draw color name e.canvas.drawText(colorName, contentRect.left + imageWidth + 3, e.textTop, { font: Fonts.Ipaexg }); } // cancel standard cell content drawing e.cancel = true; } _formatPdfChangeCell(e) { e.drawBackground(e.style.backgroundColor); // get change value and text const cellData = e.panel.getCellData(e.row, e.col, false); let change = 0; let changeText = ''; if (wjcCore.isNumber(cellData)) { change = cellData; changeText = wjcCore.Globalize.formatNumber(change, 'c'); } else if (!wjcCore.isUndefined(cellData) && cellData !== null) { changeText = wjcCore.changeType(cellData, wjcCore.DataType.String); } // determine whether change is positive or negative let changeIndicator = ''; let changeColor = e.style.color; if (change > 0) { changeIndicator = '\x73'; // ▲ changeColor = 'darkgreen'; } else if (change < 0) { changeIndicator = '\x74'; // ▼ changeColor = 'darkred'; } // draw change indicator let indent = 10; e.canvas.drawText(changeIndicator, e.contentRect.right - indent, e.contentRect.top + indent, { brush: changeColor, font: Fonts.ZapfDingbatsSm }); // draw change text indent += 3; e.canvas.drawText(changeText, e.contentRect.left, e.textTop, { brush: changeColor, align: wjcPdf.PdfTextHorizontalAlign.Right, width: e.contentRect.width - indent }); // cancel standard cell content drawing e.cancel = true; } _formatPdfHistoryCell(e, cell) { e.drawBackground(e.style.backgroundColor); // draw history svg const svgUrl = this._getHistorySvgDataUrlFromCell(cell, e.clientRect.width, e.clientRect.height); if (svgUrl) { let cr = e.contentRect; e.canvas.drawSvg(svgUrl, cr.left + 2, cr.top + 2, { width: cr.width - 4, height: cr.height - 4 }); } // cancel standard cell content drawing e.cancel = true; } _getHistorySvgDataUrlFromCell(cell, width, height) { let dataUrl = null; // extract SVG from provided cell const svg = cell.getElementsByTagName('svg')[0]; if (svg) { const clone = svg.cloneNode(true); clone.setAttribute('version', '1.1'); clone.setAttributeNS('http://www.w3.org/2000/xmlns/', 'xmlns', 'http://www.w3.org/2000/svg'); clone.style.overflow = 'visible'; clone.style.stroke = '#376092'; clone.style.fill = '#376092'; const s = document.createElement('style'); s.setAttribute('type', 'text/css'); s.innerHTML = `<![CDATA[ line { stroke-width: 2; } circle { stroke-width: 0; stroke-opacity: 0; } .wj-marker { fill: #d00000; opacity: 1; } ]]>`; const defs = document.createElement('defs'); defs.appendChild(s); clone.insertBefore(defs, clone.firstChild); const outer = document.createElement('div'); outer.appendChild(clone); dataUrl = 'data:image/svg+xml;base64,' + btoa(unescape(encodeURIComponent(outer.innerHTML))); } return dataUrl; } _formatPdfRatingCell(e) { e.drawBackground(e.style.backgroundColor); // check whether rating is defined let rating = wjcCore.changeType(e.data, wjcCore.DataType.Number); if (wjcCore.isInt(rating)) { const ratingIndicator = '\x48'; // ★ const ratingNormalColor = wjcCore.Color.fromRgba(255, 165, 0, 1); // orange const ratingLightColor = wjcCore.Color.fromRgba(255, 165, 0, 0.2); // draw rating indicators const indent = 16; const count = 5; const width = count * indent; const y = e.clientRect.top + indent; let x = e.contentRect.left + (e.contentRect.width - width) / 2; rating = wjcCore.clamp(rating, 1, count); for (let i = 0; i < count; i++) { e.canvas.drawText(ratingIndicator, x, y, { brush: (i < rating) ? ratingNormalColor : ratingLightColor, font: Fonts.ZapfDingbatsLg, height: e.clientRect.height }); x += indent; } } // cancel standard cell content drawing e.cancel = true; } _isCountryExist(countryName, countryMap) { const countryId = countryMap.getKeyValue(countryName); if (wjcCore.isUndefined(countryId) || countryId === null) { return false; } if (countryId === Country.NotFound.id) { return false; } return true; } _isColorExist(colorName, colorMap) { const colorId = colorMap.getKeyValue(colorName); if (wjcCore.isUndefined(colorId) || colorId === null) { return false; } if (colorId === KeyValue.NotFound.key) { return false; } return true; } _createCellFromCellTemplate(cellTemplate, data) { const cell = document.createElement('div'); cellTemplate({ col: FakeColumn, row: FakeRow, value: data, item: null, text: null }, cell); return cell; } }
import * as wjcCore from '@mescius/wijmo'; export class RequiredValidator { validate(name, value) { const message = name + 'は入力必須です'; if (wjcCore.isUndefined(value)) { return message; } const str = wjcCore.changeType(value, wjcCore.DataType.String); if (wjcCore.isNullOrWhiteSpace(str)) { return message; } return ''; } } export class MinValueValidator { constructor(minValue, message = '{0}は{1}より小さくすることはできません', format = null) { this.minValue = minValue; this.message = message; this.format = format; } validate(name, value) { if (value < this.minValue) { return wjcCore.format(this.message, { 0: name, 1: this._formatValue(this.minValue) }); } return ''; } } export class MaxValueValidator { constructor(maxValue, message = '{0}は{1}より大きくすることはできません', format = null) { this.maxValue = maxValue; this.message = message; this.format = format; } validate(name, value) { if (value > this.maxValue) { return wjcCore.format(this.message, { 0: name, 1: this._formatValue(this.maxValue) }); } return ''; } } export class MinNumberValidator extends MinValueValidator { constructor(minValue, message = '{0}は{1}より小さくすることはできません', format = 'n') { super(minValue, message, format); } _formatValue(value) { return wjcCore.Globalize.formatNumber(value, this.format); } } export class MaxNumberValidator extends MaxValueValidator { constructor(maxValue, message = '{0}は{1}より大きくすることはできません', format = 'n') { super(maxValue, message, format); } _formatValue(value) { return wjcCore.Globalize.formatNumber(value, this.format); } } export class MinDateValidator extends MinValueValidator { constructor(minValue, message = '{0}は{1}より小さくすることはできません', format = 'd') { super(minValue, message, format); } _formatValue(value) { return wjcCore.Globalize.formatDate(value, this.format); } } export class MaxDateValidator extends MaxValueValidator { constructor(maxValue, message = '{0}は{1}より大きくすることはできません', format = 'd') { super(maxValue, message, format); } _formatValue(value) { return wjcCore.Globalize.formatDate(value, this.format); } }
(function (global) { System.config({ transpiler: 'plugin-babel', babelOptions: { es2015: true }, meta: { '*.css': { loader: 'css' } }, paths: { // paths serve as alias 'npm:': 'node_modules/' }, // map tells the System loader where to look for things map: { 'jszip': 'npm:jszip/dist/jszip.js', '@mescius/wijmo': 'npm:@mescius/wijmo/index.js', '@mescius/wijmo.input': 'npm:@mescius/wijmo.input/index.js', '@mescius/wijmo.styles': 'npm:@mescius/wijmo.styles', '@mescius/wijmo.cultures': 'npm:@mescius/wijmo.cultures', '@mescius/wijmo.chart': 'npm:@mescius/wijmo.chart/index.js', '@mescius/wijmo.chart.analytics': 'npm:@mescius/wijmo.chart.analytics/index.js', '@mescius/wijmo.chart.animation': 'npm:@mescius/wijmo.chart.animation/index.js', '@mescius/wijmo.chart.annotation': 'npm:@mescius/wijmo.chart.annotation/index.js', '@mescius/wijmo.chart.finance': 'npm:@mescius/wijmo.chart.finance/index.js', '@mescius/wijmo.chart.finance.analytics': 'npm:@mescius/wijmo.chart.finance.analytics/index.js', '@mescius/wijmo.chart.hierarchical': 'npm:@mescius/wijmo.chart.hierarchical/index.js', '@mescius/wijmo.chart.interaction': 'npm:@mescius/wijmo.chart.interaction/index.js', '@mescius/wijmo.chart.radar': 'npm:@mescius/wijmo.chart.radar/index.js', '@mescius/wijmo.chart.render': 'npm:@mescius/wijmo.chart.render/index.js', '@mescius/wijmo.chart.webgl': 'npm:@mescius/wijmo.chart.webgl/index.js', '@mescius/wijmo.chart.map': 'npm:@mescius/wijmo.chart.map/index.js', '@mescius/wijmo.gauge': 'npm:@mescius/wijmo.gauge/index.js', '@mescius/wijmo.grid': 'npm:@mescius/wijmo.grid/index.js', '@mescius/wijmo.grid.detail': 'npm:@mescius/wijmo.grid.detail/index.js', '@mescius/wijmo.grid.filter': 'npm:@mescius/wijmo.grid.filter/index.js', '@mescius/wijmo.grid.search': 'npm:@mescius/wijmo.grid.search/index.js', '@mescius/wijmo.grid.grouppanel': 'npm:@mescius/wijmo.grid.grouppanel/index.js', '@mescius/wijmo.grid.multirow': 'npm:@mescius/wijmo.grid.multirow/index.js', '@mescius/wijmo.grid.transposed': 'npm:@mescius/wijmo.grid.transposed/index.js', '@mescius/wijmo.grid.transposedmultirow': 'npm:@mescius/wijmo.grid.transposedmultirow/index.js', '@mescius/wijmo.grid.pdf': 'npm:@mescius/wijmo.grid.pdf/index.js', '@mescius/wijmo.grid.sheet': 'npm:@mescius/wijmo.grid.sheet/index.js', '@mescius/wijmo.grid.xlsx': 'npm:@mescius/wijmo.grid.xlsx/index.js', '@mescius/wijmo.grid.selector': 'npm:@mescius/wijmo.grid.selector/index.js', '@mescius/wijmo.grid.cellmaker': 'npm:@mescius/wijmo.grid.cellmaker/index.js', '@mescius/wijmo.nav': 'npm:@mescius/wijmo.nav/index.js', '@mescius/wijmo.odata': 'npm:@mescius/wijmo.odata/index.js', '@mescius/wijmo.olap': 'npm:@mescius/wijmo.olap/index.js', '@mescius/wijmo.rest': 'npm:@mescius/wijmo.rest/index.js', '@mescius/wijmo.pdf': 'npm:@mescius/wijmo.pdf/index.js', '@mescius/wijmo.pdf.security': 'npm:@mescius/wijmo.pdf.security/index.js', '@mescius/wijmo.viewer': 'npm:@mescius/wijmo.viewer/index.js', '@mescius/wijmo.xlsx': 'npm:@mescius/wijmo.xlsx/index.js', '@mescius/wijmo.undo': 'npm:@mescius/wijmo.undo/index.js', '@mescius/wijmo.interop.grid': 'npm:@mescius/wijmo.interop.grid/index.js', '@mescius/wijmo.touch': 'npm:@mescius/wijmo.touch/index.js', '@mescius/wijmo.cloud': 'npm:@mescius/wijmo.cloud/index.js', '@mescius/wijmo.barcode': 'npm:@mescius/wijmo.barcode/index.js', '@mescius/wijmo.barcode.common': 'npm:@mescius/wijmo.barcode.common/index.js', '@mescius/wijmo.barcode.composite': 'npm:@mescius/wijmo.barcode.composite/index.js', '@mescius/wijmo.barcode.specialized': 'npm:@mescius/wijmo.barcode.specialized/index.js', 'jszip': 'npm:jszip/dist/jszip.js', 'bootstrap.css': 'npm:bootstrap/dist/css/bootstrap.min.css', 'css': 'npm:systemjs-plugin-css/css.js', 'plugin-babel': 'npm:systemjs-plugin-babel/plugin-babel.js', 'systemjs-babel-build':'npm:systemjs-plugin-babel/systemjs-babel-browser.js' }, // packages tells the System loader how to load when no filename and/or no extension packages: { src: { defaultExtension: 'js' }, "node_modules": { defaultExtension: 'js' }, } }); })(this);