From 848193074a10d9799ffbc27918a8b264a2e101bb Mon Sep 17 00:00:00 2001 From: fragosti Date: Fri, 16 Nov 2018 15:21:04 -0800 Subject: feat: close and open instant based on history changes --- packages/instant/src/index.umd.ts | 51 +++++++++++++++++++++++++++++---------- 1 file changed, 38 insertions(+), 13 deletions(-) (limited to 'packages/instant/src/index.umd.ts') diff --git a/packages/instant/src/index.umd.ts b/packages/instant/src/index.umd.ts index 0274db30c..81b7aebe3 100644 --- a/packages/instant/src/index.umd.ts +++ b/packages/instant/src/index.umd.ts @@ -5,6 +5,7 @@ import * as ReactDOM from 'react-dom'; import { DEFAULT_ZERO_EX_CONTAINER_SELECTOR, INJECTED_DIV_CLASS, INJECTED_DIV_ID } from './constants'; import { ZeroExInstantOverlay, ZeroExInstantOverlayProps } from './index'; import { assert } from './util/assert'; +import { util } from './util/util'; export const render = (props: ZeroExInstantOverlayProps, selector: string = DEFAULT_ZERO_EX_CONTAINER_SELECTOR) => { assert.isValidOrderSource('orderSource', props.orderSource); @@ -36,21 +37,45 @@ export const render = (props: ZeroExInstantOverlayProps, selector: string = DEFA assert.isWeb3Provider('props.provider', props.provider); } assert.isString('selector', selector); - const appendToIfExists = document.querySelector(selector); - assert.assert(!_.isNull(appendToIfExists), `Could not find div with selector: ${selector}`); - const appendTo = appendToIfExists as Element; - const injectedDiv = document.createElement('div'); - injectedDiv.setAttribute('id', INJECTED_DIV_ID); - injectedDiv.setAttribute('class', INJECTED_DIV_CLASS); - appendTo.appendChild(injectedDiv); - const instantOverlayProps = { - ...props, - onClose: () => { - appendTo.removeChild(injectedDiv); + // Render instant and return a callback that allows you to close it. + const renderInstant = () => { + const appendToIfExists = document.querySelector(selector); + assert.assert(!_.isNull(appendToIfExists), `Could not find div with selector: ${selector}`); + const appendTo = appendToIfExists as Element; + const injectedDiv = document.createElement('div'); + injectedDiv.setAttribute('id', INJECTED_DIV_ID); + injectedDiv.setAttribute('class', INJECTED_DIV_CLASS); + appendTo.appendChild(injectedDiv); + const instantOverlayProps = { + ...props, + onClose: () => window.history.back(), + }; + ReactDOM.render(React.createElement(ZeroExInstantOverlay, instantOverlayProps), injectedDiv); + const close = () => appendTo.removeChild(injectedDiv); + return close; + }; + // Before we render, push to history saying that instant is showing for this part of the history. + window.history.pushState({ zeroExInstantShowing: true }, '0x Instant'); + let closeInstant = renderInstant(); + + let prevOnPopState = util.boundNoop; + if (window.onpopstate) { + prevOnPopState = window.onpopstate.bind(window); + } + window.onpopstate = (e: PopStateEvent) => { + // Don't override integrators handler. + prevOnPopState(e); + // e.state represents the new state + if (e.state && e.state.zeroExInstantShowing) { + // The user pressed fowards, so re-render instant. + closeInstant = renderInstant(); + } else { + // User pressed back, so close instant. + closeInstant(); + delete window.onpopstate; if (!_.isUndefined(props.onClose)) { props.onClose(); } - }, + } }; - ReactDOM.render(React.createElement(ZeroExInstantOverlay, instantOverlayProps), injectedDiv); }; -- cgit v1.2.3 From f7914af9c564d4521e375fb3dd5825da763df7d6 Mon Sep 17 00:00:00 2001 From: fragosti Date: Fri, 16 Nov 2018 15:23:44 -0800 Subject: feat: rename props to config --- packages/instant/src/index.umd.ts | 50 +++++++++++++++++++++------------------ 1 file changed, 27 insertions(+), 23 deletions(-) (limited to 'packages/instant/src/index.umd.ts') diff --git a/packages/instant/src/index.umd.ts b/packages/instant/src/index.umd.ts index 81b7aebe3..fda21478f 100644 --- a/packages/instant/src/index.umd.ts +++ b/packages/instant/src/index.umd.ts @@ -7,34 +7,38 @@ import { ZeroExInstantOverlay, ZeroExInstantOverlayProps } from './index'; import { assert } from './util/assert'; import { util } from './util/util'; -export const render = (props: ZeroExInstantOverlayProps, selector: string = DEFAULT_ZERO_EX_CONTAINER_SELECTOR) => { - assert.isValidOrderSource('orderSource', props.orderSource); - if (!_.isUndefined(props.defaultSelectedAssetData)) { - assert.isHexString('defaultSelectedAssetData', props.defaultSelectedAssetData); +export interface ZeroExInstantConfig extends ZeroExInstantOverlayProps { + shouldUseHistoryApi?: boolean; +} + +export const render = (config: ZeroExInstantConfig, selector: string = DEFAULT_ZERO_EX_CONTAINER_SELECTOR) => { + assert.isValidOrderSource('orderSource', config.orderSource); + if (!_.isUndefined(config.defaultSelectedAssetData)) { + assert.isHexString('defaultSelectedAssetData', config.defaultSelectedAssetData); } - if (!_.isUndefined(props.additionalAssetMetaDataMap)) { - assert.isValidAssetMetaDataMap('props.additionalAssetMetaDataMap', props.additionalAssetMetaDataMap); + if (!_.isUndefined(config.additionalAssetMetaDataMap)) { + assert.isValidAssetMetaDataMap('props.additionalAssetMetaDataMap', config.additionalAssetMetaDataMap); } - if (!_.isUndefined(props.defaultAssetBuyAmount)) { - assert.isNumber('props.defaultAssetBuyAmount', props.defaultAssetBuyAmount); + if (!_.isUndefined(config.defaultAssetBuyAmount)) { + assert.isNumber('props.defaultAssetBuyAmount', config.defaultAssetBuyAmount); } - if (!_.isUndefined(props.networkId)) { - assert.isNumber('props.networkId', props.networkId); + if (!_.isUndefined(config.networkId)) { + assert.isNumber('props.networkId', config.networkId); } - if (!_.isUndefined(props.availableAssetDatas)) { - assert.areValidAssetDatas('availableAssetDatas', props.availableAssetDatas); + if (!_.isUndefined(config.availableAssetDatas)) { + assert.areValidAssetDatas('availableAssetDatas', config.availableAssetDatas); } - if (!_.isUndefined(props.onClose)) { - assert.isFunction('props.onClose', props.onClose); + if (!_.isUndefined(config.onClose)) { + assert.isFunction('props.onClose', config.onClose); } - if (!_.isUndefined(props.zIndex)) { - assert.isNumber('props.zIndex', props.zIndex); + if (!_.isUndefined(config.zIndex)) { + assert.isNumber('props.zIndex', config.zIndex); } - if (!_.isUndefined(props.affiliateInfo)) { - assert.isValidAffiliateInfo('props.affiliateInfo', props.affiliateInfo); + if (!_.isUndefined(config.affiliateInfo)) { + assert.isValidAffiliateInfo('props.affiliateInfo', config.affiliateInfo); } - if (!_.isUndefined(props.provider)) { - assert.isWeb3Provider('props.provider', props.provider); + if (!_.isUndefined(config.provider)) { + assert.isWeb3Provider('props.provider', config.provider); } assert.isString('selector', selector); // Render instant and return a callback that allows you to close it. @@ -47,7 +51,7 @@ export const render = (props: ZeroExInstantOverlayProps, selector: string = DEFA injectedDiv.setAttribute('class', INJECTED_DIV_CLASS); appendTo.appendChild(injectedDiv); const instantOverlayProps = { - ...props, + ...config, onClose: () => window.history.back(), }; ReactDOM.render(React.createElement(ZeroExInstantOverlay, instantOverlayProps), injectedDiv); @@ -73,8 +77,8 @@ export const render = (props: ZeroExInstantOverlayProps, selector: string = DEFA // User pressed back, so close instant. closeInstant(); delete window.onpopstate; - if (!_.isUndefined(props.onClose)) { - props.onClose(); + if (!_.isUndefined(config.onClose)) { + config.onClose(); } } }; -- cgit v1.2.3 From 9a53a29b1f421cdea190b6175dec437ec6d76a39 Mon Sep 17 00:00:00 2001 From: fragosti Date: Fri, 16 Nov 2018 15:41:21 -0800 Subject: feat: allow integrator to disable pushstate logic --- packages/instant/src/index.umd.ts | 54 +++++++++++++++++++++------------------ 1 file changed, 29 insertions(+), 25 deletions(-) (limited to 'packages/instant/src/index.umd.ts') diff --git a/packages/instant/src/index.umd.ts b/packages/instant/src/index.umd.ts index fda21478f..381c9094b 100644 --- a/packages/instant/src/index.umd.ts +++ b/packages/instant/src/index.umd.ts @@ -8,7 +8,7 @@ import { assert } from './util/assert'; import { util } from './util/util'; export interface ZeroExInstantConfig extends ZeroExInstantOverlayProps { - shouldUseHistoryApi?: boolean; + shouldDisablePushToHistory?: boolean; } export const render = (config: ZeroExInstantConfig, selector: string = DEFAULT_ZERO_EX_CONTAINER_SELECTOR) => { @@ -50,36 +50,40 @@ export const render = (config: ZeroExInstantConfig, selector: string = DEFAULT_Z injectedDiv.setAttribute('id', INJECTED_DIV_ID); injectedDiv.setAttribute('class', INJECTED_DIV_CLASS); appendTo.appendChild(injectedDiv); + const close = () => appendTo.removeChild(injectedDiv); const instantOverlayProps = { ...config, - onClose: () => window.history.back(), + // If we are using the history API, just go back to close + onClose: () => (config.shouldDisablePushToHistory ? close() : window.history.back()), }; ReactDOM.render(React.createElement(ZeroExInstantOverlay, instantOverlayProps), injectedDiv); - const close = () => appendTo.removeChild(injectedDiv); return close; }; - // Before we render, push to history saying that instant is showing for this part of the history. - window.history.pushState({ zeroExInstantShowing: true }, '0x Instant'); - let closeInstant = renderInstant(); + if (config.shouldDisablePushToHistory) { + renderInstant(); + } else { + // Before we render, push to history saying that instant is showing for this part of the history. + window.history.pushState({ zeroExInstantShowing: true }, '0x Instant'); + let closeInstant = renderInstant(); - let prevOnPopState = util.boundNoop; - if (window.onpopstate) { - prevOnPopState = window.onpopstate.bind(window); - } - window.onpopstate = (e: PopStateEvent) => { - // Don't override integrators handler. - prevOnPopState(e); - // e.state represents the new state - if (e.state && e.state.zeroExInstantShowing) { - // The user pressed fowards, so re-render instant. - closeInstant = renderInstant(); - } else { - // User pressed back, so close instant. - closeInstant(); - delete window.onpopstate; - if (!_.isUndefined(config.onClose)) { - config.onClose(); - } + let prevOnPopState = util.boundNoop; + if (window.onpopstate) { + prevOnPopState = window.onpopstate.bind(window); } - }; + window.onpopstate = (e: PopStateEvent) => { + // Don't override integrators handler. + prevOnPopState(e); + // e.state represents the new state + if (e.state && e.state.zeroExInstantShowing) { + // The user pressed fowards, so re-render instant. + closeInstant = renderInstant(); + } else { + // User pressed back, so close instant. + closeInstant(); + if (!_.isUndefined(config.onClose)) { + config.onClose(); + } + } + }; + } }; -- cgit v1.2.3 From a4f6cd21bd289eb2baaee8b6b7d09cbb9e0955dc Mon Sep 17 00:00:00 2001 From: fragosti Date: Fri, 16 Nov 2018 15:45:02 -0800 Subject: feat: be more specific with callback name --- packages/instant/src/index.umd.ts | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'packages/instant/src/index.umd.ts') diff --git a/packages/instant/src/index.umd.ts b/packages/instant/src/index.umd.ts index 381c9094b..298b7733f 100644 --- a/packages/instant/src/index.umd.ts +++ b/packages/instant/src/index.umd.ts @@ -41,7 +41,7 @@ export const render = (config: ZeroExInstantConfig, selector: string = DEFAULT_Z assert.isWeb3Provider('props.provider', config.provider); } assert.isString('selector', selector); - // Render instant and return a callback that allows you to close it. + // Render instant and return a callback that allows you to remove it from the DOM. const renderInstant = () => { const appendToIfExists = document.querySelector(selector); assert.assert(!_.isNull(appendToIfExists), `Could not find div with selector: ${selector}`); @@ -50,21 +50,21 @@ export const render = (config: ZeroExInstantConfig, selector: string = DEFAULT_Z injectedDiv.setAttribute('id', INJECTED_DIV_ID); injectedDiv.setAttribute('class', INJECTED_DIV_CLASS); appendTo.appendChild(injectedDiv); - const close = () => appendTo.removeChild(injectedDiv); + const removeFromDom = () => appendTo.removeChild(injectedDiv); const instantOverlayProps = { ...config, // If we are using the history API, just go back to close - onClose: () => (config.shouldDisablePushToHistory ? close() : window.history.back()), + onClose: () => (config.shouldDisablePushToHistory ? removeFromDom() : window.history.back()), }; ReactDOM.render(React.createElement(ZeroExInstantOverlay, instantOverlayProps), injectedDiv); - return close; + return removeFromDom; }; if (config.shouldDisablePushToHistory) { renderInstant(); } else { // Before we render, push to history saying that instant is showing for this part of the history. window.history.pushState({ zeroExInstantShowing: true }, '0x Instant'); - let closeInstant = renderInstant(); + let removeInstant = renderInstant(); let prevOnPopState = util.boundNoop; if (window.onpopstate) { @@ -76,10 +76,10 @@ export const render = (config: ZeroExInstantConfig, selector: string = DEFAULT_Z // e.state represents the new state if (e.state && e.state.zeroExInstantShowing) { // The user pressed fowards, so re-render instant. - closeInstant = renderInstant(); + removeInstant = renderInstant(); } else { // User pressed back, so close instant. - closeInstant(); + removeInstant(); if (!_.isUndefined(config.onClose)) { config.onClose(); } -- cgit v1.2.3 From 51dce3008841b7bdc9080212f8b5e12a90f6cce9 Mon Sep 17 00:00:00 2001 From: fragosti Date: Fri, 16 Nov 2018 15:48:55 -0800 Subject: feat: add assert for shouldDisablePushToHistory --- packages/instant/src/index.umd.ts | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) (limited to 'packages/instant/src/index.umd.ts') diff --git a/packages/instant/src/index.umd.ts b/packages/instant/src/index.umd.ts index 298b7733f..9703c6fc0 100644 --- a/packages/instant/src/index.umd.ts +++ b/packages/instant/src/index.umd.ts @@ -17,28 +17,31 @@ export const render = (config: ZeroExInstantConfig, selector: string = DEFAULT_Z assert.isHexString('defaultSelectedAssetData', config.defaultSelectedAssetData); } if (!_.isUndefined(config.additionalAssetMetaDataMap)) { - assert.isValidAssetMetaDataMap('props.additionalAssetMetaDataMap', config.additionalAssetMetaDataMap); + assert.isValidAssetMetaDataMap('additionalAssetMetaDataMap', config.additionalAssetMetaDataMap); } if (!_.isUndefined(config.defaultAssetBuyAmount)) { - assert.isNumber('props.defaultAssetBuyAmount', config.defaultAssetBuyAmount); + assert.isNumber('defaultAssetBuyAmount', config.defaultAssetBuyAmount); } if (!_.isUndefined(config.networkId)) { - assert.isNumber('props.networkId', config.networkId); + assert.isNumber('networkId', config.networkId); } if (!_.isUndefined(config.availableAssetDatas)) { assert.areValidAssetDatas('availableAssetDatas', config.availableAssetDatas); } if (!_.isUndefined(config.onClose)) { - assert.isFunction('props.onClose', config.onClose); + assert.isFunction('onClose', config.onClose); } if (!_.isUndefined(config.zIndex)) { - assert.isNumber('props.zIndex', config.zIndex); + assert.isNumber('zIndex', config.zIndex); } if (!_.isUndefined(config.affiliateInfo)) { - assert.isValidAffiliateInfo('props.affiliateInfo', config.affiliateInfo); + assert.isValidAffiliateInfo('affiliateInfo', config.affiliateInfo); } if (!_.isUndefined(config.provider)) { - assert.isWeb3Provider('props.provider', config.provider); + assert.isWeb3Provider('provider', config.provider); + } + if (!_.isUndefined(config.shouldDisablePushToHistory)) { + assert.isBoolean('shouldDisablePushToHistory', config.shouldDisablePushToHistory); } assert.isString('selector', selector); // Render instant and return a callback that allows you to remove it from the DOM. -- cgit v1.2.3 From 654c13df8aee2e43992c6629d2249d56667fec67 Mon Sep 17 00:00:00 2001 From: fragosti Date: Fri, 16 Nov 2018 16:07:37 -0800 Subject: fix: bug where we did not call onClose config --- packages/instant/src/index.umd.ts | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) (limited to 'packages/instant/src/index.umd.ts') diff --git a/packages/instant/src/index.umd.ts b/packages/instant/src/index.umd.ts index 9703c6fc0..518326e21 100644 --- a/packages/instant/src/index.umd.ts +++ b/packages/instant/src/index.umd.ts @@ -53,14 +53,19 @@ export const render = (config: ZeroExInstantConfig, selector: string = DEFAULT_Z injectedDiv.setAttribute('id', INJECTED_DIV_ID); injectedDiv.setAttribute('class', INJECTED_DIV_CLASS); appendTo.appendChild(injectedDiv); - const removeFromDom = () => appendTo.removeChild(injectedDiv); + const closeInstant = () => { + if (config.onClose) { + config.onClose(); + } + appendTo.removeChild(injectedDiv); + }; const instantOverlayProps = { ...config, // If we are using the history API, just go back to close - onClose: () => (config.shouldDisablePushToHistory ? removeFromDom() : window.history.back()), + onClose: () => (config.shouldDisablePushToHistory ? closeInstant() : window.history.back()), }; ReactDOM.render(React.createElement(ZeroExInstantOverlay, instantOverlayProps), injectedDiv); - return removeFromDom; + return closeInstant; }; if (config.shouldDisablePushToHistory) { renderInstant(); @@ -83,9 +88,6 @@ export const render = (config: ZeroExInstantConfig, selector: string = DEFAULT_Z } else { // User pressed back, so close instant. removeInstant(); - if (!_.isUndefined(config.onClose)) { - config.onClose(); - } } }; } -- cgit v1.2.3 From ac942faa258f604f4f6171759f6bcdf786317d29 Mon Sep 17 00:00:00 2001 From: fragosti Date: Fri, 16 Nov 2018 16:14:10 -0800 Subject: chore: use lodash where relevant --- packages/instant/src/index.umd.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'packages/instant/src/index.umd.ts') diff --git a/packages/instant/src/index.umd.ts b/packages/instant/src/index.umd.ts index 518326e21..34d893ad7 100644 --- a/packages/instant/src/index.umd.ts +++ b/packages/instant/src/index.umd.ts @@ -54,7 +54,7 @@ export const render = (config: ZeroExInstantConfig, selector: string = DEFAULT_Z injectedDiv.setAttribute('class', INJECTED_DIV_CLASS); appendTo.appendChild(injectedDiv); const closeInstant = () => { - if (config.onClose) { + if (!_.isUndefined(config.onClose)) { config.onClose(); } appendTo.removeChild(injectedDiv); -- cgit v1.2.3 From 9384c507ac29043d0d2f68bef3dde94a43282d09 Mon Sep 17 00:00:00 2001 From: fragosti Date: Fri, 16 Nov 2018 16:33:02 -0800 Subject: feat: add isInstantRendered check to safeguard against double renders and double removes --- packages/instant/src/index.umd.ts | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) (limited to 'packages/instant/src/index.umd.ts') diff --git a/packages/instant/src/index.umd.ts b/packages/instant/src/index.umd.ts index 34d893ad7..64f888e00 100644 --- a/packages/instant/src/index.umd.ts +++ b/packages/instant/src/index.umd.ts @@ -68,7 +68,9 @@ export const render = (config: ZeroExInstantConfig, selector: string = DEFAULT_Z return closeInstant; }; if (config.shouldDisablePushToHistory) { - renderInstant(); + if (!isInstantRendered()) { + renderInstant(); + } } else { // Before we render, push to history saying that instant is showing for this part of the history. window.history.pushState({ zeroExInstantShowing: true }, '0x Instant'); @@ -83,12 +85,18 @@ export const render = (config: ZeroExInstantConfig, selector: string = DEFAULT_Z prevOnPopState(e); // e.state represents the new state if (e.state && e.state.zeroExInstantShowing) { - // The user pressed fowards, so re-render instant. - removeInstant = renderInstant(); + // We have returned to a history state that expects instant to be rendered. + if (!isInstantRendered()) { + removeInstant = renderInstant(); + } } else { - // User pressed back, so close instant. - removeInstant(); + // History has changed to a different state. + if (isInstantRendered()) { + removeInstant(); + } } }; } }; + +const isInstantRendered = (): boolean => !!document.getElementById(INJECTED_DIV_ID); -- cgit v1.2.3 From e0beb7fb380e50e4566db4787092f5549a2d6db1 Mon Sep 17 00:00:00 2001 From: fragosti Date: Wed, 21 Nov 2018 11:42:07 -0500 Subject: feat: add more to instant dev env --- packages/instant/src/index.umd.ts | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) (limited to 'packages/instant/src/index.umd.ts') diff --git a/packages/instant/src/index.umd.ts b/packages/instant/src/index.umd.ts index 59f658b33..1d62084b5 100644 --- a/packages/instant/src/index.umd.ts +++ b/packages/instant/src/index.umd.ts @@ -7,6 +7,7 @@ import { ZeroExInstantOverlay, ZeroExInstantOverlayProps } from './index'; import { assert } from './util/assert'; import { util } from './util/util'; +const isInstantRendered = (): boolean => !!document.getElementById(INJECTED_DIV_ID); export interface ZeroExInstantConfig extends ZeroExInstantOverlayProps { shouldDisablePushToHistory?: boolean; } @@ -43,8 +44,8 @@ export const render = (config: ZeroExInstantConfig, selector: string = DEFAULT_Z if (!_.isUndefined(config.shouldDisablePushToHistory)) { assert.isBoolean('shouldDisablePushToHistory', config.shouldDisablePushToHistory); } - if (!_.isUndefined(props.shouldDisableAnalyticsTracking)) { - assert.isBoolean('props.shouldDisableAnalyticsTracking', props.shouldDisableAnalyticsTracking); + if (!_.isUndefined(config.shouldDisableAnalyticsTracking)) { + assert.isBoolean('shouldDisableAnalyticsTracking', config.shouldDisableAnalyticsTracking); } assert.isString('selector', selector); // Render instant and return a callback that allows you to remove it from the DOM. @@ -101,5 +102,3 @@ export const render = (config: ZeroExInstantConfig, selector: string = DEFAULT_Z }; } }; - -const isInstantRendered = (): boolean => !!document.getElementById(INJECTED_DIV_ID); -- cgit v1.2.3 From b494a4a4dba6c781667b690f38387f03a22fe141 Mon Sep 17 00:00:00 2001 From: fragosti Date: Wed, 21 Nov 2018 11:55:32 -0500 Subject: chore: clean up index.umd.ts a bit --- packages/instant/src/index.umd.ts | 70 +++++++++++++++++++++------------------ 1 file changed, 38 insertions(+), 32 deletions(-) (limited to 'packages/instant/src/index.umd.ts') diff --git a/packages/instant/src/index.umd.ts b/packages/instant/src/index.umd.ts index 1d62084b5..15ca59323 100644 --- a/packages/instant/src/index.umd.ts +++ b/packages/instant/src/index.umd.ts @@ -8,11 +8,8 @@ import { assert } from './util/assert'; import { util } from './util/util'; const isInstantRendered = (): boolean => !!document.getElementById(INJECTED_DIV_ID); -export interface ZeroExInstantConfig extends ZeroExInstantOverlayProps { - shouldDisablePushToHistory?: boolean; -} -export const render = (config: ZeroExInstantConfig, selector: string = DEFAULT_ZERO_EX_CONTAINER_SELECTOR) => { +const validateInstantRenderConfig = (config: ZeroExInstantConfig, selector: string) => { assert.isValidOrderSource('orderSource', config.orderSource); if (!_.isUndefined(config.defaultSelectedAssetData)) { assert.isHexString('defaultSelectedAssetData', config.defaultSelectedAssetData); @@ -48,37 +45,46 @@ export const render = (config: ZeroExInstantConfig, selector: string = DEFAULT_Z assert.isBoolean('shouldDisableAnalyticsTracking', config.shouldDisableAnalyticsTracking); } assert.isString('selector', selector); - // Render instant and return a callback that allows you to remove it from the DOM. - const renderInstant = () => { - const appendToIfExists = document.querySelector(selector); - assert.assert(!_.isNull(appendToIfExists), `Could not find div with selector: ${selector}`); - const appendTo = appendToIfExists as Element; - const injectedDiv = document.createElement('div'); - injectedDiv.setAttribute('id', INJECTED_DIV_ID); - injectedDiv.setAttribute('class', INJECTED_DIV_CLASS); - appendTo.appendChild(injectedDiv); - const closeInstant = () => { - if (!_.isUndefined(config.onClose)) { - config.onClose(); - } - appendTo.removeChild(injectedDiv); - }; - const instantOverlayProps = { - ...config, - // If we are using the history API, just go back to close - onClose: () => (config.shouldDisablePushToHistory ? closeInstant() : window.history.back()), - }; - ReactDOM.render(React.createElement(ZeroExInstantOverlay, instantOverlayProps), injectedDiv); - return closeInstant; +}; + +// Render instant and return a callback that allows you to remove it from the DOM. +const renderInstant = (config: ZeroExInstantConfig, selector: string) => { + const appendToIfExists = document.querySelector(selector); + assert.assert(!_.isNull(appendToIfExists), `Could not find div with selector: ${selector}`); + const appendTo = appendToIfExists as Element; + const injectedDiv = document.createElement('div'); + injectedDiv.setAttribute('id', INJECTED_DIV_ID); + injectedDiv.setAttribute('class', INJECTED_DIV_CLASS); + appendTo.appendChild(injectedDiv); + const closeInstant = () => { + if (!_.isUndefined(config.onClose)) { + config.onClose(); + } + appendTo.removeChild(injectedDiv); + }; + const instantOverlayProps = { + ...config, + // If we are using the history API, just go back to close + onClose: () => (config.shouldDisablePushToHistory ? closeInstant() : window.history.back()), }; + ReactDOM.render(React.createElement(ZeroExInstantOverlay, instantOverlayProps), injectedDiv); + return closeInstant; +}; + +export interface ZeroExInstantConfig extends ZeroExInstantOverlayProps { + shouldDisablePushToHistory?: boolean; +} + +export const render = (config: ZeroExInstantConfig, selector: string = DEFAULT_ZERO_EX_CONTAINER_SELECTOR) => { + validateInstantRenderConfig(config, selector); if (config.shouldDisablePushToHistory) { if (!isInstantRendered()) { - renderInstant(); + renderInstant(config, selector); } } else { // Before we render, push to history saying that instant is showing for this part of the history. window.history.pushState({ zeroExInstantShowing: true }, '0x Instant'); - let removeInstant = renderInstant(); + let removeInstant = renderInstant(config, selector); let prevOnPopState = util.boundNoop; if (window.onpopstate) { @@ -86,12 +92,12 @@ export const render = (config: ZeroExInstantConfig, selector: string = DEFAULT_Z } window.onpopstate = (e: PopStateEvent) => { // Don't override integrators handler. - prevOnPopState(e); - // e.state represents the new state - if (e.state && e.state.zeroExInstantShowing) { + // prevOnPopState(e); + const newState = e.state; + if (newState && newState.zeroExInstantShowing) { // We have returned to a history state that expects instant to be rendered. if (!isInstantRendered()) { - removeInstant = renderInstant(); + removeInstant = renderInstant(config, selector); } } else { // History has changed to a different state. -- cgit v1.2.3 From ed91c6c874282ab069a72784b8e563b634a236bf Mon Sep 17 00:00:00 2001 From: fragosti Date: Wed, 21 Nov 2018 12:44:28 -0500 Subject: fix: multiple render and closes edge case for onpopstate render --- packages/instant/src/index.umd.ts | 52 ++++++++++++++++++++------------------- 1 file changed, 27 insertions(+), 25 deletions(-) (limited to 'packages/instant/src/index.umd.ts') diff --git a/packages/instant/src/index.umd.ts b/packages/instant/src/index.umd.ts index 15ca59323..3a8694d6a 100644 --- a/packages/instant/src/index.umd.ts +++ b/packages/instant/src/index.umd.ts @@ -81,30 +81,32 @@ export const render = (config: ZeroExInstantConfig, selector: string = DEFAULT_Z if (!isInstantRendered()) { renderInstant(config, selector); } - } else { - // Before we render, push to history saying that instant is showing for this part of the history. - window.history.pushState({ zeroExInstantShowing: true }, '0x Instant'); - let removeInstant = renderInstant(config, selector); - - let prevOnPopState = util.boundNoop; - if (window.onpopstate) { - prevOnPopState = window.onpopstate.bind(window); - } - window.onpopstate = (e: PopStateEvent) => { - // Don't override integrators handler. - // prevOnPopState(e); - const newState = e.state; - if (newState && newState.zeroExInstantShowing) { - // We have returned to a history state that expects instant to be rendered. - if (!isInstantRendered()) { - removeInstant = renderInstant(config, selector); - } - } else { - // History has changed to a different state. - if (isInstantRendered()) { - removeInstant(); - } - } - }; + return; + } + // Before we render, push to history saying that instant is showing for this part of the history. + window.history.pushState({ zeroExInstantShowing: true }, '0x Instant'); + let removeInstant = renderInstant(config, selector); + // If the integrator defined a popstate handler, save it to __zeroExInstantIntegratorsPopStateHandler + // unless we have already done so on a previous render. + const anyWindow = window as any; + if (window.onpopstate && !anyWindow.__zeroExInstantIntegratorsPopStateHandler) { + anyWindow.__zeroExInstantIntegratorsPopStateHandler = window.onpopstate.bind(window); } + const integratorsOnPopStateHandler = anyWindow.__zeroExInstantIntegratorsPopStateHandler || util.boundNoop; + const onPopStateHandler = (e: PopStateEvent) => { + integratorsOnPopStateHandler(e); + const newState = e.state; + if (newState && newState.zeroExInstantShowing) { + // We have returned to a history state that expects instant to be rendered. + if (!isInstantRendered()) { + removeInstant = renderInstant(config, selector); + } + } else { + // History has changed to a different state. + if (isInstantRendered()) { + removeInstant(); + } + } + }; + window.onpopstate = onPopStateHandler; }; -- cgit v1.2.3