From 5de4e5ea8b77b86e5635a39f6b6f450a8779425c Mon Sep 17 00:00:00 2001
From: Carmine DiChiara <carmine.dichiara@committed2action.com>
Date: Sat, 16 Jan 2021 10:33:31 +0000
Subject: [PATCH] Added reCAPTCHA to Formspree and support for Netlify forms
---
layouts/_default/single.html | 2
layouts/partials/sidebar.html | 2
i18n/zh-cn.toml | 27 +++
i18n/zh-tw.toml | 29 +++
i18n/dk.toml | 29 +++
assets/css/style.css | 36 +++
i18n/es.toml | 29 +++
i18n/fi.toml | 29 +++
README.md | 32 +++
i18n/de.toml | 29 +++
i18n/fa.toml | 29 +++
i18n/pt-br.toml | 27 +++
layouts/_default/list.html | 2
i18n/en.toml | 29 +++
layouts/partials/navbar.html | 2
layouts/index.html | 4
i18n/it.toml | 29 +++
i18n/fr.toml | 29 +++
layouts/partials/contact.html | 106 +++++++++++
19 files changed, 473 insertions(+), 28 deletions(-)
diff --git a/README.md b/README.md
index c3155e2..5302c0f 100644
--- a/README.md
+++ b/README.md
@@ -129,7 +129,6 @@
[params]
doNotLoadAnimations = true # Animations are loaded by default
```
-
### Control the date Format
You can change the default date formating for the `list.html`, the `single.html` and the `index.html`. Simply configure the matching parameters.
```toml
@@ -267,9 +266,38 @@
Step 1: Configure the `contactFormAction` in the `config.toml`
```toml
[params]
-#contactFormAction = "https://formspree.io/f/your-form-hash-here"
+contactFormAction = "https://formspree.io/f/your-form-hash-here"
```
Step 2: Activate the `contact: true` or `contact=true` in the frontmatter of a page. See `exampleSite/content/contact.html` as an example.
+
+Step 3: If you wish to use a Google reCAPTCHA v2, you must [go to a Google Admin console](https://www.google.com/recaptcha/about/) and create a reCAPTCHA:
+Make sure it is a reCAPTCHA v2. You must then [go to your Formspree account](https://help.formspree.io/hc/en-us/articles/360022811154-Adding-a-custom-reCAPTCHA-key) and enter the secret key that you were given in the appropriate location.
+Step 4: Enter the reCAPTCHA site key in `config.toml`:
+```toml
+[params]
+contactFormReCaptchaSiteKey = "your-site-key"
+```
+### Netlify Contact Form on the Contact Page
+Netlify forms only work when your site is being actively hosted by Netlify - unlike Formspree, testing your form locally before committing to Netlify will not work.
+Step 1: Configure the `contactFormType` in the `config.toml`. Netlify does not require a `contactFormAction` configured.
+```toml
+[params]
+contactFormType = "netlify"
+```
+Step 2: Set `contact: true` or `contact=true` in the frontmatter of a page. See `exampleSite/content/contact.html` as an example.
+
+Step 3: If you wish to use a Google reCAPTCHA v2, you must [go to a Google Admin console](https://www.google.com/recaptcha/about/) and create a reCAPTCHA.
+Make sure it is a reCAPTCHA v2. You must then [go to your Formspree account](https://help.formspree.io/hc/en-us/articles/360022811154-Adding-a-custom-reCAPTCHA-key) and enter the secret key that you were given in the appropriate location.
+
+Step 4: Enter the reCAPTCHA site key in `config.toml`:
+```toml
+[params]
+contactFormReCaptchaSiteKey = "your-site-key"
+```
+Step 5: [Go to your Netlify account](https://www.netlify.com/blog/2018/05/23/bring-your-own-recaptcha-to-netlify-forms/) and let them know both the site key and the secret key for your custom reCAPTCHA.
+
+Step 6: You will probably want to set up some [form notification](https://docs.netlify.com/forms/notifications/).
+
### Twitter Cards support
In order to use the full functionality of Twitter cards, you will have to define a couple of settings in the `config.toml` and the frontmatter of a page.
diff --git a/assets/css/style.css b/assets/css/style.css
index 70dbb98..b3cdb4a 100644
--- a/assets/css/style.css
+++ b/assets/css/style.css
@@ -14,8 +14,10 @@
--tag-color: #424242;
--blockquote-text-color: #858585;
--blockquote-border-color: #dfe2e5;
+ --error-color: #ff3939;
--thumbnail-height: 15em;
scroll-padding-top: 100px;
+ --font-family: 'Verdana', sans-serif;
}
html[data-theme='dark'] {
@@ -32,6 +34,7 @@
--tag-color: rgb(191, 191, 191);
--blockquote-text-color: #808080;
--blockquote-border-color: #424242;
+ --error-color: #ff3939;
}
html {
@@ -41,7 +44,7 @@
body {
color: var(--body-color);
- font-family: 'Verdana', sans-serif;
+ font-family: var(--font-family);
font-size: 15px;
width: 100%;
margin: 0 auto 30px auto;
@@ -130,40 +133,48 @@
@-webkit-keyframes fadeInDown {
0% {
+ opacity: 0;
-webkit-transform: translateY(-20px);
}
100% {
+ opacity: 1;
-webkit-transform: translateY(0);
}
}
@-moz-keyframes fadeInDown {
0% {
+ opacity: 0;
-moz-transform: translateY(-20px);
}
100% {
+ opacity: 1;
-moz-transform: translateY(0);
}
}
@-o-keyframes fadeInDown {
0% {
+ opacity: 0;
-o-transform: translateY(-20px);
}
100% {
+ opacity: 1;
-o-transform: translateY(0);
}
}
@keyframes fadeInDown {
0% {
+ opacity: 0;
transform: translateY(-20px);
}
100% {
+ opacity: 1;
transform: translateY(0);
}
}
@@ -1052,7 +1063,7 @@
border: 1px solid var(--form-border-color);
color: var(--body-color);
}
-.form-style ul li .field-style:focus {
+.form-style ul li .field-style:focus {
box-shadow: 0 0 5px;
border:1px solid;
}
@@ -1068,6 +1079,10 @@
.form-style ul li input.align-right {
float:right;
}
+.form-style input,
+.form-style textarea {
+ font-family: var(--font-family);
+}
.form-style ul li textarea {
background-color: var(--bg-color);
border: 1px solid var(--form-border-color);
@@ -1075,7 +1090,6 @@
width: 100%;
height: auto;
}
-.form-style ul li input[type="button"],
.form-style ul li input[type="submit"] {
background-color: var(--bg-color);
border: 1px solid var(--form-border-color);
@@ -1085,10 +1099,20 @@
text-decoration: none;
width: 100%;
}
-.form-style ul li input[type="button"]:hover,
.form-style ul li input[type="submit"]:hover {
background-color: var(--bg-color);
border: 1px solid var(--form-button-hover-border-color);
}
-
-/* (CONTACT) FORM END */
\ No newline at end of file
+.form-style .form-row {
+ display: flex;
+ flex-direction: row;
+ align-items: center;
+ flex: 1;
+}
+.form-feedback {
+ text-align: center;
+}
+.form-feedback[feedback-success="false"] {
+ color: var(--error-color);
+}
+/* (CONTACT) FORM END */
diff --git a/i18n/de.toml b/i18n/de.toml
index 0ed8625..668e4b8 100644
--- a/i18n/de.toml
+++ b/i18n/de.toml
@@ -20,5 +20,32 @@
[comments]
other = "Kommentare"
+[name]
+other = "Name"
+
+[name_error]
+other = "Bitte geben Sie Ihren Namen an"
+
+[email]
+other = "Email"
+
+[email_error]
+other = "Bitte geben Sie eine gültige E-Mail Adresse ein"
+
+[message]
+other = "Nachricht"
+
+[message_error]
+other = "Bitte teilen Sie uns mit, warum Sie sich an uns wenden"
+
[send]
-other = "Senden"
\ No newline at end of file
+other = "Senden"
+
+[form_captcha_error]
+other = "Captcha-Fehler; bitte versuchen Sie es später noch einmal"
+
+[form_error]
+other = "Fataler Fehler, Kontakt nicht hergestellt - bitte melden Sie sich auf anderem Wege"
+
+[form_success]
+other = "Thank für Ihre Kontaktaufnahme. Wir werden uns bald bei Ihnen melden."
diff --git a/i18n/dk.toml b/i18n/dk.toml
index 1ed7e77..18465f1 100644
--- a/i18n/dk.toml
+++ b/i18n/dk.toml
@@ -20,5 +20,32 @@
[comments]
other = "kommentar"
+[name]
+other = "Name"
+
+[name_error]
+other = "Please provide your name"
+
+[email]
+other = "Email"
+
+[email_error]
+other = "Please enter a valid email address"
+
+[message]
+other = "Message"
+
+[message_error]
+other = "Please let us know why you are contacting us"
+
[send]
-other = "Sende"
\ No newline at end of file
+other = "Sende"
+
+[form_captcha_error]
+other = "Captcha error; please try again later"
+
+[form_error]
+other = "Fatal error, contact not made - please reach out some other way"
+
+[form_success]
+other = "Thank you for reaching out! We will be touch soon"
diff --git a/i18n/en.toml b/i18n/en.toml
index db43452..e59793d 100644
--- a/i18n/en.toml
+++ b/i18n/en.toml
@@ -20,5 +20,32 @@
[comments]
other = "comments"
+[name]
+other = "Name"
+
+[name_error]
+other = "Please provide your name"
+
+[email]
+other = "Email"
+
+[email_error]
+other = "Please enter a valid email address"
+
+[message]
+other = "Message"
+
+[message_error]
+other = "Please let us know why you are contacting us"
+
[send]
-other = "Send"
\ No newline at end of file
+other = "Send"
+
+[form_captcha_error]
+other = "Captcha error; please try again later"
+
+[form_error]
+other = "Fatal error, contact not made - please reach out in some other way"
+
+[form_success]
+other = "Thank you for reaching out! We will be touch soon"
diff --git a/i18n/es.toml b/i18n/es.toml
index a95542a..07db312 100644
--- a/i18n/es.toml
+++ b/i18n/es.toml
@@ -20,5 +20,32 @@
[comments]
other = "comentarios"
+[name]
+other = "Nombre"
+
+[name_error]
+other = "Por favor, indique su nombre"
+
+[email]
+other = "Email"
+
+[email_error]
+other = "Por favor, introduzca una dirección de correo electrónico válida"
+
+[message]
+other = "Mensaje"
+
+[message_error]
+other = "Por favor, háganos saber por qué está contactando con nosotros"
+
[send]
-other = "Enviar"
\ No newline at end of file
+other = "Enviar"
+
+[form_captcha_error]
+other = "Error de Captcha; por favor, inténtelo de nuevo más tarde"
+
+[form_error]
+other = "Error fatal, contacto no realizado - por favor, contacte de otra manera"
+
+[form_success]
+other = "¡Gracias por tender la mano! Pronto nos tocará"
diff --git a/i18n/fa.toml b/i18n/fa.toml
index 2911b2c..e65a259 100644
--- a/i18n/fa.toml
+++ b/i18n/fa.toml
@@ -20,5 +20,32 @@
[comments]
other = "نظرات"
+[name]
+other = "Name"
+
+[name_error]
+other = "Please provide your name"
+
+[email]
+other = "Email"
+
+[email_error]
+other = "Please enter a valid email address"
+
+[message]
+other = "Message"
+
+[message_error]
+other = "Please let us know why you are contacting us"
+
[send]
-other = "ارسال"
\ No newline at end of file
+other = "ارسال"
+
+[form_captcha_error]
+other = "Captcha error; please try again later"
+
+[form_error]
+other = "Fatal error, contact not made - please reach out some other way"
+
+[form_success]
+other = "Thank you for reaching out! We will be touch soon"
diff --git a/i18n/fi.toml b/i18n/fi.toml
index 622de2c..036fb7a 100644
--- a/i18n/fi.toml
+++ b/i18n/fi.toml
@@ -20,5 +20,32 @@
[comments]
other = "kommentit"
+[name]
+other = "Name"
+
+[name_error]
+other = "Please provide your name"
+
+[email]
+other = "Email"
+
+[email_error]
+other = "Please enter a valid email address"
+
+[message]
+other = "Message"
+
+[message_error]
+other = "Please let us know why you are contacting us"
+
[send]
-other = "Lähetä"
\ No newline at end of file
+other = "Lähetä"
+
+[form_captcha_error]
+other = "Captcha error; please try again later"
+
+[form_error]
+other = "Fatal error, contact not made - please reach out some other way"
+
+[form_success]
+other = "Thank you for reaching out! We will be touch soon"
diff --git a/i18n/fr.toml b/i18n/fr.toml
index b97fd5a..16d481d 100644
--- a/i18n/fr.toml
+++ b/i18n/fr.toml
@@ -20,5 +20,32 @@
[comments]
other = "commentaire"
+[name]
+other = "Nom"
+
+[name_error]
+other = "Veuillez indiquer votre nom"
+
+[email]
+other = "Email"
+
+[email_error]
+other = "Veuillez saisir une adresse électronique valide"
+
+[message]
+other = "Message"
+
+[message_error]
+other = "Veuillez nous indiquer la raison pour laquelle vous nous contactez"
+
[send]
-other = "Envoyer"
\ No newline at end of file
+other = "Envoyer"
+
+[form_captcha_error]
+other = "Erreur Captcha ; veuillez réessayer plus tard"
+
+[form_error]
+other = "Erreur fatale, contact non établi - veuillez prendre contact d'une autre manière"
+
+[form_success]
+other = "Merci de nous avoir contactés ! Nous vous contacterons bientôt"
diff --git a/i18n/it.toml b/i18n/it.toml
index 9f6020c..bc4eea1 100644
--- a/i18n/it.toml
+++ b/i18n/it.toml
@@ -20,5 +20,32 @@
[comments]
other = "commenti"
+[name]
+other = "Nome"
+
+[name_error]
+other = "Si prega di fornire il proprio nome"
+
+[email]
+other = "e-mail"
+
+[email_error]
+other = "Inserire un indirizzo e-mail valido"
+
+[message]
+other = "Messaggio"
+
+[message_error]
+other = "Per favore, fateci sapere perché ci contattate"
+
[send]
-other = "Spedire"
\ No newline at end of file
+other = "Spedire"
+
+[form_captcha_error]
+other = "Errore Captcha; si prega di riprovare più tardi"
+
+[form_error]
+other = "Errore fatale, contatto non effettuato - si prega di contattare in altro modo"
+
+[form_success]
+other = "Grazie per averci raggiunto! Ci sentiremo presto"
diff --git a/i18n/pt-br.toml b/i18n/pt-br.toml
index 2456fa9..477c939 100644
--- a/i18n/pt-br.toml
+++ b/i18n/pt-br.toml
@@ -20,5 +20,32 @@
[comments]
other = "comentários"
+[name]
+other = "Nome"
+
+[name_error]
+other = "Por favor, forneça seu nome"
+
+[email]
+other = "Email"
+
+[email_error]
+other = "Por favor, digite um endereço de e-mail válido"
+
+[message]
+other = "Mensagem"
+
+[message_error]
+other = "Por favor nos informe por que você está entrando em contato conosco"
+
[send]
other = "Enviar"
+
+[form_captcha_error]
+other = "Captcha error; por favor, tente novamente mais tarde"
+
+[form_error]
+other = "Erro fatal, contato não feito - por favor, procure de outra forma"
+
+[form_success]
+other = "Obrigado por estender a mão! Em breve estaremos em contato"
diff --git a/i18n/zh-cn.toml b/i18n/zh-cn.toml
index 62c1293..d67558e 100755
--- a/i18n/zh-cn.toml
+++ b/i18n/zh-cn.toml
@@ -20,5 +20,32 @@
[comments]
other = "评论"
+[name]
+other = "名称"
+
+[name_error]
+other = "请提供您的姓名"
+
+[email]
+other = "电子邮件"
+
+[email_error]
+other = "请输入有效的电子邮件地址"
+
+[message]
+other = "留言内容"
+
+[message_error]
+other = "请告诉我们您联系我们的原因。"
+
[send]
other = "发送"
+
+[form_captcha_error]
+other = "验证码错误,请稍后再试"
+
+[form_error]
+other = "致命的错误,没有取得联系--请以其他方式联系。"
+
+[form_success]
+other = "谢谢您的联系!我们会尽快与您联系。我们会尽快联系您"
diff --git a/i18n/zh-tw.toml b/i18n/zh-tw.toml
index 87e7e69..c63526f 100644
--- a/i18n/zh-tw.toml
+++ b/i18n/zh-tw.toml
@@ -20,5 +20,32 @@
[comments]
other = "註解"
+[name]
+other = "Name"
+
+[name_error]
+other = "Please provide your name"
+
+[email]
+other = "Email"
+
+[email_error]
+other = "Please enter a valid email address"
+
+[message]
+other = "Message"
+
+[message_error]
+other = "Please let us know why you are contacting us"
+
[send]
-other = "發送"
\ No newline at end of file
+other = "發送"
+
+[form_captcha_error]
+other = "Captcha error; please try again later"
+
+[form_error]
+other = "Fatal error, contact not made - please reach out some other way"
+
+[form_success]
+other = "Thank you for reaching out! We will be touch soon"
diff --git a/layouts/_default/list.html b/layouts/_default/list.html
index cad95c8..b502037 100644
--- a/layouts/_default/list.html
+++ b/layouts/_default/list.html
@@ -1,5 +1,5 @@
{{ define "main" }}
- <div class="archive {{ with .Site.Params.doNotLoadAnimations }} . {{ else }} animated fadeInDown {{ end }}">
+ <div class="archive {{ if and (or (not (isset .Site.Params "doNotLoadAnimations")) (and (isset .Site.Params "doNotLoadAnimations") (not .Site.Params.doNotLoadAnimations))) (or (not (isset .Page.Params "animation")) .Page.Params.animation) }} animated fadeInDown {{ end }}">
<ul class="list-with-title">
{{ range .Data.Pages.GroupByDate "2006" }}
<div class="listing-title">{{ .Key }}</div>
diff --git a/layouts/_default/single.html b/layouts/_default/single.html
index b4ff807..f7e360b 100644
--- a/layouts/_default/single.html
+++ b/layouts/_default/single.html
@@ -1,5 +1,5 @@
{{ define "main" }}
- <div class="post {{ with .Site.Params.doNotLoadAnimations }} . {{ else }} animated fadeInDown {{ end }}">
+ <div class="post {{ if and (or (not (isset .Site.Params "doNotLoadAnimations")) (and (isset .Site.Params "doNotLoadAnimations") (not .Site.Params.doNotLoadAnimations))) (or (not (isset .Page.Params "animation")) .Page.Params.animation) }} animated fadeInDown {{ end }}">
<div class="post-content">
{{ if .Params.thumbnail }}
<img class="post-thumbnail" src="{{ .Params.thumbnail | absURL }}" alt="Thumbnail image">
diff --git a/layouts/index.html b/layouts/index.html
index c957852..f0d2ae9 100644
--- a/layouts/index.html
+++ b/layouts/index.html
@@ -1,6 +1,6 @@
{{ define "main" }}
- <div class="post {{ with .Site.Params.doNotLoadAnimations }} . {{ else }} animated fadeInDown {{ end }}">
+ <div class="post {{ if and (or (not (isset .Site.Params "doNotLoadAnimations")) (and (isset .Site.Params "doNotLoadAnimations") (not .Site.Params.doNotLoadAnimations))) (or (not (isset .Page.Params "animation")) .Page.Params.animation) }} animated fadeInDown {{ end }}">
<!-- (Optional) Home
-- on top of `mainSections` content (aka posts) ;
-- as declared in content/_index.md
@@ -13,7 +13,7 @@
{{ $paginator := .Paginate (where .Site.RegularPages "Type" "in" .Site.Params.mainSections) }}
{{ range $paginator.Pages }}
- <div class="post {{ with .Site.Params.doNotLoadAnimations }} . {{ else }} animated fadeInDown {{ end }}">
+ <div class="post {{ if and (or (not (isset .Site.Params "doNotLoadAnimations")) (and (isset .Site.Params "doNotLoadAnimations") (not .Site.Params.doNotLoadAnimations))) (or (not (isset .Page.Params "animation")) .Page.Params.animation) }} animated fadeInDown {{ end }}">
{{ if .Params.thumbnail }}
<div class="post-thumbnail">
<a href="{{ .RelPermalink }}">
diff --git a/layouts/partials/contact.html b/layouts/partials/contact.html
index e598114..53c33b1 100644
--- a/layouts/partials/contact.html
+++ b/layouts/partials/contact.html
@@ -1,19 +1,115 @@
+{{ $jquery := resources.Get "js/jquery.js" }}
+<script type="text/javascript" src="{{ $jquery.Permalink }}"></script>
<div class="contact-form">
- <form class="form-style" method="POST" action="{{ .Site.Params.contactFormAction }}" data-toggle="validator">
+ <form id="contact-form" name="Contact Form" class="form-style" method="POST" action="{{ if eq .Site.Params.contactFormType "netlify" }}/{{ else }}{{ .Site.Params.contactFormAction }}{{ end }}"
+ {{ with .Site.Params.contactFormReCaptchaSiteKey }} data-netlify-recaptcha="true"{{ end }}
+ {{ if eq .Site.Params.contactFormType "netlify" }} data-netlify="true" netlify-honeypot="my-lovely-house"{{ end }}>
<ul>
<li>
- <input class="field-style field-full" type="text" name="username" id="username" placeholder="Name" required>
+ <input class="field-style field-full" type="text" name="username" id="username" placeholder="{{ i18n "name" }}" oninvalid="setCustomValidity('{{ i18n "name_error" }}')" oninput="setCustomValidity('')" required>
</li>
<li>
- <input class="field-style field-full" type="email" id="email" name="email" placeholder="Email" required>
+ <input class="field-style field-full" type="email" name="email" id="email" placeholder="{{ i18n "email" }}" pattern="^[a-zA-Z0-9.!#$%&’*+/=?^_`{|}~-]+@[a-zA-Z0-9-]+(?:\.[a-zA-Z0-9-]+)*$" oninvalid="setCustomValidity('{{ i18n "email_error" }}')" oninput="setCustomValidity('')" required>
</li>
<li>
- <textarea class="field-style" name="message" id="message" rows="6" placeholder="{{ i18n "message" }}"></textarea>
+ <textarea class="field-style" name="message" id="message" rows="6" placeholder="{{ i18n "message" }}" oninvalid="setCustomValidity('{{ i18n "message_error" }}')" oninput="setCustomValidity('')" required></textarea>
</li>
<li>
- <input class="field-style" type="submit" value="{{ i18n "send" }}"></input>
+ <input class="field-style" id="form-submit" type="submit" value="{{ i18n "send" }}">
</li>
+ <li>
+ <div class="form-feedback" id="submit-feedback"></div>
+ </li>
+ {{ if eq .Site.Params.contactFormType "netlify"}}
+ <input name="form-name" value="Contact Form" type="hidden">
+ <input class="field-style" name="my-lovely-house" id="my-lovely-house" type="hidden">
+ {{ end }}
+ {{ with .Site.Params.contactFormReCaptchaSiteKey }}
+ <li>
+ <div id="g-recaptcha"></div>
+ </li>
+ {{ end }}
</ul>
</form>
</div>
+
+<script>
+ // Sets feedback message.
+ function setFeedback(message = '', ok = true) {
+ const feedback = $('#submit-feedback');
+
+ feedback.attr('feedback-success', ok);
+ feedback.text(message);
+ }
+
+ // This hanlder takes care of submission post-captcha.
+ function onSubmit() {
+ // Verify if we have a recaptcha at all before checking.
+ if($('.g-recaptcha')[0] != null &&
+ grecaptcha.getResponse().length == 0) {
+ setFeedback('{{ i18n "form_captcha_error" }}', false);
+ } else {
+ // Formspree requires json; ajax will do the conversion.
+ const form = $('#contact-form');
+ const message = form.serialize();
+ const dataType = ('{{ .Site.Params.ContactFormType }}' === 'netlify')
+ ? 'application/x-www-form-urlencoded' : 'json';
+
+ $.ajax({
+ url: form.prop('action'),
+ method: 'POST',
+ data: message,
+ dataType,
+ complete: (xhr, status) => {
+ // Netlify asks for urlencoded data but sends back HTML. This causes a
+ // data type mismatch that Ajax flags as an error ... I believe the solution is to just
+ // screen for the false negative in this combined handler.
+ // https://stackoverflow.com/questions/16230624/ajax-call-fires-error-event-but-returns-200-ok/16230794
+ if (status === 'error' && xhr.status !== 200) {
+ setFeedback('{{ i18n "form_error" }}', false);
+ } else {
+ setFeedback('{{ i18n "form_success" }}');
+ }
+ },
+ });
+
+ // Enable button.
+ $('#form-submit').prop('disabled', false);
+ }
+ }
+
+ // Initial contact form submit is disabled, and optionally kicks off captcha.
+ $('#contact-form').submit((e) => {
+ // We're doing the submission to avoid the redirect for free Formspree accounts.
+ e.preventDefault();
+ setFeedback('');
+ // Disable submit button for the time being,
+ $('#form-submit').prop('disabled', true);
+
+ // Make sure we have a captcha to execute before trying to do so.
+ if ($('.g-recaptcha')[0] !== null) {
+ grecaptcha.execute();
+ } else {
+ onSubmit();
+ }
+ });
+</script>
+
+{{ with .Site.Params.contactFormReCaptchaSiteKey }}
+ <script>
+ // Captcha rendered dynamically to deal with some rendering issues with
+ // theme and with animation.
+ function captchaLoadCallback() {
+ grecaptcha.render( 'g-recaptcha', {
+ sitekey: '{{ . }}',
+ callback: onSubmit,
+ size: 'invisible',
+ badge: 'bottomright',
+ theme: $('html').attr('data-theme'),
+ });
+ }
+ </script>
+ <!-- Explicit rendering of recaptcha to deal with data-theme and animation issues -->
+ <script type="text/javascript" src="https://www.google.com/recaptcha/api.js?onload=captchaLoadCallback&render=explicit" async defer></script>
+{{ end }}
diff --git a/layouts/partials/navbar.html b/layouts/partials/navbar.html
index 9c4c28e..5d2cfed 100644
--- a/layouts/partials/navbar.html
+++ b/layouts/partials/navbar.html
@@ -1,4 +1,4 @@
-<div class="page-top {{ with .Site.Params.doNotLoadAnimations }} . {{ else }} animated fadeInDown {{ end }}">
+<div class="page-top {{ if and (or (not (isset .Site.Params "doNotLoadAnimations")) (and (isset .Site.Params "doNotLoadAnimations") (not .Site.Params.doNotLoadAnimations))) (or (not (isset .Page.Params "animation")) .Page.Params.animation) }} animated fadeInDown {{ end }}">
<a role="button" class="navbar-burger" data-target="navMenu" aria-label="menu" aria-expanded="false">
<span aria-hidden="true"></span>
<span aria-hidden="true"></span>
diff --git a/layouts/partials/sidebar.html b/layouts/partials/sidebar.html
index 22afa5d..39c5133 100644
--- a/layouts/partials/sidebar.html
+++ b/layouts/partials/sidebar.html
@@ -1,4 +1,4 @@
-<div class="sidebar{{ with .Site.Params.doNotLoadAnimations }} . {{ else }} animated fadeInDown {{ end }}">
+<div class="sidebar{{ if and (or (not (isset .Site.Params "doNotLoadAnimations")) (and (isset .Site.Params "doNotLoadAnimations") (not .Site.Params.doNotLoadAnimations))) (or (not (isset .Page.Params "animation")) .Page.Params.animation) }} animated fadeInDown {{ end }}">
<div class="logo-title">
<div class="title">
<img src="{{ .Site.Params.profilePicture | absURL }}" alt="profile picture">
--
Gitblit v1.10.0