Skip to content

Commit fc35f4c

Browse files
minor js improvements
1 parent 871eb65 commit fc35f4c

File tree

1 file changed

+56
-74
lines changed

1 file changed

+56
-74
lines changed

assets/src/js/script.js

Lines changed: 56 additions & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -3,29 +3,16 @@ const animator = require('./animator.js')
33
const Loader = require('./loader.js')
44
const COOKIE_NAME = 'mctb_bar_hidden'
55

6-
function throttle (fn, threshold, scope) {
7-
threshold || (threshold = 600)
8-
let last
9-
let deferTimer
10-
return function () {
11-
const context = scope || this
12-
const now = +new Date()
13-
const args = arguments
14-
if (last && now < last + threshold) {
15-
// hold on to it
16-
clearTimeout(deferTimer)
17-
deferTimer = setTimeout(function () {
18-
last = now
19-
fn.apply(context, args)
20-
}, threshold)
21-
} else {
22-
last = now
23-
fn.apply(context, args)
24-
}
25-
}
6+
// holder for debounce timeout
7+
let timeout
8+
function debounce (fn, delay) {
9+
clearTimeout(timeout)
10+
timeout = setTimeout(fn, delay)
2611
}
2712

28-
function Bar (wrapperEl, config) {
13+
function Bar () {
14+
const wrapperEl = document.getElementById('mailchimp-top-bar')
15+
const config = window.mctb
2916
const barEl = wrapperEl.querySelector('.mctb-bar')
3017
const iconEl = document.createElement('span')
3118
const formEl = barEl.querySelector('form')
@@ -36,66 +23,60 @@ function Bar (wrapperEl, config) {
3623
const isBottomBar = (config.position === 'bottom')
3724
const state = config.state
3825

39-
// Functions
40-
function init () {
41-
// remove "no_js" field
42-
const noJsField = barEl.querySelector('input[name="_mctb_no_js"]')
43-
noJsField.parentElement.removeChild(noJsField)
26+
// remove "no_js" field (which is used to detect bots and prevent spam)
27+
const noJsField = barEl.querySelector('input[name="_mctb_no_js"]')
28+
noJsField.parentElement.removeChild(noJsField)
4429

45-
formEl.addEventListener('submit', submitForm)
46-
47-
// save original bodyPadding
48-
if (isBottomBar) {
49-
wrapperEl.insertBefore(iconEl, barEl)
50-
originalBodyPadding = (parseInt(document.body.style.paddingBottom) || 0)
51-
} else {
52-
wrapperEl.insertBefore(iconEl, barEl.nextElementSibling)
53-
originalBodyPadding = (parseInt(document.body.style.paddingTop) || 0)
54-
}
30+
formEl.addEventListener('submit', submitForm)
5531

56-
// configure icon
57-
iconEl.className = 'mctb-close'
58-
iconEl.innerHTML = config.icons.show
59-
iconEl.addEventListener('click', toggle)
32+
// save original bodyPadding
33+
if (isBottomBar) {
34+
wrapperEl.insertBefore(iconEl, barEl)
35+
originalBodyPadding = (parseInt(document.body.style.paddingBottom) || 0)
36+
} else {
37+
wrapperEl.insertBefore(iconEl, barEl.nextElementSibling)
38+
originalBodyPadding = (parseInt(document.body.style.paddingTop) || 0)
39+
}
6040

61-
// count input fields (3 because of hidden input honeypot)
62-
if (barEl.querySelectorAll('input:not([type="hidden"])').length > 3) {
63-
wrapperEl.className += ' multiple-input-fields'
64-
}
41+
// configure icon
42+
iconEl.className = 'mctb-close'
43+
iconEl.innerHTML = config.icons.show
44+
iconEl.addEventListener('click', toggle)
6545

66-
// calculate initial dimensions
67-
calculateDimensions()
68-
69-
// on dom repaint, bar height changes. re-calculate in next repaint.
70-
window.requestAnimationFrame(calculateDimensions)
46+
// count input fields (3 because of hidden input honeypot)
47+
if (barEl.querySelectorAll('input:not([type="hidden"])').length > 3) {
48+
wrapperEl.className += ' multiple-input-fields'
49+
}
7150

72-
// Show the bar straight away?
73-
if (cookies.exists(COOKIE_NAME)) {
74-
show()
75-
}
51+
// on dom repaint, bar height changes. re-calculate in next repaint.
52+
window.requestAnimationFrame(calculateDimensions)
7653

77-
// fade response 4 seconds after showing bar
78-
if (responseEl) {
79-
window.setTimeout(fadeResponse, 4000)
80-
}
54+
// Show the bar straight away?
55+
if (!cookies.exists(COOKIE_NAME)) {
56+
show()
57+
}
8158

82-
window.addEventListener('resize', throttle(calculateDimensions))
59+
// fade response 4 seconds after showing bar
60+
if (responseEl) {
61+
window.setTimeout(fadeResponse, 4000)
8362
}
8463

64+
window.addEventListener('resize', debounce(calculateDimensions, 100))
65+
8566
function submitForm (evt) {
8667
const loader = new Loader(formEl)
8768
const data = new FormData(formEl)
8869
let request = new XMLHttpRequest()
8970
request.onreadystatechange = function () {
90-
let response
91-
92-
// are we done?
9371
if (this.readyState !== 4) {
9472
return
9573
}
9674

75+
// remove loading indicator
9776
loader.stop()
9877

78+
// parse json response
79+
let response
9980
if (this.status >= 200 && this.status < 400) {
10081
try {
10182
response = JSON.parse(this.responseText)
@@ -107,6 +88,7 @@ function Bar (wrapperEl, config) {
10788
state.success = !!response.success
10889
state.submitted = true
10990

91+
// maybe redirect to url from settings
11092
if (response.success && response.redirect_url) {
11193
window.location.href = response.redirect_url
11294
return
@@ -150,28 +132,32 @@ function Bar (wrapperEl, config) {
150132
window.setTimeout(fadeResponse, 4000)
151133
}
152134

135+
function iconFitsInsideBar () {
136+
// would the close icon fit inside the bar?
137+
let elementsWidth = 0
138+
for (let i = 0; i < barEl.firstElementChild.children.length; i++) {
139+
elementsWidth += barEl.firstElementChild.children[i].clientWidth
140+
}
141+
142+
return (elementsWidth + iconEl.clientWidth + 200) < barEl.clientWidth
143+
}
144+
153145
function calculateDimensions () {
154146
// make sure bar is visible
155147
const origBarDisplay = barEl.style.display
156148
if (origBarDisplay !== 'block') {
157149
barEl.style.visibility = 'hidden'
150+
barEl.style.display = 'block'
158151
}
159-
barEl.style.display = 'block'
160152

161153
// calculate & set new body padding if bar is currently visible
162154
bodyPadding = (originalBodyPadding + barEl.clientHeight) + 'px'
163155
if (visible) {
164156
document.body.style[isBottomBar ? 'paddingBottom' : 'paddingTop'] = bodyPadding
165157
}
166158

167-
// would the close icon fit inside the bar?
168-
let elementsWidth = 0
169-
for (let i = 0; i < barEl.firstElementChild.children.length; i++) {
170-
elementsWidth += barEl.firstElementChild.children[i].clientWidth
171-
}
172-
173159
wrapperEl.className = wrapperEl.className.replace('mctb-icon-inside-bar', '')
174-
if (elementsWidth + iconEl.clientWidth + 200 < barEl.clientWidth) {
160+
if (iconFitsInsideBar()) {
175161
wrapperEl.className += ' mctb-icon-inside-bar'
176162

177163
// since icon is now absolutely positioned, we need to set a min height
@@ -283,9 +269,6 @@ function Bar (wrapperEl, config) {
283269
return visible ? hide(true) : show(true)
284270
}
285271

286-
// Code to run upon object instantiation
287-
init()
288-
289272
// Return values
290273
return {
291274
element: wrapperEl,
@@ -296,6 +279,5 @@ function Bar (wrapperEl, config) {
296279
}
297280

298281
document.addEventListener('DOMContentLoaded', () => {
299-
const element = document.getElementById('mailchimp-top-bar')
300-
window.MailChimpTopBar = new Bar(element, window.mctb)
282+
window.MailChimpTopBar = new Bar()
301283
})

0 commit comments

Comments
 (0)