Last active
January 16, 2018 14:21
-
-
Save jmas/cb60f3656dd04f6932abfe2312648239 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// 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