diff --git a/client/coral-embed/src/Stream.js b/client/coral-embed/src/Stream.js index cb8bb5bca..4d8980834 100644 --- a/client/coral-embed/src/Stream.js +++ b/client/coral-embed/src/Stream.js @@ -35,12 +35,13 @@ function viewportDimensions() { } export default class Stream { - constructor(el, talkBaseUrl, query, opts) { + constructor(el, talkBaseUrl, query, config) { + this.query = query; - // Create and save the options. + // Extract the non-opts opts from the object. + const {events = null, snackBarStyles = null, onAuthChanged = null, ...opts} = config; this.opts = opts; - this.query = query; this.emitter = new EventEmitter({wildcard: true}); this.pym = new pym.Parent(el.id, buildStreamIframeUrl(talkBaseUrl, query), { @@ -48,7 +49,7 @@ export default class Stream { id: `${el.id}_iframe`, name: `${el.id}_iframe` }); - this.snackBar = new Snackbar(opts.snackBarStyles || {}); + this.snackBar = new Snackbar(snackBarStyles || {}); // Workaround: IOS Safari ignores `width` but respects `min-width` value. this.pym.el.firstChild.style.width = '1px'; @@ -64,8 +65,8 @@ export default class Stream { }); // Attach to the events emitted by the pym parent. - if (opts.events) { - opts.events(this.emitter); + if (events) { + events(this.emitter); } this.pym.onMessage('getConfig', () => { @@ -73,9 +74,9 @@ export default class Stream { }); // If the auth changes, and someone is listening for it, then re-emit it. - if (opts.onAuthChanged) { + if (onAuthChanged) { this.pym.onMessage('coral-auth-changed', (message) => { - opts.onAuthChanged(message ? JSON.parse(message) : null); + onAuthChanged(message ? JSON.parse(message) : null); }); } diff --git a/client/coral-embed/src/index.js b/client/coral-embed/src/index.js index 935972795..1c067757a 100644 --- a/client/coral-embed/src/index.js +++ b/client/coral-embed/src/index.js @@ -2,22 +2,43 @@ import URLSearchParams from 'url-search-params'; import Stream from './Stream'; import StreamInterface from './StreamInterface'; +// Rebuild the origin if it isn't defined. This is our poor-mans polyfill +// for the location API's. +if (!window.location.origin) { + window.location.origin = `${window.location.protocol}//${window.location.hostname}${window.location.port ? `:${window.location.port}` : ''}`; +} + +// parses the Asset URL from the config variable +function parseAssetURL() { + try { + + // Try to get the url from the canonical tag on the page. + return document.querySelector('link[rel="canonical"]').href; + } catch (e) { + console.warn( + 'This page does not include a canonical link tag. Talk has inferred this asset_url from the window object. Query params have been stripped, which may cause a single thread to be present across multiple pages.' + ); + + return window.location.origin + window.location.pathname; + } +} + export class Talk { /** * Render a Talk stream - * @param {HTMLElement} el - Element to render the stream in - * @param {Object} opts - Configuration options for talk - * @param {String} opts.talk - Talk base URL - * @param {String} [opts.title] - Title of Stream (rendered in iframe) - * @param {String} [opts.asset_url] - Asset URL - * @param {String} [opts.asset_id] - Asset ID - * @param {String} [opts.auth_token] - (optional) A jwt representing the session + * @param {HTMLElement} element - Element to render the stream in + * @param {Object} config - Configuration options for talk + * @param {String} config.talk - Talk base URL + * @param {String} [config.title] - Title of Stream (rendered in iframe) + * @param {String} [config.asset_url] - Asset URL + * @param {String} [config.asset_id] - Asset ID + * @param {String} [config.auth_token] - (optional) A jwt representing the session * @return {Object} * * Example: * ``` - * const embed = Talk.render(document.getElementById('talkStreamEmbed'), opts); + * const embed = Talk.render(document.getElementById('talkStreamEmbed'), config); * * // trigger a login with optional token. * embed.login(token); @@ -31,66 +52,47 @@ export class Talk { * }); * ``` */ - static render(el, opts) { - if (!el) { + static render(element, config) { + if (!element) { throw new Error('Please provide Coral.Talk.render() the HTMLElement you want to render Talk in.'); } - if (typeof el !== 'object') { - throw new Error(`Coral.Talk.render() expected HTMLElement but got ${el} (${typeof el})`); + if (typeof element !== 'object') { + throw new Error(`Coral.Talk.render() expected HTMLElement but got ${element} (${typeof element})`); } - - opts = opts || {}; - - // TODO: infer this URL without explicit user input (if possible, may have to be added at build/render time of this script) - if (!opts.talk) { - throw new Error( - 'Coral.Talk.render() expects opts.talk as the Talk Base URL' - ); + if (!config || typeof config !== 'object' || !config.talk) { + throw new Error('Coral.Talk.render() expected configuration with at least opts.talk as the Talk Base URL, none found'); } // Ensure el has an id, as pym can't directly accept the HTMLElement. - if (!el.id) { - el.id = `_${Math.random()}`; + if (!element.id) { + element.id = `_${Math.random()}`; } // Compose the query to send down to the Talk API so it knows what to load. const query = {}; // Parse the url parameters to extract some of the information. - const urlParams = new URLSearchParams(window.location.search); - if (urlParams.get('commentId')) { - query.comment_id = urlParams.get('commentId'); + const search = new URLSearchParams(window.location.search); + + // Pull the commentID out from the query params. + const commentID = search.get('commentId') || search.get('commentID'); + if (commentID) { + query.comment_id = commentID; } // Extract the asset id from the options. - if (opts.asset_id) { - query.asset_id = opts.asset_id; + if (config.asset_id) { + query.asset_id = config.asset_id; } - // Extract the asset url. - if (opts.asset_url) { - query.asset_url = opts.asset_url; - } else { - - // The asset url was not provided so we need to infer the asset url from // details on the page. - - try { - query.asset_url = document.querySelector('link[rel="canonical"]').href; - } catch (e) { - console.warn( - 'This page does not include a canonical link tag. Talk has inferred this asset_url from the window object. Query params have been stripped, which may cause a single thread to be present across multiple pages.' - ); - - if (!window.location.origin) { - window.location.origin = `${window.location.protocol}//${window.location.hostname}${window.location.port ? `:${window.location.port}` : ''}`; - } - - query.asset_url = window.location.origin + window.location.pathname; - } + // Parse the Asset URL. + query.asset_url = config.asset_url; + if (!query.asset_url) { + query.asset_url = parseAssetURL(); } // Create the new Stream. - const stream = new Stream(el, opts.talk, query, opts); + const stream = new Stream(element, config.talk, query, config); // Return the public interface for the stream. return new StreamInterface(stream);