Add feedback form sending

This commit is contained in:
Ilja Kartašov 2019-04-26 14:58:07 +02:00
parent 372ef5d3b8
commit 42364c1337
2 changed files with 353 additions and 246 deletions

View File

@ -1,5 +1,5 @@
<!DOCTYPE html> <!DOCTYPE html>
<html lang="en" data-view="home" class="no-js"> <html lang="en" data-view="contact" class="no-js">
<head> <head>
<meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, maximum-scale=1.0, user-scalable=0"> <meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, maximum-scale=1.0, user-scalable=0">
<meta name="apple-mobile-web-app-capable" content="yes" /> <meta name="apple-mobile-web-app-capable" content="yes" />
@ -75,20 +75,21 @@
<div class="contacts__arrow"></div> <div class="contacts__arrow"></div>
</div> </div>
<div class="contacts__feedback"> <div class="contacts__feedback">
<form method="post" action="/"> <form method="post" id="feedback__form">
<div class="contacts__message"> <div class="contacts__msg">
<label for="feedback__message">Your Message</label> <label for="feedback__msg">Your Message</label>
<textarea id="feedback__message" class="float-label"></textarea> <textarea id="feedback__msg" class="float-label"></textarea>
</div> </div>
<div class="contacts__email"> <div class="contacts__email">
<label for="feedback__email">Your E-Mail</label> <label for="feedback__email">Your E-Mail</label>
<input type="email" id="feedback__email" text="" class="float-label" /> <input type="email" id="feedback__email" text="" class="float-label" />
</div> </div>
<div class="contacts__terms"> <div class="contacts__terms">
<input id="feedback__terms" type="checkbox" name="terms_accepted" value="1" /> <!--input id="feedback__terms" type="checkbox" name="terms_accepted" value="1" />
<label for="feedback__terms" class="box-label">I agree with <a <label for="feedback__terms" class="box-label"-->
By submitting this form you agree with <a
href="/privacy-statement.html">Privacy Statement</a> and accept href="/privacy-statement.html">Privacy Statement</a> and accept
<a href="terms-of-use.html">Terms of Use</a>.</label> <a href="terms-of-use.html">Terms of Use</a>.
</div> </div>
<div class="form-row"> <div class="form-row">
<button type="submit">Send</button> <button type="submit">Send</button>

View File

@ -1,8 +1,8 @@
'use strict'; 'use strict';
// jStuff // JStuff
function jStuff(query) function JStuff(query)
{ {
this.nodes = null; this.nodes = null;
@ -33,6 +33,11 @@ function jStuff(query)
return this; return this;
}; };
this.onSubmit = function(handler) {
this.all(function(n, f) {n.addEventListener('submit', f, false)}, handler);
return this;
};
this.addClass = function(className) { this.addClass = function(className) {
this.all(function(node, cn) { this.all(function(node, cn) {
if (node.classList) if (node.classList)
@ -77,20 +82,22 @@ function jStuff(query)
} }
}, className); }, className);
} }
this.value = function(value) {
return this.all(function(node, value) {
if (node.value) {
if (value)
node.value = value;
return node.value;
}
return null;
}, value);
}
} }
jStuff.create = function(tagName, childNode) { window.$ = function(q){return new JStuff(q)};
var n = document.createElement(tagName);
if (childNode)
n.appendChild(childNode);
return new jStuff(n);
}
jStuff.createLabel = function(text) { window.$.main = function(func) {
return new jStuff(document.createTextNode(text));
}
jStuff.main = function(func) {
if (window.addEventListener) { if (window.addEventListener) {
addEventListener("load", func, false); addEventListener("load", func, false);
} else if (window.attachEvent) { } else if (window.attachEvent) {
@ -100,7 +107,105 @@ jStuff.main = function(func) {
} }
} }
window.$ = jStuff; $.create = function(tagName, childNode) {
var n = document.createElement(tagName);
if (childNode)
n.appendChild(childNode);
return new JStuff(n);
}
$.createLabel = function(text) {
return new JStuff(document.createTextNode(text));
}
// AJAX
function JStuffAjax(attr) {
var GET = 'GET',
POST = 'POST',
t = this,
query = '',
method,
r;
try {
method = (attr.method == POST) ? POST : GET;
} catch(e) {
method = GET;
}
this.onReadyStateChange = function() {
if (this.request.readyState == 4) {
if (this.request.status === 200) {
if (typeof (this.attr.load) !== 'undefined') {
this.attr.load(this.request.status, this.request.responseText);
}
}
return true;
}
return false
}
try {
r = new XMLHttpRequest();
} catch(e) {
var iev=[
"MSXML2.XmlHttp.5.0",
"MSXML2.XmlHttp.4.0",
"MSXML2.XmlHttp.3.0",
"MSXML2.XmlHttp.2.0",
"Microsoft.XmlHttp"
];
for(var i = 0; i < iev.length; i++) {
try {
r = new ActiveXObject(iev[i]);
break;
} catch(e){
// do nothing
}
}
}
if (typeof (attr.data) !== 'undefined') {
for (var key in attr.data) {
if (query != '')
query += '&';
query += encodeURIComponent(key)+'='+encodeURIComponent(attr.data[key]);
}
if (method == GET) {
attr.url += '?'+query;
query = null;
}
}
if (typeof (attr.sync) === 'undefined') {
attr.sync = true;
}
r.overrideMimeType("text/plain");
r.open(method, attr.url, attr.sync);
r.setRequestHeader("Content-type","application/x-www-form-urlencoded");
r.onreadystatechange = function() {t.onReadyStateChange()};
r.send(query);
this.request = r;
this.attr = attr;
}
$.ajax = function(attr) {return new JStuffAjax(attr)};
$.log = function(msg, ex) {
if (console.log) {
if (ex) {
msg += ' E('+ex.message+')';
}
console.log(msg);
}
};
// SVG fix // SVG fix
@ -110,293 +215,294 @@ window.$ = jStuff;
var LEGACY_SUPPORT = false; var LEGACY_SUPPORT = false;
function embed(parent, svg, target) { function embed(parent, svg, target) {
// if the target exists // if the target exists
if (target) { if (target) {
// create a document fragment to hold the contents of the target // create a document fragment to hold the contents of the target
var fragment = document.createDocumentFragment(); var fragment = document.createDocumentFragment();
// cache the closest matching viewBox // cache the closest matching viewBox
var viewBox = !svg.hasAttribute('viewBox') && target.getAttribute('viewBox'); var viewBox = !svg.hasAttribute('viewBox') && target.getAttribute('viewBox');
// conditionally set the viewBox on the svg // conditionally set the viewBox on the svg
if (viewBox) { if (viewBox) {
svg.setAttribute('viewBox', viewBox); svg.setAttribute('viewBox', viewBox);
} }
// clone the target // clone the target
var clone = target.cloneNode(true); var clone = target.cloneNode(true);
// copy the contents of the clone into the fragment // copy the contents of the clone into the fragment
while (clone.childNodes.length) { while (clone.childNodes.length) {
fragment.appendChild(clone.firstChild); fragment.appendChild(clone.firstChild);
} }
// append the fragment into the svg // append the fragment into the svg
parent.appendChild(fragment); parent.appendChild(fragment);
} }
} }
function loadreadystatechange(xhr) { function loadreadystatechange(xhr) {
// listen to changes in the request // listen to changes in the request
xhr.onreadystatechange = function () { xhr.onreadystatechange = function () {
// if the request is ready // if the request is ready
if (xhr.readyState === 4) { if (xhr.readyState === 4) {
// get the cached html document // get the cached html document
var cachedDocument = xhr._cachedDocument; var cachedDocument = xhr._cachedDocument;
// ensure the cached html document based on the xhr response // ensure the cached html document based on the xhr response
if (!cachedDocument) { if (!cachedDocument) {
cachedDocument = xhr._cachedDocument = document.implementation.createHTMLDocument(''); cachedDocument = xhr._cachedDocument = document.implementation.createHTMLDocument('');
cachedDocument.body.innerHTML = xhr.responseText; cachedDocument.body.innerHTML = xhr.responseText;
// ensure domains are the same, otherwise we'll have issues appending the // ensure domains are the same, otherwise we'll have issues appending the
// element in IE 11 // element in IE 11
// cachedDocument.domain = document.domain; // cachedDocument.domain = document.domain;
xhr._cachedTarget = {}; xhr._cachedTarget = {};
} }
// clear the xhr embeds list and embed each item // clear the xhr embeds list and embed each item
xhr._embeds.splice(0).map(function (item) { xhr._embeds.splice(0).map(function (item) {
// get the cached target // get the cached target
var target = xhr._cachedTarget[item.id]; var target = xhr._cachedTarget[item.id];
// ensure the cached target // ensure the cached target
if (!target) { if (!target) {
target = xhr._cachedTarget[item.id] = cachedDocument.getElementById(item.id); target = xhr._cachedTarget[item.id] = cachedDocument.getElementById(item.id);
} }
// embed the target into the svg // embed the target into the svg
embed(item.parent, item.svg, target); embed(item.parent, item.svg, target);
}); });
} }
}; };
// test the ready state change immediately // test the ready state change immediately
xhr.onreadystatechange(); xhr.onreadystatechange();
} }
function svg4everybody(rawopts) { function svg4everybody(rawopts) {
var opts = Object(rawopts); var opts = Object(rawopts);
// create legacy support variables // create legacy support variables
var nosvg; var nosvg;
var fallback; var fallback;
// if running with legacy support // if running with legacy support
if (LEGACY_SUPPORT) { if (LEGACY_SUPPORT) {
// configure the fallback method // configure the fallback method
fallback = opts.fallback || function (src) { fallback = opts.fallback || function (src) {
return src.replace(/\?[^#]+/, '').replace('#', '.').replace(/^\./, '') + '.png' + (/\?[^#]+/.exec(src) || [''])[0]; return src.replace(/\?[^#]+/, '').replace('#', '.').replace(/^\./, '') + '.png' + (/\?[^#]+/.exec(src) || [''])[0];
}; };
// set whether to shiv <svg> and <use> elements and use image fallbacks // set whether to shiv <svg> and <use> elements and use image fallbacks
nosvg = 'nosvg' in opts ? opts.nosvg : /\bMSIE [1-8]\b/.test(navigator.userAgent); nosvg = 'nosvg' in opts ? opts.nosvg : /\bMSIE [1-8]\b/.test(navigator.userAgent);
// conditionally shiv <svg> and <use> // conditionally shiv <svg> and <use>
if (nosvg) { if (nosvg) {
document.createElement('svg'); document.createElement('svg');
document.createElement('use'); document.createElement('use');
} }
} }
// set whether the polyfill will be activated or not // set whether the polyfill will be activated or not
var polyfill; var polyfill;
var olderIEUA = /\bMSIE [1-8]\.0\b/; var olderIEUA = /\bMSIE [1-8]\.0\b/;
var newerIEUA = /\bTrident\/[567]\b|\bMSIE (?:9|10)\.0\b/; var newerIEUA = /\bTrident\/[567]\b|\bMSIE (?:9|10)\.0\b/;
var webkitUA = /\bAppleWebKit\/(\d+)\b/; var webkitUA = /\bAppleWebKit\/(\d+)\b/;
var olderEdgeUA = /\bEdge\/12\.(\d+)\b/; var olderEdgeUA = /\bEdge\/12\.(\d+)\b/;
var edgeUA = /\bEdge\/.(\d+)\b/; var edgeUA = /\bEdge\/.(\d+)\b/;
//Checks whether iframed //Checks whether iframed
var inIframe = window.top !== window.self; var inIframe = window.top !== window.self;
if ('polyfill' in opts) { if ('polyfill' in opts) {
polyfill = opts.polyfill; polyfill = opts.polyfill;
} else if (LEGACY_SUPPORT) { } else if (LEGACY_SUPPORT) {
polyfill = olderIEUA.test(navigator.userAgent) || newerIEUA.test(navigator.userAgent) || (navigator.userAgent.match(olderEdgeUA) || [])[1] < 10547 || (navigator.userAgent.match(webkitUA) || [])[1] < 537 || edgeUA.test(navigator.userAgent) && inIframe; polyfill = olderIEUA.test(navigator.userAgent) || newerIEUA.test(navigator.userAgent) || (navigator.userAgent.match(olderEdgeUA) || [])[1] < 10547 || (navigator.userAgent.match(webkitUA) || [])[1] < 537 || edgeUA.test(navigator.userAgent) && inIframe;
} else { } else {
polyfill = newerIEUA.test(navigator.userAgent) || (navigator.userAgent.match(olderEdgeUA) || [])[1] < 10547 || (navigator.userAgent.match(webkitUA) || [])[1] < 537 || edgeUA.test(navigator.userAgent) && inIframe; polyfill = newerIEUA.test(navigator.userAgent) || (navigator.userAgent.match(olderEdgeUA) || [])[1] < 10547 || (navigator.userAgent.match(webkitUA) || [])[1] < 537 || edgeUA.test(navigator.userAgent) && inIframe;
} }
// create xhr requests object // create xhr requests object
var requests = {}; var requests = {};
// use request animation frame or a timeout to search the dom for svgs // use request animation frame or a timeout to search the dom for svgs
var requestAnimationFrame = window.requestAnimationFrame || setTimeout; var requestAnimationFrame = window.requestAnimationFrame || setTimeout;
// get a live collection of use elements on the page // get a live collection of use elements on the page
var uses = document.getElementsByTagName('use'); var uses = document.getElementsByTagName('use');
var numberOfSvgUseElementsToBypass = 0; var numberOfSvgUseElementsToBypass = 0;
function oninterval() { function oninterval() {
// get the cached <use> index // get the cached <use> index
var index = 0; var index = 0;
// while the index exists in the live <use> collection // while the index exists in the live <use> collection
while (index < uses.length) { while (index < uses.length) {
// get the current <use> // get the current <use>
var use = uses[index]; var use = uses[index];
// get the current <svg> // get the current <svg>
var parent = use.parentNode; var parent = use.parentNode;
var svg = getSVGAncestor(parent); var svg = getSVGAncestor(parent);
var src = use.getAttribute('xlink:href') || use.getAttribute('href'); var src = use.getAttribute('xlink:href') || use.getAttribute('href');
if (!src && opts.attributeName) { if (!src && opts.attributeName) {
src = use.getAttribute(opts.attributeName); src = use.getAttribute(opts.attributeName);
} }
if (svg && src) { if (svg && src) {
// if running with legacy support // if running with legacy support
if (LEGACY_SUPPORT && nosvg) { if (LEGACY_SUPPORT && nosvg) {
// create a new fallback image // create a new fallback image
var img = document.createElement('img'); var img = document.createElement('img');
// force display in older IE // force display in older IE
img.style.cssText = 'display:inline-block;height:100%;width:100%'; img.style.cssText = 'display:inline-block;height:100%;width:100%';
// set the fallback size using the svg size // set the fallback size using the svg size
img.setAttribute('width', svg.getAttribute('width') || svg.clientWidth); img.setAttribute('width', svg.getAttribute('width') || svg.clientWidth);
img.setAttribute('height', svg.getAttribute('height') || svg.clientHeight); img.setAttribute('height', svg.getAttribute('height') || svg.clientHeight);
// set the fallback src // set the fallback src
img.src = fallback(src, svg, use); img.src = fallback(src, svg, use);
// replace the <use> with the fallback image // replace the <use> with the fallback image
parent.replaceChild(img, use); parent.replaceChild(img, use);
} else if (polyfill) { } else if (polyfill) {
if (!opts.validate || opts.validate(src, svg, use)) { if (!opts.validate || opts.validate(src, svg, use)) {
// remove the <use> element // remove the <use> element
parent.removeChild(use); parent.removeChild(use);
// parse the src and get the url and id // parse the src and get the url and id
var srcSplit = src.split('#'); var srcSplit = src.split('#');
var url = srcSplit.shift(); var url = srcSplit.shift();
var id = srcSplit.join('#'); var id = srcSplit.join('#');
// if the link is external // if the link is external
if (url.length) { if (url.length) {
// get the cached xhr request // get the cached xhr request
var xhr = requests[url]; var xhr = requests[url];
// ensure the xhr request exists // ensure the xhr request exists
if (!xhr) { if (!xhr) {
xhr = requests[url] = new XMLHttpRequest(); xhr = requests[url] = new XMLHttpRequest();
xhr.open('GET', url); xhr.open('GET', url);
xhr.send(); xhr.send();
xhr._embeds = []; xhr._embeds = [];
} }
// add the svg and id as an item to the xhr embeds list // add the svg and id as an item to the xhr embeds list
xhr._embeds.push({ xhr._embeds.push({
parent: parent, parent: parent,
svg: svg, svg: svg,
id: id id: id
}); });
// prepare the xhr ready state change event // prepare the xhr ready state change event
loadreadystatechange(xhr); loadreadystatechange(xhr);
} else { } else {
// embed the local id into the svg // embed the local id into the svg
embed(parent, svg, document.getElementById(id)); embed(parent, svg, document.getElementById(id));
} }
} else { } else {
// increase the index when the previous value was not "valid" // increase the index when the previous value was not "valid"
++index; ++index;
++numberOfSvgUseElementsToBypass; ++numberOfSvgUseElementsToBypass;
} }
} }
} else { } else {
// increase the index when the previous value was not "valid" // increase the index when the previous value was not "valid"
++index; ++index;
} }
} }
// continue the interval // continue the interval
if (!uses.length || uses.length - numberOfSvgUseElementsToBypass > 0) { if (!uses.length || uses.length - numberOfSvgUseElementsToBypass > 0) {
requestAnimationFrame(oninterval, 67); requestAnimationFrame(oninterval, 67);
} }
} }
// conditionally start the interval if the polyfill is active // conditionally start the interval if the polyfill is active
if (polyfill) { if (polyfill) {
oninterval(); oninterval();
} }
} }
function getSVGAncestor(node) { function getSVGAncestor(node) {
var svg = node; var svg = node;
while (svg.nodeName.toLowerCase() !== 'svg') { while (svg.nodeName.toLowerCase() !== 'svg') {
svg = svg.parentNode; svg = svg.parentNode;
if (!svg) { if (!svg) {
break; break;
} }
} }
return svg; return svg;
} }
// Core
var gCore = {
mod: null
};
// Contact
function Contact()
{
var t = this;
this.email = $('#feedback__email');
this.msg = $('#feedback__msg');
this.onLoad = function(httpStatus, content) {
if (httpStatus == 200) {
this.email.value('');
this.msg.value('');
$.log('Success!');
alert("Thank you for your message!");
} else {
alert("Your message was not sent!");
$.log('server response: '+httpStatus);
}
};
this.onSubmit = function(evt) {
$.ajax({
url: '/hook/feedback/',
handler: function(httpStatus, content) {t.onLoad(httpStatus, content)},
data: {email: this.email.value(), msg: this.msg.value()},
method: 'POST'
});
event.preventDefault();
return false;
}
$('#feedback__form').onSubmit(function(evt) {return t.onSubmit(evt)});
}
// Main // Main
function main()
{
/*
var inps = document.querySelectorAll('.float-label');
console.log('INputs: '+JSON.stringify(inps));
for (var i=0; i<inps.length; i++)
{
var inp = inps[i];
if (inp.value != '')
inp.parentNode.classList.add('active');
inp.addEventListener('focus', (event) => {
var t = event.currentTarget;
t.parentNode.classList.add('active');
});
inp.addEventListener('blur', (event) => {
var t = event.currentTarget;
console.log(t.value)
if (t.value == '')
t.parentNode.classList.remove('active');
});
}
window.addEventListener('scroll', (event) => {
var nodes = document.querySelectorAll('.slider'),
scrollTop = window.scrollY;
for(var i=0; i<nodes.length; i++)
{
var speed = parseInt(nodes[i].getAttribute('data-speed'));
console.log(scrollTop);
console.log(nodes[i].getAttribute('data-speed'));
console.log('speed '+speed);
nodes[i].style['transform'] = 'translateY(' + -(scrollTop / speed) + 'px)';
console.log('style '+nodes[i].style.transform);
}
});
*/
}
$.main(function(){ $.main(function(){
// initialize menu
var sw = $('#menu__switch').onClick(function(evt) { var sw = $('#menu__switch').onClick(function(evt) {
var menu = $('#menu'), var menu = $('#menu'),
targ = $(evt.currentTarget); targ = $(evt.currentTarget);
menu.switchClass('menu--visible'); menu.switchClass('menu--visible');
targ.switchClass('menu__switch--opened'); targ.switchClass('menu__switch--opened');
}); });
// modules
switch($(document.documentElement).attribute('data-view')) {
case 'contact':
gCore.mod = new Contact();
break;
}
svg4everybody(); svg4everybody();
}); });