UNPKG

@jaxolotl/wdclib

Version:

Required Library to bridge javascript with Tableau. Use the scripts below to create the combined shim library. i.e. npm run-script build_and_copy

1,352 lines (1,124 loc) 124 kB
/*! Build Number: 2.1.0 */ /******/ (function(modules) { // webpackBootstrap /******/ // The module cache /******/ var installedModules = {}; /******/ // The require function /******/ function __webpack_require__(moduleId) { /******/ // Check if module is in cache /******/ if(installedModules[moduleId]) /******/ return installedModules[moduleId].exports; /******/ // Create a new module (and put it into the cache) /******/ var module = installedModules[moduleId] = { /******/ exports: {}, /******/ id: moduleId, /******/ loaded: false /******/ }; /******/ // Execute the module function /******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__); /******/ // Flag the module as loaded /******/ module.loaded = true; /******/ // Return the exports of the module /******/ return module.exports; /******/ } /******/ // expose the modules object (__webpack_modules__) /******/ __webpack_require__.m = modules; /******/ // expose the module cache /******/ __webpack_require__.c = installedModules; /******/ // __webpack_public_path__ /******/ __webpack_require__.p = ""; /******/ // Load entry module and return exports /******/ return __webpack_require__(0); /******/ }) /************************************************************************/ /******/ ([ /* 0 */ /***/ function(module, exports, __webpack_require__) { // Main entry point to pull together everything needed for the WDC shim library // This file will be exported as a bundled js file by webpack so it can be included // in a <script> tag in an html document. Alernatively, a connector may include // this whole package in their code and would need to call init like this var tableauwdc = __webpack_require__(16); tableauwdc.init(); /***/ }, /* 1 */ /***/ function(module, exports) { /** This file lists all of the enums which should available for the WDC */ var allEnums = { phaseEnum : { interactivePhase: "interactive", authPhase: "auth", gatherDataPhase: "gatherData" }, authPurposeEnum : { ephemeral: "ephemeral", enduring: "enduring" }, authTypeEnum : { none: "none", basic: "basic", custom: "custom" }, dataTypeEnum : { bool: "bool", date: "date", datetime: "datetime", float: "float", int: "int", string: "string" }, columnRoleEnum : { dimension: "dimension", measure: "measure" }, columnTypeEnum : { continuous: "continuous", discrete: "discrete" }, aggTypeEnum : { sum: "sum", avg: "avg", median: "median", count: "count", countd: "count_dist" }, geographicRoleEnum : { area_code: "area_code", cbsa_msa: "cbsa_msa", city: "city", congressional_district: "congressional_district", country_region: "country_region", county: "county", state_province: "state_province", zip_code_postcode: "zip_code_postcode", latitude: "latitude", longitude: "longitude" }, unitsFormatEnum : { thousands: "thousands", millions: "millions", billions_english: "billions_english", billions_standard: "billions_standard" }, numberFormatEnum : { number: "number", currency: "currency", scientific: "scientific", percentage: "percentage" }, localeEnum : { america: "en-us", brazil: "pt-br", china: "zh-cn", france: "fr-fr", germany: "de-de", japan: "ja-jp", korea: "ko-kr", spain: "es-es" }, joinEnum : { inner: "inner", left: "left" } } // Applies the enums as properties of the target object function apply(target) { for(var key in allEnums) { target[key] = allEnums[key]; } } module.exports.apply = apply; /***/ }, /* 2 */ /***/ function(module, exports) { /** @class Used for communicating between Tableau desktop/server and the WDC's * Javascript. is predominantly a pass-through to the Qt WebBridge methods * @param nativeApiRootObj {Object} - The root object where the native Api methods * are available. For WebKit, this is window. */ function NativeDispatcher (nativeApiRootObj) { this.nativeApiRootObj = nativeApiRootObj; this._initPublicInterface(); this._initPrivateInterface(); } NativeDispatcher.prototype._initPublicInterface = function() { console.log("Initializing public interface for NativeDispatcher"); this._submitCalled = false; var publicInterface = {}; publicInterface.abortForAuth = this._abortForAuth.bind(this); publicInterface.abortWithError = this._abortWithError.bind(this); publicInterface.addCrossOriginException = this._addCrossOriginException.bind(this); publicInterface.log = this._log.bind(this); publicInterface.submit = this._submit.bind(this); publicInterface.reportProgress = this._reportProgress.bind(this); this.publicInterface = publicInterface; } NativeDispatcher.prototype._abortForAuth = function(msg) { this.nativeApiRootObj.WDCBridge_Api_abortForAuth.api(msg); } NativeDispatcher.prototype._abortWithError = function(msg) { this.nativeApiRootObj.WDCBridge_Api_abortWithError.api(msg); } NativeDispatcher.prototype._addCrossOriginException = function(destOriginList) { this.nativeApiRootObj.WDCBridge_Api_addCrossOriginException.api(destOriginList); } NativeDispatcher.prototype._log = function(msg) { this.nativeApiRootObj.WDCBridge_Api_log.api(msg); } NativeDispatcher.prototype._submit = function() { if (this._submitCalled) { console.log("submit called more than once"); return; } this._submitCalled = true; this.nativeApiRootObj.WDCBridge_Api_submit.api(); }; NativeDispatcher.prototype._initPrivateInterface = function() { console.log("Initializing private interface for NativeDispatcher"); this._initCallbackCalled = false; this._shutdownCallbackCalled = false; var privateInterface = {}; privateInterface._initCallback = this._initCallback.bind(this); privateInterface._shutdownCallback = this._shutdownCallback.bind(this); privateInterface._schemaCallback = this._schemaCallback.bind(this); privateInterface._tableDataCallback = this._tableDataCallback.bind(this); privateInterface._dataDoneCallback = this._dataDoneCallback.bind(this); this.privateInterface = privateInterface; } NativeDispatcher.prototype._initCallback = function() { if (this._initCallbackCalled) { console.log("initCallback called more than once"); return; } this._initCallbackCalled = true; this.nativeApiRootObj.WDCBridge_Api_initCallback.api(); } NativeDispatcher.prototype._shutdownCallback = function() { if (this._shutdownCallbackCalled) { console.log("shutdownCallback called more than once"); return; } this._shutdownCallbackCalled = true; this.nativeApiRootObj.WDCBridge_Api_shutdownCallback.api(); } NativeDispatcher.prototype._schemaCallback = function(schema, standardConnections) { // Check to make sure we are using a version of desktop which has the WDCBridge_Api_schemaCallbackEx defined if (!!this.nativeApiRootObj.WDCBridge_Api_schemaCallbackEx) { // Providing standardConnections is optional but we can't pass undefined back because Qt will choke this.nativeApiRootObj.WDCBridge_Api_schemaCallbackEx.api(schema, standardConnections || []); } else { this.nativeApiRootObj.WDCBridge_Api_schemaCallback.api(schema); } } NativeDispatcher.prototype._tableDataCallback = function(tableName, data) { this.nativeApiRootObj.WDCBridge_Api_tableDataCallback.api(tableName, data); } NativeDispatcher.prototype._reportProgress = function (progress) { this.nativeApiRootObj.WDCBridge_Api_reportProgress.api(progress); } NativeDispatcher.prototype._dataDoneCallback = function() { this.nativeApiRootObj.WDCBridge_Api_dataDoneCallback.api(); } module.exports = NativeDispatcher; /***/ }, /* 3 */ /***/ function(module, exports, __webpack_require__) { var Table = __webpack_require__(5); var Enums = __webpack_require__(1); /** @class This class represents the shared parts of the javascript * library which do not have any dependence on whether we are running in * the simulator, in Tableau, or anywhere else * @param tableauApiObj {Object} - The already created tableau API object (usually window.tableau) * @param privateApiObj {Object} - The already created private API object (usually window._tableau) * @param globalObj {Object} - The global object to attach things to (usually window) */ function Shared (tableauApiObj, privateApiObj, globalObj) { this.privateApiObj = privateApiObj; this.globalObj = globalObj; this._hasAlreadyThrownErrorSoDontThrowAgain = false; this.changeTableauApiObj(tableauApiObj); } Shared.prototype.init = function() { console.log("Initializing shared WDC"); this.globalObj.onerror = this._errorHandler.bind(this); // Initialize the functions which will be invoked by the native code this._initTriggerFunctions(); // Assign the deprecated functions which aren't availible in this version of the API this._initDeprecatedFunctions(); } Shared.prototype.changeTableauApiObj = function(tableauApiObj) { this.tableauApiObj = tableauApiObj; // Assign our make & register functions right away because a connector can use // them immediately, even before bootstrapping has completed this.tableauApiObj.makeConnector = this._makeConnector.bind(this); this.tableauApiObj.registerConnector = this._registerConnector.bind(this); Enums.apply(this.tableauApiObj); } Shared.prototype._errorHandler = function(message, file, line, column, errorObj) { console.error(errorObj); // print error for debugging in the browser if (this._hasAlreadyThrownErrorSoDontThrowAgain) { return true; } var msg = message; if(errorObj) { msg += " stack:" + errorObj.stack; } else { msg += " file: " + file; msg += " line: " + line; } if (this.tableauApiObj && this.tableauApiObj.abortWithError) { this.tableauApiObj.abortWithError(msg); } else { throw msg; } this._hasAlreadyThrownErrorSoDontThrowAgain = true; return true; } Shared.prototype._makeConnector = function() { var defaultImpls = { init: function(cb) { cb(); }, shutdown: function(cb) { cb(); } }; return defaultImpls; } Shared.prototype._registerConnector = function (wdc) { // do some error checking on the wdc var functionNames = ["init", "shutdown", "getSchema", "getData"]; for (var ii = functionNames.length - 1; ii >= 0; ii--) { if (typeof(wdc[functionNames[ii]]) !== "function") { throw "The connector did not define the required function: " + functionNames[ii]; } }; console.log("Connector registered"); this.globalObj._wdc = wdc; this._wdc = wdc; } Shared.prototype._initTriggerFunctions = function() { this.privateApiObj.triggerInitialization = this._triggerInitialization.bind(this); this.privateApiObj.triggerSchemaGathering = this._triggerSchemaGathering.bind(this); this.privateApiObj.triggerDataGathering = this._triggerDataGathering.bind(this); this.privateApiObj.triggerShutdown = this._triggerShutdown.bind(this); } // Starts the WDC Shared.prototype._triggerInitialization = function() { this._wdc.init(this.privateApiObj._initCallback); } // Starts the schema gathering process Shared.prototype._triggerSchemaGathering = function() { this._wdc.getSchema(this.privateApiObj._schemaCallback); } // Starts the data gathering process Shared.prototype._triggerDataGathering = function(tablesAndIncrementValues) { if (tablesAndIncrementValues.length != 1) { throw ("Unexpected number of tables specified. Expected 1, actual " + tablesAndIncrementValues.length.toString()); } var tableAndIncremntValue = tablesAndIncrementValues[0]; var table = new Table(tableAndIncremntValue.tableInfo, tableAndIncremntValue.incrementValue, this.privateApiObj._tableDataCallback); this._wdc.getData(table, this.privateApiObj._dataDoneCallback); } // Tells the WDC it's time to shut down Shared.prototype._triggerShutdown = function() { this._wdc.shutdown(this.privateApiObj._shutdownCallback); } // Initializes a series of global callbacks which have been deprecated in version 2.0.0 Shared.prototype._initDeprecatedFunctions = function() { this.tableauApiObj.initCallback = this._initCallback.bind(this); this.tableauApiObj.headersCallback = this._headersCallback.bind(this); this.tableauApiObj.dataCallback = this._dataCallback.bind(this); this.tableauApiObj.shutdownCallback = this._shutdownCallback.bind(this); } Shared.prototype._initCallback = function () { this.tableauApiObj.abortWithError("tableau.initCallback has been deprecated in version 2.0.0. Please use the callback function passed to init"); }; Shared.prototype._headersCallback = function (fieldNames, types) { this.tableauApiObj.abortWithError("tableau.headersCallback has been deprecated in version 2.0.0"); }; Shared.prototype._dataCallback = function (data, lastRecordToken, moreData) { this.tableauApiObj.abortWithError("tableau.dataCallback has been deprecated in version 2.0.0"); }; Shared.prototype._shutdownCallback = function () { this.tableauApiObj.abortWithError("tableau.shutdownCallback has been deprecated in version 2.0.0. Please use the callback function passed to shutdown"); }; module.exports = Shared; /***/ }, /* 4 */ /***/ function(module, exports, __webpack_require__) { /** @class Used for communicating between the simulator and web data connector. It does * this by passing messages between the WDC window and its parent window * @param globalObj {Object} - the global object to find tableau interfaces as well * as register events (usually window) */ function SimulatorDispatcher (globalObj) { this.globalObj = globalObj; this._initMessageHandling(); this._initPublicInterface(); this._initPrivateInterface(); } SimulatorDispatcher.prototype._initMessageHandling = function() { console.log("Initializing message handling"); this.globalObj.addEventListener('message', this._receiveMessage.bind(this), false); this.globalObj.document.addEventListener("DOMContentLoaded", this._onDomContentLoaded.bind(this)); } SimulatorDispatcher.prototype._onDomContentLoaded = function() { // Attempt to notify the simulator window that the WDC has loaded if(this.globalObj.parent !== window) { this.globalObj.parent.postMessage(this._buildMessagePayload('loaded'), '*'); } if(this.globalObj.opener) { try { // Wrap in try/catch for older versions of IE this.globalObj.opener.postMessage(this._buildMessagePayload('loaded'), '*'); } catch(e) { console.warn('Some versions of IE may not accurately simulate the Web Data Connector. Please retry on a Webkit based browser'); } } } SimulatorDispatcher.prototype._packagePropertyValues = function() { var propValues = { "connectionName": this.globalObj.tableau.connectionName, "connectionData": this.globalObj.tableau.connectionData, "password": this.globalObj.tableau.password, "username": this.globalObj.tableau.username, "usernameAlias": this.globalObj.tableau.usernameAlias, "incrementalExtractColumn": this.globalObj.tableau.incrementalExtractColumn, "versionNumber": this.globalObj.tableau.versionNumber, "locale": this.globalObj.tableau.locale, "authPurpose": this.globalObj.tableau.authPurpose, "platformOS": this.globalObj.tableau.platformOS, "platformVersion": this.globalObj.tableau.platformVersion, "platformEdition": this.globalObj.tableau.platformEdition, "platformBuildNumber": this.globalObj.tableau.platformBuildNumber }; return propValues; } SimulatorDispatcher.prototype._applyPropertyValues = function(props) { if (props) { this.globalObj.tableau.connectionName = props.connectionName; this.globalObj.tableau.connectionData = props.connectionData; this.globalObj.tableau.password = props.password; this.globalObj.tableau.username = props.username; this.globalObj.tableau.usernameAlias = props.usernameAlias; this.globalObj.tableau.incrementalExtractColumn = props.incrementalExtractColumn; this.globalObj.tableau.locale = props.locale; this.globalObj.tableau.language = props.locale; this.globalObj.tableau.authPurpose = props.authPurpose; this.globalObj.tableau.platformOS = props.platformOS; this.globalObj.tableau.platformVersion = props.platformVersion; this.globalObj.tableau.platformEdition = props.platformEdition; this.globalObj.tableau.platformBuildNumber = props.platformBuildNumber; } } SimulatorDispatcher.prototype._buildMessagePayload = function(msgName, msgData, props) { var msgObj = {"msgName": msgName, "msgData": msgData, "props": props, "version": ("2.1.0") }; return JSON.stringify(msgObj); } SimulatorDispatcher.prototype._sendMessage = function(msgName, msgData) { var messagePayload = this._buildMessagePayload(msgName, msgData, this._packagePropertyValues()); // Check first to see if we have a messageHandler defined to post the message to if (typeof this.globalObj.webkit != 'undefined' && typeof this.globalObj.webkit.messageHandlers != 'undefined' && typeof this.globalObj.webkit.messageHandlers.wdcHandler != 'undefined') { this.globalObj.webkit.messageHandlers.wdcHandler.postMessage(messagePayload); } else if (!this._sourceWindow) { throw "Looks like the WDC is calling a tableau function before tableau.init() has been called." } else { this._sourceWindow.postMessage(messagePayload, "*"); } } SimulatorDispatcher.prototype._getPayloadObj = function(payloadString) { var payload = null; try { payload = JSON.parse(payloadString); } catch(e) { return null; } return payload; } SimulatorDispatcher.prototype._getWebSecurityWarningConfirm = function() { // Due to cross-origin security issues over https, we may not be able to retrieve _sourceWindow. // Use sourceOrigin instead. var hostName = this._sourceOrigin || this._sourceWindow.location.origin; var supportedHosts = ["http://localhost", "https://localhost", "http://tableau.github.io", "https://tableau.github.io"]; if (supportedHosts.indexOf(hostName) >= 0) { return true; } // Whitelist Tableau domains if (hostName && hostName.endsWith("online.tableau.com")) { return true; } var localizedWarningTitle = this._getLocalizedString("webSecurityWarning"); var completeWarningMsg = localizedWarningTitle + "\n\n" + hostName + "\n"; return confirm(completeWarningMsg); } SimulatorDispatcher.prototype._getCurrentLocale = function() { // Use current browser's locale to get a localized warning message var currentBrowserLanguage = (navigator.language || navigator.userLanguage); var locale = currentBrowserLanguage? currentBrowserLanguage.substring(0, 2): "en"; var supportedLocales = ["de", "en", "es", "fr", "ja", "ko", "pt", "zh"]; // Fall back to English for other unsupported lanaguages if (supportedLocales.indexOf(locale) < 0) { locale = 'en'; } return locale; } SimulatorDispatcher.prototype._getLocalizedString = function(stringKey) { var locale = this._getCurrentLocale(); // Use static require here, otherwise webpack would generate a much bigger JS file var deStringsMap = __webpack_require__(7); var enStringsMap = __webpack_require__(8); var esStringsMap = __webpack_require__(9); var jaStringsMap = __webpack_require__(11); var frStringsMap = __webpack_require__(10); var koStringsMap = __webpack_require__(12); var ptStringsMap = __webpack_require__(13); var zhStringsMap = __webpack_require__(14); var stringJsonMapByLocale = { "de": deStringsMap, "en": enStringsMap, "es": esStringsMap, "fr": frStringsMap, "ja": jaStringsMap, "ko": koStringsMap, "pt": ptStringsMap, "zh": zhStringsMap }; var localizedStringsJson = stringJsonMapByLocale[locale]; return localizedStringsJson[stringKey]; } SimulatorDispatcher.prototype._receiveMessage = function(evt) { console.log("Received message!"); var wdc = this.globalObj._wdc; if (!wdc) { throw "No WDC registered. Did you forget to call tableau.registerConnector?"; } var payloadObj = this._getPayloadObj(evt.data); if(!payloadObj) return; // This message is not needed for WDC if (!this._sourceWindow) { this._sourceWindow = evt.source; this._sourceOrigin = evt.origin; } var msgData = payloadObj.msgData; this._applyPropertyValues(payloadObj.props); switch(payloadObj.msgName) { case "init": // Warn users about possible phinishing attacks var confirmResult = this._getWebSecurityWarningConfirm(); if (!confirmResult) { window.close(); } else { this.globalObj.tableau.phase = msgData.phase; this.globalObj._tableau.triggerInitialization(); } break; case "shutdown": this.globalObj._tableau.triggerShutdown(); break; case "getSchema": this.globalObj._tableau.triggerSchemaGathering(); break; case "getData": this.globalObj._tableau.triggerDataGathering(msgData.tablesAndIncrementValues); break; } }; /**** PUBLIC INTERFACE *****/ SimulatorDispatcher.prototype._initPublicInterface = function() { console.log("Initializing public interface"); this._submitCalled = false; var publicInterface = {}; publicInterface.abortForAuth = this._abortForAuth.bind(this); publicInterface.abortWithError = this._abortWithError.bind(this); publicInterface.addCrossOriginException = this._addCrossOriginException.bind(this); publicInterface.log = this._log.bind(this); publicInterface.submit = this._submit.bind(this); // Assign the public interface to this this.publicInterface = publicInterface; } SimulatorDispatcher.prototype._abortForAuth = function(msg) { this._sendMessage("abortForAuth", {"msg": msg}); } SimulatorDispatcher.prototype._abortWithError = function(msg) { this._sendMessage("abortWithError", {"errorMsg": msg}); } SimulatorDispatcher.prototype._addCrossOriginException = function(destOriginList) { // Don't bother passing this back to the simulator since there's nothing it can // do. Just call back to the WDC indicating that it worked console.log("Cross Origin Exception requested in the simulator. Pretending to work.") setTimeout(function() { this.globalObj._wdc.addCrossOriginExceptionCompleted(destOriginList); }.bind(this), 0); } SimulatorDispatcher.prototype._log = function(msg) { this._sendMessage("log", {"logMsg": msg}); } SimulatorDispatcher.prototype._submit = function() { this._sendMessage("submit"); }; /**** PRIVATE INTERFACE *****/ SimulatorDispatcher.prototype._initPrivateInterface = function() { console.log("Initializing private interface"); var privateInterface = {}; privateInterface._initCallback = this._initCallback.bind(this); privateInterface._shutdownCallback = this._shutdownCallback.bind(this); privateInterface._schemaCallback = this._schemaCallback.bind(this); privateInterface._tableDataCallback = this._tableDataCallback.bind(this); privateInterface._dataDoneCallback = this._dataDoneCallback.bind(this); // Assign the private interface to this this.privateInterface = privateInterface; } SimulatorDispatcher.prototype._initCallback = function() { this._sendMessage("initCallback"); } SimulatorDispatcher.prototype._shutdownCallback = function() { this._sendMessage("shutdownCallback"); } SimulatorDispatcher.prototype._schemaCallback = function(schema, standardConnections) { this._sendMessage("_schemaCallback", {"schema": schema, "standardConnections" : standardConnections || []}); } SimulatorDispatcher.prototype._tableDataCallback = function(tableName, data) { this._sendMessage("_tableDataCallback", { "tableName": tableName, "data": data }); } SimulatorDispatcher.prototype._dataDoneCallback = function() { this._sendMessage("_dataDoneCallback"); } module.exports = SimulatorDispatcher; /***/ }, /* 5 */ /***/ function(module, exports) { /** * @class Represents a single table which Tableau has requested * @param tableInfo {Object} - Information about the table * @param incrementValue {string=} - Incremental update value */ function Table(tableInfo, incrementValue, dataCallbackFn) { /** @member {Object} Information about the table which has been requested. This is guaranteed to be one of the tables the connector returned in the call to getSchema. */ this.tableInfo = tableInfo; /** @member {string} Defines the incremental update value for this table. Empty string if there is not an incremental update requested. */ this.incrementValue = incrementValue || ""; /** @private */ this._dataCallbackFn = dataCallbackFn; // bind the public facing version of this function so it can be passed around this.appendRows = this._appendRows.bind(this); } /** * @method appends the given rows to the set of data contained in this table * @param data {array} - Either an array of arrays or an array of objects which represent * the individual rows of data to append to this table */ Table.prototype._appendRows = function(data) { // Do some quick validation that this data is the format we expect if (!data) { console.warn("rows data is null or undefined"); return; } if (!Array.isArray(data)) { // Log a warning because the data is not an array like we expected console.warn("Table.appendRows must take an array of arrays or array of objects"); return; } // Call back with the rows for this table this._dataCallbackFn(this.tableInfo.id, data); } module.exports = Table; /***/ }, /* 6 */ /***/ function(module, exports) { function copyFunctions(src, dest) { for(var key in src) { if (typeof src[key] === 'function') { dest[key] = src[key]; } } } module.exports.copyFunctions = copyFunctions; /***/ }, /* 7 */ /***/ function(module, exports) { module.exports = { "webSecurityWarning": "To help prevent malicious sites from getting access to your confidential data, confirm that you trust the following site:" }; /***/ }, /* 8 */ /***/ function(module, exports) { module.exports = { "webSecurityWarning": "To help prevent malicious sites from getting access to your confidential data, confirm that you trust the following site:" }; /***/ }, /* 9 */ /***/ function(module, exports) { module.exports = { "webSecurityWarning": "To help prevent malicious sites from getting access to your confidential data, confirm that you trust the following site:" }; /***/ }, /* 10 */ /***/ function(module, exports) { module.exports = { "webSecurityWarning": "To help prevent malicious sites from getting access to your confidential data, confirm that you trust the following site:" }; /***/ }, /* 11 */ /***/ function(module, exports) { module.exports = { "webSecurityWarning": "To help prevent malicious sites from getting access to your confidential data, confirm that you trust the following site:" }; /***/ }, /* 12 */ /***/ function(module, exports) { module.exports = { "webSecurityWarning": "To help prevent malicious sites from getting access to your confidential data, confirm that you trust the following site:" }; /***/ }, /* 13 */ /***/ function(module, exports) { module.exports = { "webSecurityWarning": "To help prevent malicious sites from getting access to your confidential data, confirm that you trust the following site:" }; /***/ }, /* 14 */ /***/ function(module, exports) { module.exports = { "webSecurityWarning": "wwTo help prevent malicious sites from getting access to your confidential data, confirm that you trust the following site:" }; /***/ }, /* 15 */ /***/ function(module, exports, __webpack_require__) { /**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Copyright (C) 2014 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Milian Wolff <milian.wolff@kdab.com> ** Contact: http://www.qt.io/licensing/ ** ** This file is part of the QtWebChannel module of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL21$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see http://www.qt.io/terms-conditions. For further ** information use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** As a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ "use strict"; var QWebChannelMessageTypes = { signal: 1, propertyUpdate: 2, init: 3, idle: 4, debug: 5, invokeMethod: 6, connectToSignal: 7, disconnectFromSignal: 8, setProperty: 9, response: 10, }; var QWebChannel = function(transport, initCallback) { if (typeof transport !== "object" || typeof transport.send !== "function") { console.error("The QWebChannel expects a transport object with a send function and onmessage callback property." + " Given is: transport: " + typeof(transport) + ", transport.send: " + typeof(transport.send)); return; } var channel = this; this.transport = transport; this.send = function(data) { if (typeof(data) !== "string") { data = JSON.stringify(data); } channel.transport.send(data); } this.transport.onmessage = function(message) { var data = message.data; if (typeof data === "string") { data = JSON.parse(data); } switch (data.type) { case QWebChannelMessageTypes.signal: channel.handleSignal(data); break; case QWebChannelMessageTypes.response: channel.handleResponse(data); break; case QWebChannelMessageTypes.propertyUpdate: channel.handlePropertyUpdate(data); break; default: console.error("invalid message received:", message.data); break; } } this.execCallbacks = {}; this.execId = 0; this.exec = function(data, callback) { if (!callback) { // if no callback is given, send directly channel.send(data); return; } if (channel.execId === Number.MAX_VALUE) { // wrap channel.execId = Number.MIN_VALUE; } if (data.hasOwnProperty("id")) { console.error("Cannot exec message with property id: " + JSON.stringify(data)); return; } data.id = channel.execId++; channel.execCallbacks[data.id] = callback; channel.send(data); }; this.objects = {}; this.handleSignal = function(message) { var object = channel.objects[message.object]; if (object) { object.signalEmitted(message.signal, message.args); } else { console.warn("Unhandled signal: " + message.object + "::" + message.signal); } } this.handleResponse = function(message) { if (!message.hasOwnProperty("id")) { console.error("Invalid response message received: ", JSON.stringify(message)); return; } channel.execCallbacks[message.id](message.data); delete channel.execCallbacks[message.id]; } this.handlePropertyUpdate = function(message) { for (var i in message.data) { var data = message.data[i]; var object = channel.objects[data.object]; if (object) { object.propertyUpdate(data.signals, data.properties); } else { console.warn("Unhandled property update: " + data.object + "::" + data.signal); } } channel.exec({type: QWebChannelMessageTypes.idle}); } this.debug = function(message) { channel.send({type: QWebChannelMessageTypes.debug, data: message}); }; channel.exec({type: QWebChannelMessageTypes.init}, function(data) { for (var objectName in data) { var object = new QObject(objectName, data[objectName], channel); } // now unwrap properties, which might reference other registered objects for (var objectName in channel.objects) { channel.objects[objectName].unwrapProperties(); } if (initCallback) { initCallback(channel); } channel.exec({type: QWebChannelMessageTypes.idle}); }); }; function QObject(name, data, webChannel) { this.__id__ = name; webChannel.objects[name] = this; // List of callbacks that get invoked upon signal emission this.__objectSignals__ = {}; // Cache of all properties, updated when a notify signal is emitted this.__propertyCache__ = {}; var object = this; // ---------------------------------------------------------------------- this.unwrapQObject = function(response) { if (response instanceof Array) { // support list of objects var ret = new Array(response.length); for (var i = 0; i < response.length; ++i) { ret[i] = object.unwrapQObject(response[i]); } return ret; } if (!response || !response["__QObject*__"] || response["id"] === undefined) { return response; } var objectId = response.id; if (webChannel.objects[objectId]) return webChannel.objects[objectId]; if (!response.data) { console.error("Cannot unwrap unknown QObject " + objectId + " without data."); return; } var qObject = new QObject( objectId, response.data, webChannel ); qObject.destroyed.connect(function() { if (webChannel.objects[objectId] === qObject) { delete webChannel.objects[objectId]; // reset the now deleted QObject to an empty {} object // just assigning {} though would not have the desired effect, but the // below also ensures all external references will see the empty map // NOTE: this detour is necessary to workaround QTBUG-40021 var propertyNames = []; for (var propertyName in qObject) { propertyNames.push(propertyName); } for (var idx in propertyNames) { delete qObject[propertyNames[idx]]; } } }); // here we are already initialized, and thus must directly unwrap the properties qObject.unwrapProperties(); return qObject; } this.unwrapProperties = function() { for (var propertyIdx in object.__propertyCache__) { object.__propertyCache__[propertyIdx] = object.unwrapQObject(object.__propertyCache__[propertyIdx]); } } function addSignal(signalData, isPropertyNotifySignal) { var signalName = signalData[0]; var signalIndex = signalData[1]; object[signalName] = { connect: function(callback) { if (typeof(callback) !== "function") { console.error("Bad callback given to connect to signal " + signalName); return; } object.__objectSignals__[signalIndex] = object.__objectSignals__[signalIndex] || []; object.__objectSignals__[signalIndex].push(callback); if (!isPropertyNotifySignal && signalName !== "destroyed") { // only required for "pure" signals, handled separately for properties in propertyUpdate // also note that we always get notified about the destroyed signal webChannel.exec({ type: QWebChannelMessageTypes.connectToSignal, object: object.__id__, signal: signalIndex }); } }, disconnect: function(callback) { if (typeof(callback) !== "function") { console.error("Bad callback given to disconnect from signal " + signalName); return; } object.__objectSignals__[signalIndex] = object.__objectSignals__[signalIndex] || []; var idx = object.__objectSignals__[signalIndex].indexOf(callback); if (idx === -1) { console.error("Cannot find connection of signal " + signalName + " to " + callback.name); return; } object.__objectSignals__[signalIndex].splice(idx, 1); if (!isPropertyNotifySignal && object.__objectSignals__[signalIndex].length === 0) { // only required for "pure" signals, handled separately for properties in propertyUpdate webChannel.exec({ type: QWebChannelMessageTypes.disconnectFromSignal, object: object.__id__, signal: signalIndex }); } } }; } /** * Invokes all callbacks for the given signalname. Also works for property notify callbacks. */ function invokeSignalCallbacks(signalName, signalArgs) { var connections = object.__objectSignals__[signalName]; if (connections) { connections.forEach(function(callback) { callback.apply(callback, signalArgs); }); } } this.propertyUpdate = function(signals, propertyMap) { // update property cache for (var propertyIndex in propertyMap) { var propertyValue = propertyMap[propertyIndex]; object.__propertyCache__[propertyIndex] = propertyValue; } for (var signalName in signals) { // Invoke all callbacks, as signalEmitted() does not. This ensures the // property cache is updated before the callbacks are invoked. invokeSignalCallbacks(signalName, signals[signalName]); } } this.signalEmitted = function(signalName, signalArgs) { invokeSignalCallbacks(signalName, signalArgs); } function addMethod(methodData) { var methodName = methodData[0]; var methodIdx = methodData[1]; object[methodName] = function() { var args = []; var callback; for (var i = 0; i < arguments.length; ++i) { if (typeof arguments[i] === "function") callback = arguments[i]; else args.push(arguments[i]); } webChannel.exec({ "type": QWebChannelMessageTypes.invokeMethod, "object": object.__id__, "method": methodIdx, "args": args }, function(response) { if (response !== undefined) { var result = object.unwrapQObject(response); if (callback) { (callback)(result); } } }); }; } function bindGetterSetter(propertyInfo) { var propertyIndex = propertyInfo[0]; var propertyName = propertyInfo[1]; var notifySignalData = propertyInfo[2]; // initialize property cache with current value // NOTE: if this is an object, it is not directly unwrapped as it might // reference other QObject that we do not know yet object.__propertyCache__[propertyIndex] = propertyInfo[3]; if (notifySignalData) { if (notifySignalData[0] === 1) { // signal name is optimized away, reconstruct the actual name notifySignalData[0] = propertyName + "Changed"; } addSignal(notifySignalData, true); } Object.defineProperty(object, propertyName, { get: function () { var propertyValue = object.__propertyCache__[propertyIndex]; if (propertyValue === undefined) { // This shouldn't happen console.warn("Undefined value in property cache for property \"" + propertyName + "\" in object " + object.__id__); } return propertyValue; }, set: function(value) { if (value === undefined) { console.warn("Property setter for " + propertyName + " called with undefined value!"); return; } object.__propertyCache__[propertyIndex] = value; webChannel.exec({ "type": QWebChannelMessageTypes.setProperty, "object": object.__id__, "property": propertyIndex, "value": value }); } }); } // ---------------------------------------------------------------------- data.methods.forEach(addMethod); data.properties.forEach(bindGetterSetter); data.signals.forEach(function(signal) { addSignal(signal, false); }); for (var name in data.enums) { object[name] = data.enums[name]; } } //required for use with nodejs if (true) { module.exports = { QWebChannel: QWebChannel }; } /***/ }, /* 16 */ /***/ function(module, exports, __webpack_require__) { "use strict"; var Utilities = __webpack_require__(6); var Shared = __webpack_require__(3); var NativeDispatcher = __webpack_require__(2); var SimulatorDispatcher = __webpack_require__(4); var qwebchannel = __webpack_require__(15); /** @module ShimLibrary - This module defines the WDC's shim library which is used to bridge the gap between the javascript code of the WDC and the driving context of the WDC (Tableau desktop, the simulator, etc.) */ // This function should be called once bootstrapping has been completed and the // dispatcher and shared WDC objects are both created and available function bootstrappingFinished(_dispatcher, _shared) { Utilities.copyFunctions(_dispatcher.publicInterface, window.tableau); Utilities.copyFunctions(_dispatcher.privateInterface, window._tableau); _shared.init(); } // Initializes the wdc shim library. You must call this before doing anything with WDC module.exports.init = function() { // The initial code here is the only place in our module which should have global // knowledge of how all the WDC components are glued together. This is the only place // which will know about the window object or other global objects. This code will be run // immediately when the shim library loads and is responsible for determining the context // which it is running it and setup a communications channel between the js & running code var dispatcher = null; var shared = null; // Always define the private _tableau object at the start window._tableau = {}; // Check to see if the tableauVersionBootstrap is defined as a global object. If so, // we are running in the Tableau desktop/server context. If not, we're running in the simulator if (!!window.tableauVersionBootstrap) { // We have the tableau object defined console.log("Initializing NativeDispatcher, Reporting version number"); window.tableauVersionBootstrap.ReportVersionNumber(("2.1.0")); dispatcher = new NativeDispatcher(window); } else if (!!window.qt && !!window.qt.webChannelTransport) { console.log("Initializing NativeDispatcher for qwebchannel"); window.tableau = {}; // We're running in a context where the webChannelTransport is available. This means QWebEngine is in use window.channel = new qwebchannel.QWebChannel(qt.webChannelTransport, function(channel) { console.log("QWebChannel created successfully"); // Define the function which tableau will call after it has inserted all the required objects into the javascript frame window._tableau._nativeSetupCompleted = function() { // Once the native code tells us everything here is done, we should have all the expected objects inserted into js dispatcher = new NativeDispatcher(channel.objects); window.tableau = channel.objects.tableau; shared.changeTableauApiObj(window.tableau); bootstrappingFinished(dispatcher, shared); }; // Actually call into the version bootstrapper to report our version number channel.objects.tableauVersionBootstrap.ReportVersionNumber(("2.1.0")); }); } else { console.log("Version Bootstrap is not defined, Initializing SimulatorDispatcher"); window.tableau = {}; dispatcher = new SimulatorDispatcher(window); } // Initialize the shared WDC object and add in our enum values shared = new Shared(window.tableau, window._tableau, window); // Check to see if the dispatcher is already defined and immediately call the // callback if so if (dispatcher) { bootstrappingFinished(dispatcher, shared); } }; /***/ } /******/ ]); //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYnVuZGxlLmpzIiwic291cmNlcyI6WyJ3ZWJwYWNrOi8vL3dlYnBhY2svYm9vdHN0cmFwIDQzYTZiMWVkOGNkOTQ0MWQ0NWNhIiwid2VicGFjazovLy8uL2luZGV4LmpzIiwid2VicGFjazovLy8uL0VudW1zLmpzIiwid2VicGFjazovLy8uL05hdGl2ZURpc3BhdGNoZXIuanMiLCJ3ZWJwYWNrOi8vLy4vU2hhcmVkLmpzIiwid2VicGFjazovLy8uL1NpbXVsYXRvckRpc3BhdGNoZXIuanMiLCJ3ZWJwYWNrOi8vLy4vVGFibGUuanMiLCJ3ZWJwYWNrOi8vLy4vVXRpbGl0aWVzLmpzIiwid2VicGFjazovLy8uL3Jlc291cmNlcy9TaGltX2xpYl9yZXNvdXJjZXNfZGUtREUuanNvbiIsIndlYnBhY2s6Ly8vLi9yZXNvdXJjZXMvU2hpbV9saWJfcmVzb3VyY2VzX2VuLVVTLmpzb24iLCJ3ZWJwYWNrOi8vLy4vcmVzb3VyY2VzL1NoaW1fbGliX3Jlc291cmNlc19lcy1FUy5qc29uIiwid2VicGFjazovLy8uL3Jlc291cmNlcy9TaGltX2xpYl9yZXNvdXJjZXNfZnItRlIuanNvbiIsIndlYnBhY2s6Ly8vLi9yZXNvdXJjZXMvU2hpbV9saWJfcmVzb3VyY2VzX2phLUpQLmpzb24iLCJ3ZWJwYWNrOi8vLy4vcmVzb3VyY2VzL1NoaW1fbGliX3Jlc291cmNlc19rby1LUi5qc29uIiwid2VicGFjazovLy8uL3Jlc291cmNlcy9TaGltX2xpYl9yZXNvdXJjZXNfcHQtQlIuanNvbiIsIndlYnBhY2s6Ly8vLi9yZXNvdXJjZXMvU2hpbV9saWJfcmVzb3VyY2VzX3poLUNOLmpzb24iLCJ3ZWJwYWNrOi8vLy4vfi9xd2ViY2hhbm5lbC9xd2ViY2hhbm5lbC5qcyIsIndlYnBhY2s6Ly8vLi90YWJsZWF1d2RjLmpzIl0sInNvdXJjZXNDb250ZW50IjpbIiBcdC8vIFRoZSBtb2R1bGUgY2FjaGVcbiBcdHZhciBpbnN0YWxsZWRNb2R1bGVzID0ge307XG5cbiBcdC8vIFRoZSByZXF1aXJlIGZ1bmN0aW9uXG4gXHRmdW5jdGlvbiBfX3dlYnBhY2tfcmVxdWlyZV9fKG1vZHVsZUlkKSB7XG5