Skip to content

Commit c6ead21

Browse files
author
Matej Lednicky
committed
feat(DIST-305): Add popover popup type
For popup mode "popover" you can also set width and height of the popup. For "drawer_left" and "drawer_right" property "drawerWidth" was deprecated and replaced with "width".
1 parent c5e1832 commit c6ead21

File tree

15 files changed

+291
-139
lines changed

15 files changed

+291
-139
lines changed

.travis.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ jobs:
8484
script:
8585
- yarn build
8686
- pip install --user awscli
87-
- yarn add @typeform/[email protected] # jarvis version pinned, latest version has a bug, we should unpin it when its fixed
87+
- yarn add @typeform/[email protected]
8888
- ./scripts/consolidate-dist.sh
8989
- DEBUG=jarvis yarn run jarvis deploy --path dist --preview --notify-preview
9090
- name: "Release to NPM"
@@ -96,6 +96,6 @@ jobs:
9696
script:
9797
- yarn build
9898
- pip install --user awscli
99-
- yarn add @typeform/[email protected] # jarvis version pinned, latest version has a bug, we should unpin it when its fixed
99+
- yarn add @typeform/[email protected]
100100
- ./scripts/consolidate-dist.sh
101101
- DEBUG=jarvis jarvis deploy --path dist

README.md

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -106,15 +106,17 @@ typeformEmbed.makePopup(url, options)
106106

107107
| option | description | values | default |
108108
|----------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------|-------------------------------------------------------------------------------|---------|
109-
| mode | The way of showing the popup | `String` any of: <br/> `"popup"` <br/> `"drawer_left"` <br/> `"drawer_right"` <br/> `"side-panel"` <br/> `"popover"` | "popup" |
109+
| mode | The way of showing the popup | `String` any of: <br/> `"popup"` <br/> `"drawer_left"` <br/> `"drawer_right"` <br/> `"popover"` | "popup" |
110110
| ❌ autoOpen | Your typeform will launch as soon as your web page is opened **Deprecated:** Use `open: "load"` instead | `Boolean` | false |
111111
| 💡 open | Your typeform will launch based on behavioral triggers | `String` any of: <br/> `"exit"` <br/> `"load"` <br/> `"scroll"` <br/> `"time"`| null |
112112
| 💡 openValue | Configuration for behavioral triggers. Based on `open`: <br/> - `"exit"`: exit threshold in pixels <br/> - `"scroll"`: % of page scrolled <br/> * `"time"`: time in milliseconds | `Number` | null |
113113
| autoClose | Time until the embedded typeform will automatically close after a respondent clicks the Submit button. The default time is 5 seconds. PRO+ users can change the `autoClose` time. | `Number` (seconds) | - |
114114
| hideScrollbars | Hide fixed scrollbars. | `Boolean` | false |
115115
| hideFooter | Hide typeform footer, that appears showing the progress bar and the navigation buttons. | `Boolean` | false |
116116
| hideHeaders | Hide typeform header, that appears when you have a Question group, or a long question that you need to scroll through to answer, like a Multiple Choice block. | `Boolean` | false |
117-
| drawerWidth | Specify the width of the drawer (only applies if using `mode` `"drawer_left"` or `"drawer_right"`). | `Number` (pixels) | 800 |
117+
| ❌ drawerWidth | Specify the width of the drawer (only applies if using `mode` `"drawer_left"` or `"drawer_right"`). | `Number` (pixels) | |
118+
| width | Specify the width of the drawer or popup (only applies if using `mode` `"drawer_left"` or `"drawer_right"` or `"popover"`). | `Number` (pixels) | 800 for `"drawer_left"` ano `"drawer_right"` <br/> 320 for `"popover"` |
119+
| height | Specify the height of the popup (only applies if using `mode` `"popover"`). | `Number` (pixels) | 500 |
118120
| onSubmit | Callback function that will be executed right after the typeform is successfully submitted. | `Function` | - |
119121
| onReady | Callback function that will be executed once the typeform is ready. | `Function` | - |
120122
| onClose | Callback function that will be executed once the typeform is closed. | `Function` | - |

demo/popup-and-widget.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@
3434
<a
3535
class="typeform-share"
3636
href="//betatests.typeform.com/to/Z9k3bK"
37-
data-mode="1"
37+
data-mode="popup"
3838
target="_blank"
3939
>
4040
Launch me as a popup!

demo/popup-api-container.html

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ <h1>Lorem ipsum dolor!</h1>
7373
window.typeformEmbed.makePopup('//betatests.typeform.com/to/Z9k3bK', {
7474
mode: 'drawer_right',
7575
autoOpen: true,
76-
drawerWidth: 600,
76+
width: 600,
7777
onSubmit: () => {
7878
alert('open-popup-1 has been submitted')
7979
}
@@ -100,7 +100,7 @@ <h1>Lorem ipsum dolor!</h1>
100100
mode: 'drawer_left',
101101
autoOpen: true,
102102
container: container,
103-
drawerWidth: 400,
103+
width: 400,
104104
onSubmit: () => {
105105
alert('open-popup-3 has been submitted')
106106
}

demo/popup.html

Lines changed: 58 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,48 +6,99 @@
66
<!--CSS styles that ensure your typeform takes up all the available screen space (DO NOT EDIT!)-->
77
<style type="text/css">
88
body, html {
9+
font-family: sans-serif;
910
margin: 0;
1011
padding: 0;
1112
height: 100%;
1213
}
1314

14-
a {
15+
a.popup {
1516
margin: 20px;
1617
display: block;
1718
}
19+
20+
.popover {
21+
width: 54px;
22+
height: 54px;
23+
position: fixed;
24+
right: 16px;
25+
bottom: 16px;
26+
border-radius: 50%;
27+
display: flex;
28+
align-items: center;
29+
justify-content: center;
30+
cursor: pointer;
31+
background: #427fed;
32+
}
33+
34+
.popover > .icon {
35+
align-items: center;
36+
justify-content: center;
37+
display: flex;
38+
}
39+
40+
.popover-hint {
41+
color: darkgray;
42+
position: fixed;
43+
right: 90px;
44+
bottom: 16px;
45+
height: 54px;
46+
line-height: 54px;
47+
}
48+
1849
</style>
1950
</head>
2051
<body>
2152
<a
22-
class="typeform-share"
53+
class="typeform-share popup"
2354
href="//betatests.typeform.com/to/Z9k3bK?disable-tracking=true"
24-
data-mode="1"
55+
data-mode="popup"
2556
data-submit-close-delay="4"
2657
target="_blank"
2758
>
2859
Launch me as a popup!
2960
</a>
3061

3162
<a
32-
class="typeform-share"
63+
class="typeform-share popup"
3364
href="//betatests.typeform.com/to/Z9k3bK?disable-tracking=true"
34-
data-mode="2"
65+
data-mode="drawer_left"
3566
data-submit-close-delay="4"
3667
target="_blank"
3768
>
3869
Launch me as a drawer!
3970
</a>
4071

4172
<a
42-
class="typeform-share"
73+
class="typeform-share popup"
4374
href="//betatests.typeform.com/to/Z9k3bK?disable-tracking=true"
44-
data-mode="3"
75+
data-mode="drawer_right"
76+
data-width="400"
4577
data-submit-close-delay="4"
4678
target="_blank"
4779
>
4880
Launch me as a right drawer!
4981
</a>
5082

83+
<div class="popover-hint">To launch a popover click this button 👉</div>
84+
85+
<a
86+
class="typeform-share popover"
87+
href="//betatests.typeform.com/to/Z9k3bK?disable-tracking=true"
88+
data-mode="popover"
89+
data-width="500"
90+
data-height="600"
91+
data-submit-close-delay="4"
92+
target="_blank"
93+
>
94+
<span class="icon">
95+
<svg width="24" height="24" fill="none" style="margin-top:7px" viewBox="0 0 84 83">
96+
<rect width="84" height="56" fill="#fff" rx="8" />
97+
<path fill="#fff" d="M43 50h41v33L43 50z" opacity=".7" />
98+
</svg>
99+
</span>
100+
</a>
101+
51102
<script type="text/javascript" src="embed.js"></script>
52103
<script type="text/javascript" src="demo.js"></script>
53104
</body>

e2e/spec/functional/popup.spec.js

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,15 @@ import {
44
openPopup,
55
closePopupViaKeyboard,
66
closePopupViaButtonOnMobile,
7-
IFRAME_SELECTOR, openOnMobile
7+
IFRAME_SELECTOR,
8+
openOnMobile
89
} from '../../cypress-utils'
910

1011
const popupModes = {
11-
1: 'Popup',
12-
2: 'Drawer Left',
13-
3: 'Drawer Right'
12+
popup: 'Popup',
13+
drawer_left: 'Drawer Left',
14+
drawer_right: 'Drawer Right',
15+
popover: 'Popover'
1416
}
1517

1618
Object.keys(popupModes).forEach(popupMode => {

e2e/spec/visual/popup.spec.js

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,10 @@ import { eyesCheckDesktop, eyesCheckMobile } from '../../applitools-utils'
33

44
describe('Popup Widget', () => {
55
const popupModes = {
6-
1: 'Popup',
7-
2: 'Drawer Left',
8-
3: 'Drawer Right'
6+
popup: 'Popup',
7+
drawer_left: 'Drawer Left',
8+
drawer_right: 'Drawer Right',
9+
popover: 'Popover'
910
}
1011

1112
Object.keys(popupModes).forEach(popupMode => {

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222
"build": "./scripts/build.sh",
2323
"start": "yarn serve -S demo",
2424
"test": "yarn lint && yarn test:unit && yarn test:visual && yarn test:functional",
25-
"lint": "yarn eslint ./src --ext .js --ignore-path .eslintignore",
25+
"lint": "yarn eslint ./src --ext .js --ignore-path .eslintignore --max-warnings=0",
2626
"test:unit": "yarn jest",
2727
"test:unit:watch": "yarn jest --watch",
2828
"test:unit:coverage": "yarn jest --coverage",

src/core/attributes.js

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,14 @@ const sanitizePopupAttributes = data => {
6565
obj.openValue = data.openValue
6666
}
6767

68+
if (data.width) {
69+
obj.width = parseInt(data.width, 10)
70+
}
71+
72+
if (data.height) {
73+
obj.height = parseInt(data.height, 10)
74+
}
75+
6876
return obj
6977
}
7078

src/core/make-popup.js

Lines changed: 55 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -15,26 +15,43 @@ import {
1515
import Popup, {
1616
POPUP,
1717
POPUP_MODES,
18-
DEFAULT_AUTOCLOSE_TIMEOUT
18+
DEFAULT_AUTOCLOSE_TIMEOUT,
19+
POPOVER,
20+
DRAWER,
21+
DRAWER_RIGHT
1922
} from './views/popup'
2023
import MobileModal from './views/mobile-modal'
2124
import { getPostMessageHandler } from './utils/get-post-message-handler'
2225
import { handleAutoOpen } from './utils/popup-auto-open'
2326

2427
const DEFAULT_DRAWER_WIDTH = 800
28+
const DEFAULT_POPUP_WIDTH = 320
29+
const DEFAULT_POPUP_HEIGHT = 500
2530

26-
const defaultOptions = {
27-
mode: POPUP,
28-
isModalOpen: false,
29-
autoClose: DEFAULT_AUTOCLOSE_TIMEOUT,
30-
hideFooter: false,
31-
hideHeaders: false,
32-
hideScrollbars: false,
33-
disableTracking: false,
34-
drawerWidth: DEFAULT_DRAWER_WIDTH,
35-
onSubmit: noop,
36-
open: null,
37-
openValue: null
31+
const buildOptions = (embedId, options) => {
32+
const isDrawer = options.mode === DRAWER || options.mode === DRAWER_RIGHT
33+
const drawerWidth = options.width || options.drawerWidth || DEFAULT_DRAWER_WIDTH
34+
const popupWidth = options.width || DEFAULT_POPUP_WIDTH
35+
const width = isDrawer ? drawerWidth : popupWidth
36+
37+
return {
38+
embedId,
39+
mode: POPUP,
40+
embedType: POPUP_MODES[options.mode] || POPUP_MODES[POPUP],
41+
isModalOpen: false,
42+
autoClose: DEFAULT_AUTOCLOSE_TIMEOUT,
43+
hideFooter: false,
44+
hideHeaders: false,
45+
hideScrollbars: false,
46+
disableTracking: false,
47+
onSubmit: noop,
48+
open: null,
49+
openValue: null,
50+
width,
51+
height: DEFAULT_POPUP_HEIGHT,
52+
isAutoCloseEnabled: options.autoClose !== undefined,
53+
...options
54+
}
3855
}
3956

4057
const queryStringKeys = {
@@ -45,7 +62,7 @@ const queryStringKeys = {
4562
}
4663

4764
const renderComponent = (params, options) => {
48-
const { url, domNode, close } = params
65+
const { url, domNode, close, icon } = params
4966
const {
5067
autoClose,
5168
buttonText,
@@ -63,6 +80,7 @@ const renderComponent = (params, options) => {
6380
render(
6481
<Popup
6582
embedId={embedId}
83+
icon={icon}
6684
onClose={close}
6785
options={options}
6886
url={urlWithQueryString}
@@ -87,23 +105,22 @@ const renderComponent = (params, options) => {
87105
}
88106
}
89107

90-
export default function makePopup (url, options) {
91-
window.addEventListener('message', getPostMessageHandler('form-ready', options.onReady))
92-
window.addEventListener('message', getPostMessageHandler('form-closed', options.onClose))
108+
export default function makePopup (url, userOptions) {
109+
window.addEventListener('message', getPostMessageHandler('form-ready', userOptions.onReady))
110+
window.addEventListener('message', getPostMessageHandler('form-closed', userOptions.onClose))
93111

94112
const embedId = randomString()
95113

96-
options = {
97-
...defaultOptions,
98-
...options,
99-
isAutoCloseEnabled: options.autoClose !== undefined,
100-
embedType: POPUP_MODES[options.mode],
101-
embedId
102-
}
114+
const options = buildOptions(embedId, userOptions)
103115

104-
if (!Number.isSafeInteger(options.drawerWidth)) {
116+
if (!Number.isSafeInteger(options.width)) {
105117
throw new Error(
106-
`Whoops! You provided an invalid 'drawerWidth' option: "${options.drawerWidth}". It must be a number.`
118+
`Whoops! You provided an invalid 'width' option: "${options.width}". It must be a number.`
119+
)
120+
}
121+
if (!Number.isSafeInteger(options.height)) {
122+
throw new Error(
123+
`Whoops! You provided an invalid 'height' option: "${options.height}". It must be a number.`
107124
)
108125
}
109126

@@ -116,17 +133,26 @@ export default function makePopup (url, options) {
116133
open (event) {
117134
const { currentTarget } = event || {}
118135
const currentUrl = currentTarget && currentTarget.href ? currentTarget.href : url
136+
const icon = currentTarget && currentTarget.querySelector('span.icon')
119137
const params = {
120138
domNode,
139+
icon,
121140
url: currentUrl,
122-
close: this.close
141+
close: this.close.bind(this)
123142
}
124143

125-
renderComponent(params, options)
144+
const isOpen = domNode.children.length > 0
145+
const togglePopup = options.mode === POPOVER
146+
if (isOpen && togglePopup) {
147+
if (typeof window.tfClosePopup === 'function') {
148+
window.tfClosePopup({ ...event, detail: { embedId } })
149+
}
150+
} else {
151+
renderComponent(params, options)
152+
}
126153
},
127154
close () {
128155
window.postMessage({ type: 'form-closed', embedId }, '*')
129-
130156
unmountComponentAtNode(domNode)
131157
}
132158
}

0 commit comments

Comments
 (0)