diff --git a/Samples-Typescript/VizImage/VizImage.trex b/Samples-Typescript/VizImage/VizImage.trex new file mode 100644 index 00000000..fdddc5f3 --- /dev/null +++ b/Samples-Typescript/VizImage/VizImage.trex @@ -0,0 +1,19 @@ + + + + en_US + + Viz Image Sample + + 1.6 + + http://localhost:8765/Samples-Typescript/VizImage/vizImage.html + + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEwAACxMBAJqcGAAAAlhJREFUOI2Nkt9vy1EYh5/3bbsvRSySCZbIxI+ZCKsN2TKtSFyIrV2WuRCJuBiJWxfuxCVXbvwFgiEtposgLFJElnbU1SxIZIIRJDKTrdu+53Uhra4mce7Oe57Pcz7JOULFisViwZ+29LAzOSjQYDgz1ZcCvWuXV11MJpN+OS/lm6179teqH0yDqxPTCyKSA8DcDsyOmOprnCaeP7459pdgy969i0LTC3IO/RQMyoHcQN+3cnljW3dNIFC47qDaK3g7BwdTkwBaBELT4ZPOUVWgKl4ZBnjxJPUlMDnTDrp0pmr6RHFeEjjcUUXPDGeSEwDN0Xg8sivxMhJNjGzbHd8PkM3eHRfkrBM5NkcQaY2vUnTlrDIA0NoaX+KLXFFlowr14tvVpqb2MICzmQcKqxvbumv+NAhZGCCIPwEw6QWXKYRL/VUXO0+rAUJiPwAk5MIlgVfwPjjHLCL1APmHN94ZdqeYN+NW/mn6I4BvwQYchcLnwFhJMDiYmlRxAzjpKWZkYkUCcZ2I61wi37tLbYyjiN0fHk5Oz3nGSLSzBbNHCF35R7f6K1/hN9PRhek11FrymfQQQKB4+Gl05P2qNRtmETlXW7e+b2z01dfycGNbfFMAbqNyKp9Jp4rzOT8RYFs0njJkc2iqsCObvTsOsDWWqA5C1uFy+Uz/oXJeKwVT4h0RmPUXhi79vuC0Ku6yOffTK3g9lfxfDQAisY516sg5kfOCiJk7HoLt2cf9b/9LANAc7dznm98PagG1fUOZ9IP5uMB8Q4CPoyNvausapkTt3rNMuvdf3C/o6+czhtdwmwAAAABJRU5ErkJggg== + + + + Viz Image Sample + + + diff --git a/Samples-Typescript/VizImage/vizImage.html b/Samples-Typescript/VizImage/vizImage.html new file mode 100644 index 00000000..77062d2e --- /dev/null +++ b/Samples-Typescript/VizImage/vizImage.html @@ -0,0 +1,48 @@ + + + + + + + Viz Image Sample + + + + + + + + + + + + + + + +
+

Viz Image Sample

+
+ + + +
+
+
+
+ + diff --git a/Samples-Typescript/VizImage/vizImage.ts b/Samples-Typescript/VizImage/vizImage.ts new file mode 100644 index 00000000..ab0484c1 --- /dev/null +++ b/Samples-Typescript/VizImage/vizImage.ts @@ -0,0 +1,92 @@ +import { MarkType } from '@tableau/extensions-api-types'; + +// Wrap everything in an anonymous function to avoid polluting the global namespace +(async () => { + class VizImage { + // Avoid globals. + constructor(private _$: JQueryStatic) { } + + /** + * Initializes the extension + */ + public async initialize() { + console.log('Waiting for DOM ready'); + await this._$.ready; + console.log('Initializing extension API'); + await tableau.extensions.initializeAsync(); + + await this.addVizImage(tableau.MarkType.Bar, 'tableau20_10_0'); + + const markSelector = this._$('#mark-select'); + const colorSelector = this._$('#color-select'); + + markSelector.prop('disabled', false); + colorSelector.prop('disabled', false); + + // updating viz images with new values upon a selector change + markSelector.change(() => { + this.addVizImage(markSelector.val() as MarkType, colorSelector.val() as string); + }); + colorSelector.change(() => { + this.addVizImage(markSelector.val() as MarkType, colorSelector.val() as string); + }); + } + + /** + * Builds the input specifications and displays the created viz image + * @param markType + * @param colorPalette + */ + private async addVizImage(markType: MarkType, palette: string) { + // Building the input specification object that is used to create the viz image + // Data values used in the viz image are prefilled + const vizInputSpec = { + data: { + values: [ + {Product: 'Paper', Sales: 28, Region: 'Central'}, + {Product: 'Pens', Sales: 45, Region: 'East'}, + {Product: 'Rulers', Sales: 35, Region: 'East'}, + {Product: 'Rulers', Sales: 43, Region: 'South'}, + {Product: 'Paper', Sales: 50, Region: 'West'}, + {Product: 'Pens', Sales: 56, Region: 'West'} + ] + }, + description: 'A sample viz', // optional parameter + encoding: { + color: {field: 'Product', type: tableau.VizImageEncodingType.Discrete, palette}, + columns: {field: 'Region', type: tableau.VizImageEncodingType.Discrete}, + rows: {field: 'Sales', type: tableau.VizImageEncodingType.Continuous} + }, + mark: markType, + markcolor: '#FFED5F', // may not get used in viz if color is encoded in viz + size: {width: 400, height: 300} + }; + + // defaulting values if null + if (markType === null) { + vizInputSpec.mark = tableau.MarkType.Bar; + } + if (palette === null) { + vizInputSpec.encoding.color.palette = 'tableau20_10_0'; + } + + const svg = await tableau.extensions.createVizImageAsync(vizInputSpec); + // making call to create viz image from the input specifications + const blob = new Blob([svg], { type: 'image/svg+xml' }); + const url = URL.createObjectURL(blob); + const image = document.createElement('img'); + image.src = url; + image.style.maxWidth = '100%'; + image.style.maxHeight = '100%'; + image.className = 'center-block'; + const vizApiElement = document.getElementById('viz-container'); + // clearing UI and adding in new viz + vizApiElement.innerHTML = ''; + vizApiElement.appendChild(image); + image.addEventListener('load', () => URL.revokeObjectURL(url), { once: true }); + } + } + + console.log('Initializing VizImage extension.'); + await new VizImage($).initialize(); +})(); diff --git a/Samples/VizImage/VizImage.trex b/Samples/VizImage/VizImage.trex new file mode 100644 index 00000000..684f9612 --- /dev/null +++ b/Samples/VizImage/VizImage.trex @@ -0,0 +1,19 @@ + + + + en_US + + Viz Image Sample + + 1.6 + + http://localhost:8765/Samples/VizImage/vizImage.html + + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEwAACxMBAJqcGAAAAlhJREFUOI2Nkt9vy1EYh5/3bbsvRSySCZbIxI+ZCKsN2TKtSFyIrV2WuRCJuBiJWxfuxCVXbvwFgiEtposgLFJElnbU1SxIZIIRJDKTrdu+53Uhra4mce7Oe57Pcz7JOULFisViwZ+29LAzOSjQYDgz1ZcCvWuXV11MJpN+OS/lm6179teqH0yDqxPTCyKSA8DcDsyOmOprnCaeP7459pdgy969i0LTC3IO/RQMyoHcQN+3cnljW3dNIFC47qDaK3g7BwdTkwBaBELT4ZPOUVWgKl4ZBnjxJPUlMDnTDrp0pmr6RHFeEjjcUUXPDGeSEwDN0Xg8sivxMhJNjGzbHd8PkM3eHRfkrBM5NkcQaY2vUnTlrDIA0NoaX+KLXFFlowr14tvVpqb2MICzmQcKqxvbumv+NAhZGCCIPwEw6QWXKYRL/VUXO0+rAUJiPwAk5MIlgVfwPjjHLCL1APmHN94ZdqeYN+NW/mn6I4BvwQYchcLnwFhJMDiYmlRxAzjpKWZkYkUCcZ2I61wi37tLbYyjiN0fHk5Oz3nGSLSzBbNHCF35R7f6K1/hN9PRhek11FrymfQQQKB4+Gl05P2qNRtmETlXW7e+b2z01dfycGNbfFMAbqNyKp9Jp4rzOT8RYFs0njJkc2iqsCObvTsOsDWWqA5C1uFy+Uz/oXJeKwVT4h0RmPUXhi79vuC0Ku6yOffTK3g9lfxfDQAisY516sg5kfOCiJk7HoLt2cf9b/9LANAc7dznm98PagG1fUOZ9IP5uMB8Q4CPoyNvausapkTt3rNMuvdf3C/o6+czhtdwmwAAAABJRU5ErkJggg== + + + + Viz Image Sample + + + diff --git a/Samples/VizImage/vizImage.html b/Samples/VizImage/vizImage.html new file mode 100644 index 00000000..df3d5ade --- /dev/null +++ b/Samples/VizImage/vizImage.html @@ -0,0 +1,48 @@ + + + + + + + Viz Image Sample + + + + + + + + + + + + + + + +
+

Viz Image Sample

+
+ + + +
+
+
+
+ + diff --git a/Samples/VizImage/vizImage.js b/Samples/VizImage/vizImage.js new file mode 100644 index 00000000..00117564 --- /dev/null +++ b/Samples/VizImage/vizImage.js @@ -0,0 +1,77 @@ +'use strict'; + +// Wrap everything in an anonymous function to avoid polluting the global namespace +(function () { + $(document).ready(function () { + tableau.extensions.initializeAsync().then(function () { + addVizImage(tableau.MarkType.Bar, 'tableau20_10_0'); + + let markSelector = $('#mark-select'); + let colorSelector = $('#color-select'); + + markSelector.prop('disabled', false); + colorSelector.prop('disabled', false); + + // updating viz images with new values upon a selector change. + markSelector.change(function () { + addVizImage(markSelector.val(), colorSelector.val()); + }); + colorSelector.change(function () { + addVizImage(markSelector.val(), colorSelector.val()); + }); + }); + }); + + // This function creates and displays a viz image. + function addVizImage (markType, palette) { + // Building the input specification object that is used to create the viz image. + // Data values used in the viz image are prefilled. + const vizInputSpec = { + description: 'A sample viz', // optional parameter. + size: {width: 400, height: 300}, + data: { + values: [ + {'Product': 'Paper', 'Sales': 28, 'Region': 'Central'}, + {'Product': 'Pens', 'Sales': 45, 'Region': 'East'}, + {'Product': 'Rulers', 'Sales': 35, 'Region': 'East'}, + {'Product': 'Rulers', 'Sales': 43, 'Region': 'South'}, + {'Product': 'Paper', 'Sales': 50, 'Region': 'West'}, + {'Product': 'Pens', 'Sales': 56, 'Region': 'West'} + ] + }, + mark: markType, + markcolor: '#FFED5F', // may not get used in viz if color is encoded in viz. + encoding: { + columns: {field: 'Region', type: tableau.VizImageEncodingType.Discrete}, + rows: {field: 'Sales', type: tableau.VizImageEncodingType.Continuous}, + color: {field: 'Product', type: tableau.VizImageEncodingType.Discrete, palette} + } + }; + + // defaulting values if null. + if (markType === null) { + vizInputSpec.mark = tableau.MarkType.Bar; + } + if (palette === null) { + vizInputSpec.encoding.color.palette = 'tableau20_10_0'; + } + + // making call to create viz image from the input specifications. + tableau.extensions.createVizImageAsync(vizInputSpec).then(function (svg) { + var blob = new Blob([svg], { type: 'image/svg+xml' }); + var url = URL.createObjectURL(blob); + var image = document.createElement('img'); + image.src = url; + image.style.maxWidth = '100%'; + image.style.maxHeight = '100%'; + image.className = 'center-block'; + var vizApiElement = document.getElementById('viz-container'); + // clearing UI and adding in new viz. + vizApiElement.innerHTML = ''; + vizApiElement.appendChild(image); + image.addEventListener('load', function () { return URL.revokeObjectURL(url); }, { once: true }); + }, function (err) { + console.log(err); + }); + } +})(); diff --git a/package-lock.json b/package-lock.json index 57670803..2fe90cc1 100644 --- a/package-lock.json +++ b/package-lock.json @@ -92,9 +92,9 @@ } }, "@tableau/tabextsandbox": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@tableau/tabextsandbox/-/tabextsandbox-1.1.0.tgz", - "integrity": "sha512-uWo+JsyCHhBg2bNBt6Y47Drv1AM7CuOZ0veTy88tu+dMYTI3SApL0J/eWajJmSz9EAs+ZLxYzQLO0auTb2nnGw==", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@tableau/tabextsandbox/-/tabextsandbox-1.2.1.tgz", + "integrity": "sha512-psZ8OVb1fcJvcQnSbZXW2LzDBivr5YYUTrt+6H8iiRepILmuC19HYvuPXTu2JFKliUD9fnVrsm/wRrMn6NhXrQ==", "dev": true, "requires": { "ejs": "^2.6.1", diff --git a/package.json b/package.json index 5cb7edef..3692fdc4 100644 --- a/package.json +++ b/package.json @@ -22,7 +22,7 @@ }, "devDependencies": { "@tableau/extensions-api-types": "1.6.0", - "@tableau/tabextsandbox": "^1.1.0", + "@tableau/tabextsandbox": "^1.2.1", "@types/jquery": "^3.3.29", "concurrently": "^6.2.1", "semistandard": "^11.0.0", diff --git a/webpack.config.js b/webpack.config.js index ec4bb526..86e46f9b 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -7,6 +7,7 @@ module.exports = { datasources: './Samples-Typescript/DataSources/datasources.ts', filtering: './Samples-Typescript/Filtering/filtering.ts', parameters: './Samples-Typescript/Parameters/parameters.ts', + vizImage: './Samples-Typescript/VizImage/vizImage.ts', }, mode: 'production', output: {