JavaScript API functions

Examples

Displaying the user’s info

This example will display the user’s name in the application.

<!-- index.html -->
<html>
    <head>
        <!-- styles -->
    </head>
    <body>
        <h1>Welcome <span id="name"></span></h1>
        <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit...</p>
        <script src="main.es6.js"></script>
    </body>
</html>
// main.es6.js
window.onShowpadLibLoaded = () => addUserName();

function addUserName () {
    const userInfo = window.ShowpadLib.getUserInfo();
    document.getElementById('name').innerHTML = userInfo.user_name;
}

Download example app

Create a PDF file and upload it to My Files

<!-- index.html -->
<html>
    <head></head>
    <body>
        <input type="button" onclick="createPdf()" id="create" value="Create PDF" disabled="disabled"/><br/>
        <input type="button" onclick="uploadPdf()" id="upload" value="Upload PDF" disabled="disabled"/><br/>

        <div id="output"></div>

        <script src="node_modules/whatwg-fetch/fetch.js"></script>
        <script src="jspdf.js"></script>
        <script src="./main.es6.js"></script>
    </body>
</html>
// main.es6.js
'use strict';

let apiConfig = null;
let pdfDocBlob = null;

window.onShowpadLibLoaded = () => window.ShowpadLib.getShowpadApi(onShowpadApiConfig);

function onShowpadApiConfig (config)
{
    apiConfig = config;
    document.getElementById('create').removeAttribute('disabled');
}

function createPdf()
{
    if (pdfDocArray == null)
    {
        const doc = new jsPDF();

        doc.ellipse(40, 20, 10, 5);

        doc.setFillColor(0,0,255);
        doc.ellipse(80, 20, 10, 5, 'F');

        doc.setLineWidth(1);
        doc.setDrawColor(0);
        doc.setFillColor(255,0,0);
        doc.circle(120, 20, 5, 'FD');

        pdfDocBlob = doc.output('blob');

        document.getElementById('output').innerHTML += 'PDF Created in memory<br/>';
        document.getElementById('upload').disabled = false;
    }
}

function uploadPdf()
{
    const url = `${apiConfig.url}/api/v3/divisions/mine/assets.json`;
    const formData = new FormData();

    // The third argument needs to have the correct file-extension!
    formData.append('file', pdfDocBlob, 'file.pdf');
    formData.append('isPersonal', 'true');

    var xhr = new XMLHttpRequest();
    xhr.open('POST', url);
    xhr.setRequestHeader('Authorization', `Bearer ${accessToken}`);

    xhr.onreadystatechange = function () {
        if (xhr.readyState == 4) {
            const json = JSON.parse(xhr.responseText);
            if (json.response && json.response.resourcetype === 'Ticket') {
                pollTicket(json.response.id);
            }
        }
    };

    xhr.send(formData);
}

function pollTicket (id) {
    const url = `${apiConfig.url}/api/v3/tickets/${id}.json`;
    const config = {
        headers: {
            'Authorization': `Bearer ${apiConfig.accessToken}`
        }
    };

    fetch(url, config)
        .then(response => response.json())
        .then(json => {
            if (json.response.status) {
                switch(json.response.status) {
                    case 'completed':
                        // File was processed
                        if (json.response.asset && json.response.asset.id) {
                            const assetId = json.response.asset.id;
                            console.log("file processed with asset id: " + assetId);
                            // File was processed
                        }
                        else {
                            // Something else failed
                        }
                        break;
                    case 'queued':
                    case 'processing':
                        // Still processing, poll again in 2 seconds
                        setTimeout(() => {
                            pollTicket(id);
                        }, 2000);
                        break;
                    case 'failed':
                        // File processing failed..
                        break;
                }
            }
        });
}

Querying the API

This example will load 2 available tags for the logged in user and then load all the available assets which have been tagged with one of the previously loaded tags.

<!-- index.html -->
<html>
    <head>
        <!-- styles -->
    </head>
    <body>
        <h1>Click one of your assets</h1>
        <ul id="asset-list"></ul>

        <script src="main.es6.js"></script>
    </body>
</html>
// main.es6.js
const TAG_DEMO_1 = '3709662152eeb8467aa30';
const TAG_DEMO_2 = 'da31b6bcf30e98177d6c8';

const NODE_FIELDS = `id,label,icon,type,asset,slug,hideLabel,left,right,level,` +
    `rootNode,parentNode,channel,humanReadablePath,path,url,createdAt`;
const NODE_EXPAND = `asset,icon,asset.tags`;

window.onShowpadLibLoaded = () => displayAssets();

function displayAssets () {
    findChannelNodesWithTags([TAG_DEMO_1, TAG_DEMO_2], nodes => {
        if (nodes !== null) {
            document.getElementById('asset-list').innerHTML = nodes
                .map(node => nodeDataToHtml(node))
                .join('');
        }
    });
}

function findChannelNodesWithTags (tagIds, callbackFn) {

    const endpoint = `channelnodes.json?assetTagIds=${tagIds.join('%2C')}&fields=${NODE_FIELDS}&expand=${NODE_EXPAND}`;

    window.ShowpadLib.getShowpadApi(onShowpadApiConfig);

    function onShowpadApiConfig (apiConfig) {
        if (apiConfig !== null) {
            getJson(endpoint, apiConfig, callbackFn);
        }
        else {
            callbackFn(null);
        }
    }
}

function getJson (endpoint, apiConfig, callbackFn) {

    const url = `${apiConfig.url}/api/v3/${endpoint}`;
    const config = {
        headers: {
            Authorization: `Bearer ${apiConfig.accessToken}`
        }
    };

    fetch(url, config)
        .then(response => {
            if (response.ok) {
                return response
                    .json()
                    .then(data => callbackFn(data.response.items));
            }
            else {
                callbackFn(null);
            }
        })
        .catch(() => callback(null));
}

function nodeDataToHtml (node) {
    return `
        <li>
            <a href="${node.asset.appLink}?modal=true">
                <img src="${node.asset.previewDownloadLink}" />
                <label>${node.label}</label>
            </a>
        </li>
    `;
}

Download example app

Calling the Salesforce API through an iFrame

<!-- index.html (in HTML Content) -->
<html>
    <head></head>
    <body>
        <input type="button" value="Fetch Contacts" onclick="fetchContacts()" />
        <iframe
            height="0"
            width="0"
            src="https://my-whitelisted-domain.com/salesforce-iframe.html"
            name="salesforce-iframe"
            id="salesforce-iframe"
            border="0"
        ></iframe>

        <script src="./main.es6.js"></script>
    </body>
</html>
// main.es6.js (in HTML Content)
const iframeElement = document.getElementById('salesforce-iframe');
const iframeHost = 'https://my-whitelisted-domain.com';

// Wait for ShowpadLib to be ready
window.onShowpadLibLoaded = () => getSalesforceInfo();

// Listen for message from the iFrame
window.addEventListener("message", onMessage, false);

// Fetch the Salesforce Info and post it to the iframe.
function getSalesforceInfo ()
{
    window.ShowpadLib.getSalesforceApi(data => {
        if (data.accessToken && data.url) {
            data.type = 'info';
            iframeElement.contentWindow.postMessage(data, iframeHost);
        }
        else {
            // Can't call Salesforce, show error
        }
    });
}

// Do an API call
function fetchContacts ()
{
    var q = encodeURIComponent('SELECT Id, LastName, FirstName FROM Contact LIMIT 50').replace(/%20/g, '+');

    var data = {
        type: 'call',
        method: 'GET',
        path: '/services/data/v33.0/query?q=' + q
    };

    iframeElement.contentWindow.postMessage(data, iframeHost);
}


function onMessage(event) {
    // Handle the event here
    console.log('Got Response in source: ' + event.data);
}
<!-- salesforce-iframe.html (Hosted on https://my-whitelisted-domain.com/) -->
<html>
    <head></head>
    <body>
        <script src="./salesforce-iframe.es6.js"></script>
    </body>
</html>
// salesforce-iframe.es6.js (Hosted on https://my-whitelisted-domain.com/)
const info = {
    uri: null,
    token: null
};

window.addEventListener("message", onMessage, false);
window.sfCall = sfCall;

function onMessage(event)
{
    const  data = event.data;

    if (data.type === 'info')
    {
        info.uri = data.url;
        info.token = data.accessToken;
    }
    else if (data.type === 'call') {
        sfCall(data.method, data.path, function (response){
            event.source.postMessage(response, '*');
        });
    }
}

/**
 * @param  {string} method GET,POST,...
 * @param  {string} path eg. '/services/data/v33.0/query?q=xxx'
 * @return {Promise}
 */
function sfCall (method, path, callbackFn)
{
    const url = info.uri + path;
    const config = {
        headers : {
            Authorization: `Bearer ${info.token}`
        }
    };

    fetch(url, config)
        .then(checkStatus)
        .then(response => {
            callbackFn({
                type: 'success',
                response: response
            });
        })
        .catch(error => {
            callbackFn({
                type: 'error',
                response: response
            });
        });
}

function checkStatus (response)
{
    if (response.status >= 200 && response.status < 300) {
        return response;
    }

    const error = new Error();
    error.statusCode = response.status;
    throw error;
}