Skip to content

Instantly share code, notes, and snippets.

@jmas
Last active January 16, 2018 14:21
Show Gist options
  • Save jmas/cb60f3656dd04f6932abfe2312648239 to your computer and use it in GitHub Desktop.
Save jmas/cb60f3656dd04f6932abfe2312648239 to your computer and use it in GitHub Desktop.
// utils
function listenMessage(fromWhat, handler) {
fromWhat.addEventListener('message', ({data}) => {
const {type, payload} = data;
handler(type, payload);
});
}
function createFrame({
src='about:blank',
}) {
const frame = document.createElement('iframe');
frame.src = src;
frame.style.width = '100%';
frame.style.maxWidth = '100%';
frame.style.border = 'none';
frame.style.verticalAlign = 'top';
return frame;
}
function sendMessage(type, payload) {
window.parent.postMessage({
type,
payload,
}, '*');
}
function getOrigin(url) {
if (!url) {
return '';
}
const protocolReg = /^https?:\/\//g;
const protocol = url.match(protocolReg);
const noProtocol = url.replace(protocolReg, '');
const domain = noProtocol.split('/')[0];
if (!protocol) {
return `http://${domain}`;
}
return protocol[0] + domain;
}
function insertElementBefore(baseElement, elementForInsert) {
const parent = baseElement.parentNode;
return parent.insertBefore(elementForInsert, baseElement);
}
// message types
const MESSAGE_INIT = 'widget-init';
const MESSAGE_INIT_SUCCESS = 'widget-initSuccess';
const MESSAGE_INIT_FAIL = 'widget-initFail';
const MESSAGE_RESIZE = 'widget-resize';
// widget-related constants
const WIDGET_ATTR = 'data-widget-id';
function createBusinessSelector({
container,
fontFamily='sans-serif',
}) {
const frame = createFrame({
src: 'about:blank',
});
frame.style.position = 'absolute';
container.appendChild(frame);
const frameWindow = frame.contentWindow;
frameWindow.document.body.innerHTML = `<div id="items"></div>`;
const itemsContainer = frameWindow.document.getElementById('items');
return {
setItems(items) {
itemsContainer.innerHTML = items.map(item => (`<a href="#">${item.name}</a>`)).join('...');
},
toggle(state=null) {
const newState = (state === null ? !(frame.style.display === 'block'): state);
frame.style.display = newState ? 'block': 'none';
},
};
}
// widget constructor
function createWidget({
url,
container,
fontFamily='sans-serif',
}) {
const frame = createFrame({
src: url,
});
container.style.position = 'relative';
container.appendChild(frame);
const businessSelector = createBusinessSelector({
container,
});
const widget = {
setHeight(height) {
frame.style.height = height + 'px';
},
toggle(state=null) {
const newState = (state === null ? !(frame.style.display === 'block'): state);
frame.style.display = newState ? 'block': 'none';
},
};
listenMessage(window, (type, payload) => {
switch (type) {
case MESSAGE_INIT_SUCCESS:
widget.toggle(true);
widget.setHeight(payload.widgetHeight);
break;
case MESSAGE_INIT_FAIL:
widget.toggle(false);
break;
case MESSAGE_RESIZE:
widget.setHeight(payload.widgetHeight);
break;
case MESSAGE_PLACES_UPDATE:
businessSelector.setItems(payload.businesses);
break;
}
});
sendMessage(MESSAGE_INIT, {
fontFamily,
});
return widget;
}
function createWidgetFromScriptElement(widgetScriptElement) {
const widgetId = parseInt(widgetScriptElement.getAttribute(WIDGET_ATTR), 10);
const container = insertElementBefore(widgetScriptElement, document.createElement('div'));
const origin = getOrigin(widgetScriptElement.getAttribute('src'));
const widget = createWidget({
url: `${origin}/external/lead-gen/widgets/${widgetId}`,
container,
});
}
// run
[...document.querySelectorAll(`[${WIDGET_ATTR}]`)].forEach(el => {
createWidgetFromScriptElement(el);
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment