Tableau Embedding API v3 - Promise not resolving for getMarksAsync() function - javascript

We are currently exploring the possibility of grabbing selected values when users click on marks using Tableau Embedding API V3.
However, Whenever I click on the event, the event is triggered but, the promise is showing as pending.
Can you please check the following and let me know if there is any mistake from my side in resolving the promise.
<html>
<head>
<meta charset="utf-8">
<title>Tableau 8 Javascrip API</title>
<script type="text/javascript">
function getSelectedMarks(marksEvent) {
alert('Triggered');
console.log(marksEvent.detail.getMarksAsync().then(reportSelectedMarks));
// const marksSelected = await marksEvent.detail.getMarksAsync();
// const numMarks = marksSelected.data[0].data.length;
// alert(`${numMarks} marks Selected`);
}
function reportSelectedMarks(marks) {
console.log(marks);
}
</script>
</head>
<body>
<tableau-viz
id="tableauViz"
src='http://public.tableau.com/views/WorldIndicators/GDPpercapita?Region='
device="phone" toolbar="bottom" hide-tabs
>
</tableau-viz>
<script type='module'>
import {TableauEventType} from 'https://uatdataviz.hruk.pri/javascripts/api/tableau.embedding.3.latest.min.js';
let viz = document.getElementById('tableauViz');
viz.addEventListener(TableauEventType.FirstInteractive, async (event) => {
viz.addEventListener(TableauEventType.MarkSelectionChanged, getSelectedMarks);
});
</script>
</body>
</html>
For example Tableau Embedding API reference for Event Listeners
Any assistance would be appreciated.

Issue resolved. I have to use https instead of http for viz URL.

Related

Printing a HTML + JavaScript variable from an external js to an index.html file using fetch + node.js

I was under the impression I could use node.js to do this but you cannot b/c of reasons given by the answer. Essentially I just wanted to use fetch and that's all you really need. Here is a very basic way of using it.
async function fetch_weather() {
const response = await fetch('https://api.openweathermap.org/data/2.5/weather?zip=90210,us&appid={API-KEY}&units=imperial');
const weather = await response.json();
document.querySelector("#weather").innerHTML =
<table>
<caption>Current weather data using <code>fetch</code></caption>
<br>
<thead>
<tr>
<th>City/State</th>
<th>Current Temp</th>
<th>Feels Like:</th>
<th>Longitude:</th>
<th>Latitude:</th>
<th>Sunrise (Unix)</th>
<th>Sunset (Unix)</th>
</tr>
</thead>
<tbody>
<tr>
<td>${weather.name}, GA</td>
<td>${weather.main.temp}</td>
<td>${weather.main.feels_like}</td>
<td>${weather.coord.lon}</td>
<td>${weather.coord.lat}</td>
<td>${weather.sys.sunrise}</td>
<td>${weather.sys.sunset}</td>
</tr>
</tbody>
</table>
};
Here was the non-working node.js code:
index.js
import fetch from './node-fetch';
async function fetchWeatherJSON() {
const response = await fetch('https://api.openweathermap.org/data/.../&appid={API-KEY}');
const weather = await response.json();
return weather;
}
fetchWeatherJSON().then(weather => {
document.querySelector("#weather").innerHTML = `Longitude: ${weather.coord.lon}`
console.log(`Longitude: ${weather.coord.lon}`);
console.log(`Latitude: ${weather.coord.lat}`);
console.log(`Current Temp: ${weather.main.temp}`);
console.log(`Feels Like: ${weather.main.feels_like}`);
console.log(`Sunrise: ${weather.sys.sunrise}`);
console.log(`Sunset: ${weather.sys.sunset}`);
console.log(`City/State: ${weather.name}, GA`);
});
Inside fetchWeatherJSON().then(...) part I tried things like
document.querySelector("#weather").innerHTML = `Longitude: ${weather.coord.lon}`;
but none of those types of ways worked. I have no idea if there is just something I am doing wrong here as far as selectors or this isn't the best way (or any way) to do it.
I'd like to print this to an index.html page, here is a simple example of some HTML. It would be nice to be able to print whatever is shown the javascript console inside the opening an close <p> elements.
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Node.js Weather App</title>
</head>
<body>
<h2>Node.js Weather App</h2>
<div id="weather"></div>
<script type="text/javascript" src="index.js"></script>
</body>
</html>
This code cannot work. Not on node.js nor on the browser because:
Node.js has no fetch built in, so you need an extra library for it. For this you use node-fetch. But in the same .js file you try to access DOM elements with document.. Dom elements does not exist in Node.js, only inside the browser.
This code wont work, because usually you have an bundler like Vite or webpack that bundles your npm packages. Anyway, node-fetch is only made for Node.js, not for the browser.
The browser already has an built-in fetch.
Set a console.log to check if "weather" has any value.
Also, your QuerySelector is wrong:
document.querySelector("#weatherHTML")
You are using the wrong type of query selector: document.querySelector("weatherHTML") will select elements named accordingly (<weatherHTML></weatherHTML>).
You should use document.querySelector("#weatherHTML") to select the element with the corresponding id.
This is also equivalent to document.getElementById("weatherHTML")
Using this principle, this is the new fetchWeatherJSON callback:
fetchWeatherJSON().then(weather => {
console.log(`Longitude: ${weather.coord.lon}`);
console.log(`Latitude: ${weather.coord.lat}`);
console.log(`Current Temp: ${weather.main.temp}`);
console.log(`Feels Like: ${weather.main.feels_like}`);
console.log(`Sunrise: ${weather.sys.sunrise}`);
console.log(`Sunset: ${weather.sys.sunset}`);
console.log(`City/State: ${weather.name}, GA`);
document.querySelector("#weatherHTML").innerHTML = `Longitude: ${weather.coord.lon}...`
});

How do you update Docusign Clickwrap render call to include a custom value for clientUserId

Here is Docusign's Clickwrap example.
var myCustomUserId = Math.floor(Math.random() * 100000) + 1;
console.log(myCustomUserId); // this works
<div id="ds-terms-of-service"></div>
<script src="https://demo.docusign.net/clickapi/sdk/latest/docusign-click.js"></script>
<script>docuSignClick.Clickwrap.render({
environment: 'https://demo.docusign.net',
accountId: 'daf5048a-xxxx-xxxx-xxxx-d5ae2a842017',
clickwrapId: '9888ca17-xxxx-xxxx-xxxx-9bd95f46345d',
clientUserId: myCustomUserId
}, '#ds-terms-of-service');
I am creating an overly simple html app that is attempting to send a custom userid to the Clickwrap service. However, the above example does not work (even using our actual accountId and clickwrapId). How do you update myCustomUserId in this clickwrap call with a variable inside my html (hopefully using simple javascript/css/html)?
I have a hunch the example code I posted above (copied from their website) was meant as a 1-off test and not a fully functioning example. I want to confirm my suspicion that we may have to call another api to request a clickwrap, and pass that api the clientUserId, and in return, docusign returns the full clickwrap with the embedded clientUserId value.
Thanks in advance!
<!DOCTYPE html>
<html>
<head>
<title>Test</title>
</head>
<body>
<div id="ds-clickwrap"></div>
<script src="https://demo.docusign.net/clickapi/sdk/latest/docusign-click.js"></script>
<script>
const myCustomUserId = Math.floor(Math.random() * 100000) + 1;
docuSignClick.Clickwrap.render(
{
environment: "https://demo.docusign.net",
accountId: "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
clickwrapId: "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
clientUserId: `${myCustomUserId}`
},
"#ds-clickwrap"
);
</script>
<script src="index.js" async defer></script>
</body>
</html>
Hey zenbudda! For testing purposes, This should do the trick. You need to pass in your custom ID properly.

How do I use the Tableau Javascript API to embed dashboards in a webpage for dashboards hosted in Tableau Online?

I am trying to recreate the example provided by Tableau here with a dashboard that is hosted in Tableau Online. A separate article from Tableau talks about modifying the URL of the JS API based on where the dashboard is hosted, which I've tried to follow.
Even though the resulting embed should require a login to be displayed, I expect that login to be displayed in that embedded output/iframe on my webpage. Please refer to the included code. Instead, I'm getting a CORS error:
Refused to display 'https://10ay.online.tableau.com/site/jpl/views/JPLDashboard_V05_JUE/Awareness?:iid=2&:size=800,700&:embed=y&:showVizHome=n&:bootstrapWhenNotified=y&:tabs=n&:apiID=host0#navType=1&navSrc=Parse' in a frame because it set 'X-Frame-Options' to 'sameorigin'.
Is the approach I'm taking correct? If embedding Tableau Online dashboards is possible with their JS API, how do I avoid the CORS error?
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>JPL Dashboard</title>
<script type="text/javascript" src="https://online.tableau.com/javascripts/api/tableau-2.min.js"></script>
<script type="text/javascript">
function initViz() {
var containerDiv = document.getElementById("vizContainer"),
//url = "http://public.tableau.com/views/RegionalSampleWorkbook/Storms",
url = "https://10ay.online.tableau.com/site/jpl/views/JPLDashboard_V05_JUE/Awareness?:iid=2",
options = {
hideTabs: true,
onFirstInteractive: function() {
console.log("Run this code when the viz has finished loading.");
}
};
var viz = new tableau.Viz(containerDiv, url, options);
}
</script>
</head>
<body>
<div id="vizContainer" style="width:800px; height:700px;"></div>
<script type="text/javascript">
(function () {
window.onload = function () {
initViz();
};
})();
</script>
</body>
</html>
Ensure that the URL used for embedding the view is from the Share option in Tableau Online:
In Tableau Online, navigate to the view encountering the problem.
Click the Share button.
Copy the URL link within the Link section.
Configure the embed code to use this URL rather than the Tableau Online URL in the browser address bar.
If it is correct, try to add: <meta http-equiv="X-Frame-Options" content="allow"> in the HTML header
I hope it is helpful,
Gigi

Why does $.ajax() cause the wep page to postback twice?

Can anyone tell me why does this $.ajax() cause the webpage to do a postback twice? Isn't it suppose to fire only once?
This is what I saw when debugging in Visual Studio and it is causing the server-side script to run twice. I'm using JQuery version 2.0.0 .
The ThrobblerAnimationBegin() function is what show the processing icon animation to let the end-user know the webpage is busy executing the script. The #{} bracket is the server-side script, this is how I was able to tell when a postback was made to the server-side backend, by using debugging breakpoint.
Thanks...
#{
string foo = "Me Me Me";
foo += ", fee fee fee";
}<!DOCTYPE html>
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=UTF-8" />
<title>BookItOut - A New Dawn In Auto Pricing"</title>
<script type="text/javascript" src="~/Member/Scripts/jquery-v2.0.3/jquery-v2.0.3.min.js"></script>
<script type="text/javascript">
function ThrobblerAnimationBegin() {
return $.ajax();
}
function ThrobblerAnimationEnd() {
}
$(document).ready(function () {
function DrawVehicleCostPerDays() {
var $deferred = $.Deferred(); //$.Deferred.done() --> to allow ayschronous sleep/delay until this current function() is finish before running done() afterward to continue. [[http://stackoverflow.com/questions/12116505/wait-till-a-function-is-finished-until-running-another-function]]...
$deferred.resolve();
return $deferred;
}
//Load the script...
ThrobblerAnimationBegin().done(function () {
//alert("done");
DrawVehicleCostPerDays(
).done(function () { ThrobblerAnimationEnd(); /*alert('success');*/ }
).fail(function () { ThrobblerAnimationEnd(); /*alert('failed');*/ });
});
});
</script>
</head>
<body>
</body>
</html>
EDIT as per request Here's the snapshot from Firefox's Firebug.
Your ajax is not firing twice. Instead, what you are seeing is the initial page load (what you are counting as the first ajax request) and then the ajax request (what you were counting as the second). Since you did not specify a URL in the .ajax() call, it made a request to the same page, which is likely what confused you.
You should probably read the .ajax() documentation for simple examples of how to use it.

Load YouTube JSON API dynamically

I want to dynamically make different YouTube JSON API requests and then use a function to sort the data I want.
Currently following the examples on the YouTube data JSON API site here.
Here is my current code which is getting me the id's nicely.
My question is currently it's using a script tag and the callback URL query to use my function. Is there a different way that I can implement in JavaScript only and keep doing requests that call my getid function?
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>Untitled Document</title>
</head>
<body>
<script type="text/javascript">
function getid(data) {
var i=0;
for(items in data.data){
i++
console.log(data.data.items[i].id)
}
}
</script><script type="text/javascript" src="https://gdata.youtube.com/feeds/api/videos?q=surfing&v=2&alt=jsonc&callback=getid"></script>
</body>
</html>
jsonp function below will dynamically create a script tag and append it to the body.
function jsonp(url,callback) {
var script = document.createElement("script");
script.setAttribute("src",url);
script.setAttribute("type","text/javascript");
document.body.appendChild(script);
}
function getid(data) {
var i=0;
for(items in data.data){
i++
console.log(data.data.items[i].id)
}
}
// pass a url and callback
var url = "https://gdata.youtube.com/feeds/api/videos?q=surfing&v=2&alt=jsonc&callback=getid";
jsonp(url, getid)

Categories