I created a simple modal that when a user scrolls down a blog post, a modal pops up. If the user wants to sign up for newsletter, then a form pops up. The only external library I used was body-scroll-lock that helps mitigate some issues with modals/forms on iOS.
I'm curious about the need to remove event listeners and other pitfalls that I may be overlooking. Should I be using more es6 type conventions? The code is just before the </body>
tag. Here it is in action: https://develop--tanyamark-prod.netlify.com/blog/do-you-eat-when-youre-hungry-stop-when-youre-full/
// Wait at least 2s to so CTA
var wait = window.setTimeout(showCta, 2000);
function showCta() {
// Only show CTA on post pages.
if (document.querySelector('.post-single') === null) {
return;
}
var screenWidth = window.innerWidth ||
document.documentElement.clientWidth ||
document.body.clientWidth;
var bodyTag = document.getElementsByTagName('body')[0];
var blogCta = document.getElementById("blog-cta");
var openFormButton = document.getElementById("open-cta");
var closeButtonUnsubmitted = document.getElementById("close-cta");
var submittedCloseButton = document.getElementById("submitted-close");
// Wait to show cta until user scrolls down page.
bodyTag.onscroll = function () {
if ( window.pageYOffset > (document.body.clientHeight / 4) ) {
blogCta.classList.remove("hide");
}
};
var openForm = function(e) {
if (screenWidth < 901) {
blogCta.classList.add("mobile-blog-cta");
bodyScrollLock.disableBodyScroll(blogCta);
}
// Show the form.
document.getElementById("cta-ck-form").style.display = 'block';
// Remove click event from button.
openFormButton.removeEventListener('click', openForm);
// Hide openFormButton
openFormButton.style.display = 'none';
};
var removeCTA = function() {
blogCta.classList.remove("mobile-blog-cta");
if (screenWidth < 901) {
bodyScrollLock.clearAllBodyScrollLocks();
}
// Set inline so it doesn't show more than once.
blogCta.style.display = 'none';
};
// Register events
openFormButton.addEventListener('click', openForm);
closeButtonUnsubmitted.addEventListener('click', removeCTA);
submittedCloseButton.addEventListener('click', removeCTA);
}
/partials/_cta.html (The form itself is a convert kit embed)
<div id="blog-cta" class="blog-cta hide">
<div class="cta-content">
<p id="cta-message">Hi, It's Tanya. Like what you're reading? Get tips once a week on <em>nourishing your whole self.</em></p>
<div id="open-cta" class="button pink">Yes, please!</div>
<div id="cta-ck-form" class="ck_form_container ck_inline" data-ck-version="6">
<div class="ck_form ck_naked">
<div class="ck_form_fields">
<div id="ck_success_msg" style="display:none;">
<p>Success! Check your email to confirm your subscription.</p>
<button id="submitted-close">Close</button>
</div>
<!-- Form starts here -->
<form id="ck_subscribe_form" class="ck_subscribe_form" action="https://app.convertkit.com/landing_pages/309440/subscribe" data-remote="true">
<input type="hidden" value="{"form_style":"naked"}" id="ck_form_options">
<input type="hidden" name="id" value="309440" id="landing_page_id">
<input type="hidden" name="ck_form_recaptcha" value="" id="ck_form_recaptcha">
<div class="ck_errorArea">
<div id="ck_error_msg" style="display:none">
<p>There was an error submitting your subscription. Please try again.</p>
</div>
</div>
<div class="ck_control_group ck_email_field_group">
<label id="ck-test" class="ck_label" for="ck_emailField" style="display: none">Email Address</label>
<input type="text" name="first_name" class="ck_first_name" id="ck_firstNameField" placeholder="First Name" required="required">
<input type="email" name="email" class="ck_email_address" id="ck_emailField" placeholder="Email Address" required>
</div>
<div class="ck_control_group ck_captcha2_h_field_group ck-captcha2-h" style="position: absolute !important;left: -999em !important;">
<input type="text" name="captcha2_h" class="ck-captcha2-h" id="ck_captcha2_h" placeholder="We use this field to detect spam bots. If you fill this in, you will be marked as a spammer.">
</div>
<button class="subscribe_button ck_subscribe_button btn fields" id="ck_subscribe_button">
Subscribe
</button>
</form>
</div>
</div>
</div>
</div>
<div class="container-author-pic">
<div class="incoming-message"><span>1</span></div>
<img class="article-author-pic" src="/img/tanya-cup-prof.jpg" alt=""/>
<div class="mobile-header">Tanya</div>
<div id="close-cta">X</div>
</div>
</div>
/partials/_cta.css (Using postcss-cssnext plugin)
.blog-cta {
display: flex;
flex-direction: row;
position: fixed;
bottom: 80px;
right: 30px;
z-index: 820;
animation: grow .5s ease-in-out;
@media all and (max-width: 600px) {
right: 0;
margin: 15px;
}
}
@keyframes grow {
0% {
display: none;
opacity: 0;
transform: scale(0);
}
100% {
opacity: 1;
transform: scale(1);
}
}
.cta-content {
position: relative;
display: flex;
flex-direction: column;
max-width: 300px;
background-color: white;
box-shadow: 0 0 30px rgba(42, 63, 253, .4);
margin-right: 15px;
}
.cta-content::after {
position: absolute;
display: block;
content: "";
width: 0;
height: 0;
left: 100%;
top: 45px;
border-top: 8px solid transparent;
border-bottom: 8px solid transparent;
border-left: 10px solid #fff;
@media all and (max-width: 600px) {
top: 30px;
}
}
#cta-message {
color: #1c3f55;
font-size: 17px;
line-height: 22px;
padding: 12px;
margin: 0;
}
#open-cta {
cursor: pointer;
}
.mobile-header {
/* Will show on mobile */
display: none;
}
.incoming-message {
width: 20px;
height: 20px;
background-color: red;
border-radius: 24px;
color: white;
font-size: 14px;
position: absolute;
display: flex;
align-items: center;
justify-content: center;
}
#close-cta {
display: inline-flex;
justify-content: center;
align-items: center;
position: absolute;
top: -15px;
right: -15px;
font-family: var(--sans-serif-stack);
color: #a2a1a1;
font-size: 14px;
cursor: pointer;
height: 16px;
width: 16px;
padding: 5px;
border-radius: 16px;
background: #f1f1f5;
}
#close-cta:hover {
color: black;
transition: color .2s ease-in-out;
transition: font-size .2s ease-in-out;
}
/********************/
/* Convert Kit Form */
/********************/
#cta-ck-form {
display: none;
animation: grow .3s ease-in-out;
}
.ck_form, .ck_form * {
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
box-sizing: border-box;
}
.ck_errorArea {
display: none;
/* temporary */
}
.ck_form input[type="text"]:focus,
.ck_form input[type="email"]:focus {
outline: none;
border-color: #aaa;
}
.ck_converted_content {
display: none;
padding: 5%;
background: #fff;
}
.ck_form.ck_naked.width400 .ck_subscribe_button,
.ck_form.ck_naked.width400 input[type="text"],
.ck_form.ck_naked.width400 input[type="email"] {
width: 100%;
float: none;
margin-top: 5px;
}
.ck_slide_up, .ck_modal,
.ck_slide_up .ck_naked,
.ck_modal .ck_naked {
min-width: 400px;
}
.page .ck_form.ck_naked {
margin: 50px auto;
max-width: 700px;
}
.ck_slide_up.ck_form_v6, .ck_modal.ck_form_v6,
.ck_slide_up.ck_form_v6 .ck_naked, .ck_modal.ck_form_v6 .ck_naked {
min-width: 0 !important;
}
.ck_form_v6 #ck_success_msg {
padding: 0px 10px;
}
@media all and (max-width: 403px) {
.ck_form_v6.ck_modal .ck_naked {
padding-top: 30px;
}
}
@media all and (max-width: 499px) {
.ck_form_v6.ck_modal .ck_naked+.ck_close_link {
color: #fff;
top: 10px;
}
}
.ck_form_v6.ck_slide_up .ck_naked+.ck_close_link {
right: 10px;
top: -5px;
}
@media all and (min-width: 600px) {
.ck_form_v6.ck_slide_up .ck_naked+.ck_close_link {
right: 35px;
}
}
/************************/
/* ConvertKit overrides */
/************************/
.blog-cta .ck_form.ck_naked p {
font-size: 17px;
line-height: 20px;
}
.blog-cta .ck_form.ck_naked .ck_form_fields {
padding: 12px;
}
.blog-cta .ck_form.ck_naked input[type="text"],
.blog-cta .ck_form.ck_naked input[type="email"] {
padding: 10px 8px;
border: 1px solid #d6d6d6;
height: 40px;
font-size: 18px;
}
.blog-cta .ck_form.ck_naked .ck_subscribe_button,
.blog-cta #ck_success_msg button {
color: #fff;
font-size: 18px;
background: #db65cb;
cursor: pointer;
border: none;
height: 44px;
margin-top: 10px
}
.blog-cta #ck_success_msg button {
padding: 0 20px;
display: block;
margin: 0 auto;
}
/*************************/
/* Mobile + Small Screen */
/*************************/
.mobile-blog-cta.blog-cta {
bottom: initial;
flex-direction: column-reverse;
justify-content: flex-end;
align-items: center;
margin: 0;
background: #f6f6f6;
position: fixed;
top: 0;
height: 100vh;
width: 100%;
right: 0;
animation: anim .5s ease-in-out;
@media (max-height: 370px), (max-width: 320px) {
height: 100vh;
}
}
@keyframes anim {
0% {
transform: scale(0);
}
100% {
opacity: 1;
transform: scale(1);
}
}
.mobile-blog-cta .cta-content {
margin: 10px 10px;
max-width: 600px;
background-color: white;
padding: 30px;
box-shadow: 0 2px 20px 0 rgba(0,0,0,.15);
@media (max-height: 370px), (max-width: 320px) {
background-color: initial;
padding: 0;
box-shadow: initial;
}
}
.mobile-blog-cta .cta-content #cta-message {
padding-top: 0;
}
.mobile-blog-cta .cta-content::after {
display: none;
}
.mobile-blog-cta .container-author-pic {
width: 100%;
height: 30px;
background: #fff;
padding: 10px 0;
margin-bottom: 30px;
box-shadow: 0 0 20px rgba(0,0,0,.5);
display: flex;
justify-content: space-around;
align-items: center;
}
.mobile-blog-cta .article-author-pic {
margin-top: 30px;
border: #fff 5px solid;
}
.mobile-blog-cta .mobile-header{
display: inline-block;
line-height: 50px;
font-weight: 600;
}
.mobile-blog-cta .incoming-message {
display: none;
}
.mobile-blog-cta #close-cta {
position: relative;
font-size: 20px;
color: initial;
top: initial;
right: initial;
height: 22px;
width: 22px;
}
.mobile-blog-cta #ck_firstNameField, .mobile-blog-cta #ck_emailField {
width: 100%;
margin-bottom: 10px;
}
.mobile-blog-cta .ck_form.ck_naked .ck_subscribe_button,
.mobile-blog-cta #ck_success_msg button {
width: 100%;
}
bodyScrollLock
defined? \$\endgroup\$