@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,540 lines (1,268 loc) • 185 kB
JavaScript
/*! Build Number: 2.1.3 */
/******/ (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__(20);
tableauwdc.init();
/***/ },
/* 1 */
/***/ function(module, exports, __webpack_require__) {
var APPROVED_ORIGINS_KEY = "wdc_approved_origins";
var SEPARATOR = ",";
var Cookies = __webpack_require__(9);
function _getApprovedOriginsValue() {
var result = Cookies.get(APPROVED_ORIGINS_KEY);
return result;
}
function _saveApprovedOrigins(originArray) {
var newOriginString = originArray.join(SEPARATOR);
console.log("Saving approved origins '" + newOriginString + "'");
// We could potentially make this a longer term cookie instead of just for the current session
var result = Cookies.set(APPROVED_ORIGINS_KEY, newOriginString);
return result;
}
// Adds an approved origins to the list already saved in a session cookie
function addApprovedOrigin(origin) {
if (origin) {
var origins = getApprovedOrigins();
origins.push(origin);
_saveApprovedOrigins(origins);
}
}
// Retrieves the origins which have already been approved by the user
function getApprovedOrigins() {
var originsString = _getApprovedOriginsValue();
if (!originsString || 0 === originsString.length) {
return [];
}
var origins = originsString.split(SEPARATOR);
return origins;
}
module.exports.addApprovedOrigin = addApprovedOrigin;
module.exports.getApprovedOrigins = getApprovedOrigins;
/***/ },
/* 2 */
/***/ 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;
/***/ },
/* 3 */
/***/ 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) {
// Report progress was added in 2.1 so it may not be available if Tableau only knows 2.0
if (!!this.nativeApiRootObj.WDCBridge_Api_reportProgress) {
this.nativeApiRootObj.WDCBridge_Api_reportProgress.api(progress);
} else {
console.log("reportProgress not available from this Tableau version");
}
}
NativeDispatcher.prototype._dataDoneCallback = function() {
this.nativeApiRootObj.WDCBridge_Api_dataDoneCallback.api();
}
module.exports = NativeDispatcher;
/***/ },
/* 4 */
/***/ function(module, exports, __webpack_require__) {
var Table = __webpack_require__(6);
var Enums = __webpack_require__(2);
/** @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;
/***/ },
/* 5 */
/***/ function(module, exports, __webpack_require__) {
var ApprovedOrigins = __webpack_require__(1);
// Required for IE & Edge which don't support endsWith
__webpack_require__(8);
/** @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.3") };
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 {
// Make sure we only post this info back to the source origin the user approved in _getWebSecurityWarningConfirm
this._sourceWindow.postMessage(messagePayload, this._sourceOrigin);
}
}
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 origin = this._sourceOrigin;
var Uri = __webpack_require__(18);
var parsedOrigin = new Uri(origin);
var hostName = parsedOrigin.host();
var supportedHosts = ["localhost", "tableau.github.io"];
if (supportedHosts.indexOf(hostName) >= 0) {
return true;
}
// Whitelist Tableau domains
if (hostName && hostName.endsWith("online.tableau.com")) {
return true;
}
var alreadyApprovedOrigins = ApprovedOrigins.getApprovedOrigins();
if (alreadyApprovedOrigins.indexOf(origin) >= 0) {
// The user has already approved this origin, no need to ask again
console.log("Already approved the origin'" + origin + "', not asking again");
return true;
}
var localizedWarningTitle = this._getLocalizedString("webSecurityWarning");
var completeWarningMsg = localizedWarningTitle + "\n\n" + hostName + "\n";
var isConfirmed = confirm(completeWarningMsg);
if (isConfirmed) {
// Set a session cookie to mark that we've approved this already
ApprovedOrigins.addApprovedOrigin(origin);
}
return isConfirmed;
}
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__(10);
var enStringsMap = __webpack_require__(11);
var esStringsMap = __webpack_require__(12);
var jaStringsMap = __webpack_require__(14);
var frStringsMap = __webpack_require__(13);
var koStringsMap = __webpack_require__(15);
var ptStringsMap = __webpack_require__(16);
var zhStringsMap = __webpack_require__(17);
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.reportProgress = this._reportProgress.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._reportProgress = function(msg) {
this._sendMessage("reportProgress", {"progressMsg": 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;
/***/ },
/* 6 */
/***/ 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;
/***/ },
/* 7 */
/***/ 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;
/***/ },
/* 8 */
/***/ function(module, exports) {
/*! http://mths.be/endswith v0.2.0 by @mathias */
if (!String.prototype.endsWith) {
(function() {
'use strict'; // needed to support `apply`/`call` with `undefined`/`null`
var defineProperty = (function() {
// IE 8 only supports `Object.defineProperty` on DOM elements
try {
var object = {};
var $defineProperty = Object.defineProperty;
var result = $defineProperty(object, object, object) && $defineProperty;
} catch(error) {}
return result;
}());
var toString = {}.toString;
var endsWith = function(search) {
if (this == null) {
throw TypeError();
}
var string = String(this);
if (search && toString.call(search) == '[object RegExp]') {
throw TypeError();
}
var stringLength = string.length;
var searchString = String(search);
var searchLength = searchString.length;
var pos = stringLength;
if (arguments.length > 1) {
var position = arguments[1];
if (position !== undefined) {
// `ToInteger`
pos = position ? Number(position) : 0;
if (pos != pos) { // better `isNaN`
pos = 0;
}
}
}
var end = Math.min(Math.max(pos, 0), stringLength);
var start = end - searchLength;
if (start < 0) {
return false;
}
var index = -1;
while (++index < searchLength) {
if (string.charCodeAt(start + index) != searchString.charCodeAt(index)) {
return false;
}
}
return true;
};
if (defineProperty) {
defineProperty(String.prototype, 'endsWith', {
'value': endsWith,
'configurable': true,
'writable': true
});
} else {
String.prototype.endsWith = endsWith;
}
}());
}
/***/ },
/* 9 */
/***/ function(module, exports, __webpack_require__) {
var __WEBPACK_AMD_DEFINE_RESULT__;/*
* Cookies.js - 1.2.3
* https://github.com/ScottHamper/Cookies
*
* This is free and unencumbered software released into the public domain.
*/
(function (global, undefined) {
'use strict';
var factory = function (window) {
if (typeof window.document !== 'object') {
throw new Error('Cookies.js requires a `window` with a `document` object');
}
var Cookies = function (key, value, options) {
return arguments.length === 1 ?
Cookies.get(key) : Cookies.set(key, value, options);
};
// Allows for setter injection in unit tests
Cookies._document = window.document;
// Used to ensure cookie keys do not collide with
// built-in `Object` properties
Cookies._cacheKeyPrefix = 'cookey.'; // Hurr hurr, :)
Cookies._maxExpireDate = new Date('Fri, 31 Dec 9999 23:59:59 UTC');
Cookies.defaults = {
path: '/',
secure: false
};
Cookies.get = function (key) {
if (Cookies._cachedDocumentCookie !== Cookies._document.cookie) {
Cookies._renewCache();
}
var value = Cookies._cache[Cookies._cacheKeyPrefix + key];
return value === undefined ? undefined : decodeURIComponent(value);
};
Cookies.set = function (key, value, options) {
options = Cookies._getExtendedOptions(options);
options.expires = Cookies._getExpiresDate(value === undefined ? -1 : options.expires);
Cookies._document.cookie = Cookies._generateCookieString(key, value, options);
return Cookies;
};
Cookies.expire = function (key, options) {
return Cookies.set(key, undefined, options);
};
Cookies._getExtendedOptions = function (options) {
return {
path: options && options.path || Cookies.defaults.path,
domain: options && options.domain || Cookies.defaults.domain,
expires: options && options.expires || Cookies.defaults.expires,
secure: options && options.secure !== undefined ? options.secure : Cookies.defaults.secure
};
};
Cookies._isValidDate = function (date) {
return Object.prototype.toString.call(date) === '[object Date]' && !isNaN(date.getTime());
};
Cookies._getExpiresDate = function (expires, now) {
now = now || new Date();
if (typeof expires === 'number') {
expires = expires === Infinity ?
Cookies._maxExpireDate : new Date(now.getTime() + expires * 1000);
} else if (typeof expires === 'string') {
expires = new Date(expires);
}
if (expires && !Cookies._isValidDate(expires)) {
throw new Error('`expires` parameter cannot be converted to a valid Date instance');
}
return expires;
};
Cookies._generateCookieString = function (key, value, options) {
key = key.replace(/[^#$&+\^`|]/g, encodeURIComponent);
key = key.replace(/\(/g, '%28').replace(/\)/g, '%29');
value = (value + '').replace(/[^!#$&-+\--:<-\[\]-~]/g, encodeURIComponent);
options = options || {};
var cookieString = key + '=' + value;
cookieString += options.path ? ';path=' + options.path : '';
cookieString += options.domain ? ';domain=' + options.domain : '';
cookieString += options.expires ? ';expires=' + options.expires.toUTCString() : '';
cookieString += options.secure ? ';secure' : '';
return cookieString;
};
Cookies._getCacheFromString = function (documentCookie) {
var cookieCache = {};
var cookiesArray = documentCookie ? documentCookie.split('; ') : [];
for (var i = 0; i < cookiesArray.length; i++) {
var cookieKvp = Cookies._getKeyValuePairFromCookieString(cookiesArray[i]);
if (cookieCache[Cookies._cacheKeyPrefix + cookieKvp.key] === undefined) {
cookieCache[Cookies._cacheKeyPrefix + cookieKvp.key] = cookieKvp.value;
}
}
return cookieCache;
};
Cookies._getKeyValuePairFromCookieString = function (cookieString) {
// "=" is a valid character in a cookie value according to RFC6265, so cannot `split('=')`
var separatorIndex = cookieString.indexOf('=');
// IE omits the "=" when the cookie value is an empty string
separatorIndex = separatorIndex < 0 ? cookieString.length : separatorIndex;
var key = cookieString.substr(0, separatorIndex);
var decodedKey;
try {
decodedKey = decodeURIComponent(key);
} catch (e) {
if (console && typeof console.error === 'function') {
console.error('Could not decode cookie with key "' + key + '"', e);
}
}
return {
key: decodedKey,
value: cookieString.substr(separatorIndex + 1) // Defer decoding value until accessed
};
};
Cookies._renewCache = function () {
Cookies._cache = Cookies._getCacheFromString(Cookies._document.cookie);
Cookies._cachedDocumentCookie = Cookies._document.cookie;
};
Cookies._areEnabled = function () {
var testKey = 'cookies.js';
var areEnabled = Cookies.set(testKey, 1).get(testKey) === '1';
Cookies.expire(testKey);
return areEnabled;
};
Cookies.enabled = Cookies._areEnabled();
return Cookies;
};
var cookiesExport = (global && typeof global.document === 'object') ? factory(global) : factory;
// AMD support
if (true) {
!(__WEBPACK_AMD_DEFINE_RESULT__ = function () { return cookiesExport; }.call(exports, __webpack_require__, exports, module), __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
// CommonJS/Node.js support
} else if (typeof exports === 'object') {
// Support Node.js specific `module.exports` (which can be a function)
if (typeof module === 'object' && typeof module.exports === 'object') {
exports = module.exports = cookiesExport;
}
// But always support CommonJS module 1.1.1 spec (`exports` cannot be a function)
exports.Cookies = cookiesExport;
} else {
global.Cookies = cookiesExport;
}
})(typeof window === 'undefined' ? this : window);
/***/ },
/* 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": "To help prevent malicious sites from getting access to your confidential data, confirm that you trust the following site:"
};
/***/ },
/* 15 */
/***/ 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:"
};
/***/ },
/* 16 */
/***/ 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:"
};
/***/ },
/* 17 */
/***/ 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:"
};
/***/ },
/* 18 */
/***/ function(module, exports, __webpack_require__) {
var __WEBPACK_AMD_DEFINE_RESULT__;/*!
* jsUri
* https://github.com/derek-watson/jsUri
*
* Copyright 2013, Derek Watson
* Released under the MIT license.
*
* Includes parseUri regular expressions
* http://blog.stevenlevithan.com/archives/parseuri
* Copyright 2007, Steven Levithan
* Released under the MIT license.
*/
/*globals define, module */
(function(global) {
var re = {
starts_with_slashes: /^\/+/,
ends_with_slashes: /\/+$/,
pluses: /\+/g,
query_separator: /[&;]/,
uri_parser: /^(?:(?![^:@]+:[^:@\/]*@)([^:\/?#.]+):)?(?:\/\/)?((?:(([^:@\/]*)(?::([^:@]*))?)?@)?(\[[0-9a-fA-F:.]+\]|[^:\/?#]*)(?::(\d+|(?=:)))?(:)?)((((?:[^?#](?![^?#\/]*\.[^?#\/.]+(?:[?#]|$)))*\/?)?([^?#\/]*))(?:\?([^#]*))?(?:#(.*))?)/
};
/**
* Define forEach for older js environments
* @see https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Array/forEach#Compatibility
*/
if (!Array.prototype.forEach) {
Array.prototype.forEach = function(callback, thisArg) {
var T, k;
if (this == null) {
throw new TypeError(' this is null or not defined');
}
var O = Object(this);
var len = O.length >>> 0;
if (typeof callback !== "function") {
throw new TypeError(callback + ' is not a function');
}
if (arguments.length > 1) {
T = thisArg;
}
k = 0;
while (k < len) {
var kValue;
if (k in O) {
kValue = O[k];
callback.call(T, kValue, k, O);
}
k++;
}
};
}
/**
* unescape a query param value
* @param {string} s encoded value
* @return {string} decoded value
*/
function decode(s) {
if (s) {
s = s.toString().replace(re.pluses, '%20');
s = decodeURIComponent(s);
}
return s;
}
/**
* Breaks a uri string down into its individual parts
* @param {string} str uri
* @return {object} parts
*/
function parseUri(str) {
var parser = re.uri_parser;
var parserKeys = ["source", "protocol", "authority", "userInfo", "user", "password", "host", "port", "isColonUri", "relative", "path", "directory", "file", "query", "anchor"];
var m = parser.exec(str || '');
var parts = {};
parserKeys.forEach(function(key, i) {
parts[key] = m[i] || '';
});
return parts;
}
/**
* Breaks a query string down into an array of key/value pairs
* @param {string} str query
* @return {array} array of arrays (key/value pairs)
*/
function parseQuery(str) {
var i, ps, p, n, k, v, l;
var pairs = [];
if (typeof(str) === 'undefined' || str === null || str === '') {
return pairs;
}
if (str.indexOf('?') === 0) {
str = str.substring(1);
}
ps = str.toString().split(re.query_separator);
for (i = 0, l = ps.length; i < l; i++) {
p = ps[i];
n = p.indexOf('=');
if (n !== 0) {
k = decode(p.substring(0, n));
v = decode(p.substring(n + 1));
pairs.push(n === -1 ? [p, null] : [k, v]);
}
}
return pairs;
}
/**
* Creates a new Uri object
* @constructor
* @param {string} str
*/
function Uri(str) {
this.uriParts = parseUri(str);
this.queryPairs = parseQuery(this.uriParts.query);
this.hasAuthorityPrefixUserPref = null;
}
/**
* Define getter/setter methods
*/
['protocol', 'userInfo', 'host', 'port', 'path', 'anchor'].forEach(function(key) {
Uri.prototype[key] = function(val) {
if (typeof val !== 'undefined') {
this.uriParts[key] = val;
}
return this.uriParts[key];
};
});
/**
* if there is no protocol, the leading // can be enabled or disabled
* @param {Boolean} val
* @return {Boolean}
*/
Uri.prototype.hasAuthorityPrefix = function(val) {
if (typeof val !== 'undefined') {
this.hasAuthorityPrefixUserPref = val;
}
if (this.hasAuthorityPrefixUserPref === null) {
return (this.uriParts.source.indexOf('//') !== -1);
} else {
return this.hasAuthorityPrefixUserPref;
}
};
Uri.prototype.isColonUri = function (val) {
if (typeof val !== 'undefined') {
this.uriParts.isColonUri = !!val;
} else {
return !!this.uriParts.isColonUri;
}
};
/**
* Serializes the internal state of the query pairs
* @param {string} [val] set a new query string
* @return {string} query string
*/
Uri.prototype.query = function(val) {
var s = '', i, param, l;
if (typeof val !== 'undefined') {
this.queryPairs = parseQuery(val);
}
for (i = 0, l = this.queryPairs.length; i < l; i++) {
param = this.queryPairs[i];
if (s.length > 0) {
s += '&';
}
if (param[1] === null) {
s += param[0];
} else {
s += param[0];
s += '=';
if (typeof param[1] !== 'undefined') {
s += encodeURIComponent(param[1]);
}
}
}
return s.length > 0 ? '?' + s : s;
};
/**
* returns the first query param value found for the key
* @param {string} key query key
* @return {string} first value found for key
*/
Uri.prototype.getQueryParamValue = function (key) {
var param, i, l;
for (i = 0, l = this.queryPairs.length; i < l; i++) {
param = this.queryPairs[i];
if (key === param[0]) {
return param[1];
}
}
};
/**
* returns an array of query param values for the key
* @param {string} key query key
* @return {array} array of values
*/
Uri.prototype.getQueryParamValues = function (key) {
var arr = [], i, param, l;
for (i = 0, l = this.queryPairs.length; i < l; i++) {
param = this.queryPairs[i];
if (key === param[0]) {
arr.push(param[1]);
}
}
return arr;
};
/**
* removes query parameters
* @param {string} key remove values for key
* @param {val} [val] remove a specific value, otherwise removes all
* @return {Uri} returns self for fluent chaining
*/
Uri.prototype.deleteQueryParam = function (key, val) {
var arr = [], i, param, keyMatchesFilter, valMatchesFilter, l;
for (i = 0, l = this.queryPairs.length; i < l; i++) {
param = this.queryPairs[i];
keyMatchesFilter = decode(param[0]) === decode(key);
valMatchesFilter = param[1] === val;
if ((arguments.length === 1 && !keyMatchesFilter) || (arguments.length === 2 && (!keyMatchesFilter || !valMatchesFilter))) {
arr.push(param);
}
}
this.queryPairs = arr;
return this;
};
/**
* adds a query parameter
* @param {string} key add values for key
* @param {string} val value to add
* @param {integer} [index] specific index to add the value at
* @return {Uri} returns self for fluent chaining
*/
Uri.prototype.addQueryParam = function (key, val, index) {
if (arguments.length === 3 && index !== -1) {
index = Math.min(index, this.queryPairs.length);
this.queryPairs.splice(index, 0, [key, val]);
} else if (arguments.length > 0) {
this.queryPairs.push([key, val]);
}
return this;
};
/**
* test for the existence of a query parameter
* @param {string} key add values for key
* @param {string} val value to add
* @param {integer} [index] specific index to add the value at
* @return {Uri} returns self for fluent chaining
*/
Uri.prototype.hasQueryParam = function (key) {
var i, len = this.queryPairs.length;
for (i = 0; i < len; i++) {
if (this.queryPairs[i][0] == key)
return true;
}
return false;
};
/**
* replaces query param values
* @param {string} key key to replace value for
* @param {string} newVal new value
* @param {string} [oldVal] replace only one specific value (otherwise replaces all)
* @return {Uri} returns self for fluent chaining
*/
Uri.prototype.replaceQueryParam = function (key, newVal, oldVal) {
var index = -1, len = this.queryPairs.length, i, param;
if (arguments.length === 3) {
for (i = 0; i < len; i++) {
param = this.queryPairs[i];
if (decode(param[0]) === decode(key) && decodeURIComponent(param[1]) === decode(oldVal)) {
index = i;
break;
}
}
if (index >= 0) {
this.deleteQueryParam(key, decode(oldVal)).addQueryParam(key, newVal, index);
}
} else {
for (i = 0; i < len; i++) {
param = this.queryPairs[i];
if (decode(param[0]) === decode(key)) {
index = i;
break;
}
}
this.deleteQueryParam(key);
this.addQueryParam(key, newVal, index);
}
return this;
};
/**
* Define fluent setter methods (setProtocol, setHasAuthorityPrefix, etc)
*/
['protocol', 'hasAuthorityPrefix', 'isColonUri', 'userInfo', 'host', 'port', 'path', 'query', 'anchor'].forEach(function(key) {
var method = 'set' + key.charAt(0).toUpperCase() + key.slice(1);
Uri.prototype[method] = function(val) {
this[key](val);
return this;
};
});
/**
* Scheme name, colon and doubleslash, as required
* @return {string} http:// or possibly just //
*/
Uri.prototype.scheme = function() {
var s = '';
if (this.protocol()) {
s += this.protocol();
if (this.protocol().indexOf(':') !== this.protocol().length - 1) {
s += ':';
}
s += '//';
} else {
if (this.hasAuthorityPrefix() && this.host()) {
s += '//';
}
}
return s;
};
/**
* Same as Mozilla nsIURI.prePath
* @return {string} scheme://user:p