Merge branch 'release/1.3.12'
This commit is contained in:
commit
9c69ae6816
@ -4,6 +4,15 @@ All notable changes to this project will be documented in this file.
|
|||||||
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
||||||
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
||||||
|
|
||||||
|
## [Unreleased]
|
||||||
|
|
||||||
|
## [1.3.12] - 2022-05-25
|
||||||
|
### Added
|
||||||
|
- Captcha to newsletter form
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
- Post only views to accept only POST requests
|
||||||
|
|
||||||
## [1.3.11] - 2022-05-21
|
## [1.3.11] - 2022-05-21
|
||||||
### Changed
|
### Changed
|
||||||
- File logging handler to not propagate
|
- File logging handler to not propagate
|
||||||
|
|||||||
@ -2,7 +2,7 @@ from decimal import Decimal
|
|||||||
from django.test import TestCase
|
from django.test import TestCase
|
||||||
|
|
||||||
from measurement.measures import Weight
|
from measurement.measures import Weight
|
||||||
|
from accounts.models import User
|
||||||
from core.models import (
|
from core.models import (
|
||||||
Product,
|
Product,
|
||||||
ProductPhoto,
|
ProductPhoto,
|
||||||
@ -16,6 +16,8 @@ from core.models import (
|
|||||||
|
|
||||||
|
|
||||||
class ProductModelTest(TestCase):
|
class ProductModelTest(TestCase):
|
||||||
|
fixtures = ['accounts.json']
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def setUpTestData(cls):
|
def setUpTestData(cls):
|
||||||
Product.objects.create(
|
Product.objects.create(
|
||||||
|
|||||||
@ -1,446 +1,371 @@
|
|||||||
<form method="POST" action="https://ptcoffee.activehosted.com/proc.php" id="_form_3_" class="_form _form_3 _inline-form _dark" novalidate>
|
<form action="https://ptcoffee.activehosted.com/proc.php" class="_form _form_3 _inline-form _dark" id="_form_3_" method="post" name="_form_3_" novalidate="">
|
||||||
<input type="hidden" name="u" value="3" />
|
<input name="u" type="hidden" value="3"> <input name="f" type="hidden" value="3"> <input name="s" type="hidden"> <input name="c" type="hidden" value="0"> <input name="m" type="hidden" value="0"> <input name="act" type="hidden" value="sub"> <input name="v" type="hidden" value="2"> <input name="or" type="hidden" value="976f58eb66df9127e2ab7e5003a0ca69">
|
||||||
<input type="hidden" name="f" value="3" />
|
|
||||||
<input type="hidden" name="s" />
|
|
||||||
<input type="hidden" name="c" value="0" />
|
|
||||||
<input type="hidden" name="m" value="0" />
|
|
||||||
<input type="hidden" name="act" value="sub" />
|
|
||||||
<input type="hidden" name="v" value="2" />
|
|
||||||
<input type="hidden" name="or" value="4ef7da616ee5aadd87ec694f0969cb87" />
|
|
||||||
<div class="_form-content">
|
<div class="_form-content">
|
||||||
<div class="_form_element _x15986148 _full_width _clear" >
|
<div class="_form_element _x15986148 _full_width _clear">
|
||||||
<div class="_form-title">
|
<div class="_form-title">
|
||||||
<h5>Get 10% OFF</h5>
|
<h5>Get 10% OFF</h5>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="_form_element _x92496915 _full_width _clear" >
|
<div class="_form_element _x92496915 _full_width _clear">
|
||||||
<div class="_html-code">
|
<div class="_html-code">
|
||||||
<p>Subscribe to get 10% off your first order!</p>
|
<p>Subscribe to get 10% off your first order!</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="_form_element _x55366865 _full_width " >
|
<div class="_form_element _x55366865 _full_width">
|
||||||
<label for="fullname" class="_form-label">
|
<label class="_form-label" for="fullname">Full Name</label>
|
||||||
Full Name
|
|
||||||
</label>
|
|
||||||
<div class="_field-wrapper">
|
<div class="_field-wrapper">
|
||||||
<input type="text" id="fullname" name="fullname" placeholder="Type your name" />
|
<input id="fullname" name="fullname" placeholder="Type your name" type="text">
|
||||||
</div>
|
</div><!-- This STARTS the Custom Objects section -->
|
||||||
<!-- This STARTS the Custom Objects section -->
|
</div>
|
||||||
</div><br>
|
<div class="_form_element _x53687886 _full_width">
|
||||||
<div class="_form_element _x53687886 _full_width " >
|
<label class="_form-label" for="email">Email*</label>
|
||||||
<label for="email" class="_form-label">Email*</label>
|
|
||||||
<div class="_field-wrapper">
|
<div class="_field-wrapper">
|
||||||
<input type="text" id="email" name="email" placeholder="Type your email" required/>
|
<input id="email" name="email" placeholder="Type your email" type="text">
|
||||||
</div>
|
</div><!-- This STARTS the Custom Objects section -->
|
||||||
<!-- This STARTS the Custom Objects section -->
|
</div>
|
||||||
</div><br>
|
<br>
|
||||||
|
<div class="_form_element _x71226546 _full_width">
|
||||||
|
<label class="_form-label" for="ls">Please verify your request*</label>
|
||||||
|
<div class="g-recaptcha" data-sitekey="6LcwIw8TAAAAACP1ysM08EhCgzd6q5JAOUR1a0Go"></div>
|
||||||
|
</div>
|
||||||
|
<br>
|
||||||
<div class="_button-wrapper _full_width">
|
<div class="_button-wrapper _full_width">
|
||||||
<p>
|
<button class="_submit" id="_form_3_submit" type="submit">Subscribe</button>
|
||||||
<button id="_form_3_submit" class="_submit" type="submit">
|
|
||||||
Subscribe
|
|
||||||
</button>
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
<div class="_clear-element">
|
|
||||||
</div>
|
</div>
|
||||||
|
<div class="_clear-element"></div>
|
||||||
</div>
|
</div>
|
||||||
<div class="_form-thank-you" style="display:none;">
|
<div class="_form-thank-you" style="display:none;"></div>
|
||||||
</div>
|
</form>
|
||||||
</form>
|
|
||||||
<script type="text/javascript">
|
<script type="text/javascript">
|
||||||
window.cfields = [];
|
window.cfields = [];
|
||||||
window._show_thank_you = function(id, message, trackcmp_url, email) {
|
window._show_thank_you = function(id, message, trackcmp_url, email) {
|
||||||
var form = document.getElementById('_form_' + id + '_'),
|
var form = document.getElementById('_form_' + id + '_'), thank_you = form.querySelector('._form-thank-you');
|
||||||
thank_you = form.querySelector('._form-thank-you');
|
form.querySelector('._form-content').style.display = 'none';
|
||||||
form.querySelector('._form-content').style.display = 'none';
|
thank_you.innerHTML = message;
|
||||||
thank_you.innerHTML = message;
|
thank_you.style.display = 'block';
|
||||||
thank_you.style.display = 'block';
|
const vgoAlias = typeof visitorGlobalObjectAlias === 'undefined' ? 'vgo' : visitorGlobalObjectAlias;
|
||||||
const vgoAlias = typeof visitorGlobalObjectAlias === 'undefined' ? 'vgo' : visitorGlobalObjectAlias;
|
var visitorObject = window[vgoAlias];
|
||||||
var visitorObject = window[vgoAlias];
|
if (email && typeof visitorObject !== 'undefined') {
|
||||||
if (email && typeof visitorObject !== 'undefined') {
|
visitorObject('setEmail', email);
|
||||||
visitorObject('setEmail', email);
|
visitorObject('update');
|
||||||
visitorObject('update');
|
} else if (typeof(trackcmp_url) != 'undefined' && trackcmp_url) {
|
||||||
} else if (typeof(trackcmp_url) != 'undefined' && trackcmp_url) {
|
// Site tracking URL to use after inline form submission.
|
||||||
// Site tracking URL to use after inline form submission.
|
_load_script(trackcmp_url);
|
||||||
_load_script(trackcmp_url);
|
}
|
||||||
}
|
if (typeof window._form_callback !== 'undefined') window._form_callback(id);
|
||||||
if (typeof window._form_callback !== 'undefined') window._form_callback(id);
|
};
|
||||||
};
|
window._show_error = function(id, message, html) {
|
||||||
window._show_error = function(id, message, html) {
|
var form = document.getElementById('_form_' + id + '_'), err = document.createElement('div'), button = form.querySelector('button'), old_error = form.querySelector('._form_error');
|
||||||
var form = document.getElementById('_form_' + id + '_'),
|
if (old_error) old_error.parentNode.removeChild(old_error);
|
||||||
err = document.createElement('div'),
|
err.innerHTML = message;
|
||||||
button = form.querySelector('button'),
|
err.className = '_error-inner _form_error _no_arrow';
|
||||||
old_error = form.querySelector('._form_error');
|
var wrapper = document.createElement('div');
|
||||||
if (old_error) old_error.parentNode.removeChild(old_error);
|
wrapper.className = '_form-inner';
|
||||||
err.innerHTML = message;
|
wrapper.appendChild(err);
|
||||||
err.className = '_error-inner _form_error _no_arrow';
|
button.parentNode.insertBefore(wrapper, button);
|
||||||
var wrapper = document.createElement('div');
|
document.querySelector('[id^="_form"][id$="_submit"]').disabled = false;
|
||||||
wrapper.className = '_form-inner';
|
if (html) {
|
||||||
wrapper.appendChild(err);
|
var div = document.createElement('div');
|
||||||
button.parentNode.insertBefore(wrapper, button);
|
div.className = '_error-html';
|
||||||
document.querySelector('[id^="_form"][id$="_submit"]').disabled = false;
|
div.innerHTML = html;
|
||||||
if (html) {
|
err.appendChild(div);
|
||||||
var div = document.createElement('div');
|
}
|
||||||
div.className = '_error-html';
|
};
|
||||||
div.innerHTML = html;
|
window._load_script = function(url, callback) {
|
||||||
err.appendChild(div);
|
var head = document.querySelector('head'), script = document.createElement('script'), r = false;
|
||||||
}
|
script.type = 'text/javascript';
|
||||||
};
|
script.charset = 'utf-8';
|
||||||
window._load_script = function(url, callback) {
|
script.src = url;
|
||||||
var head = document.querySelector('head'),
|
if (callback) {
|
||||||
script = document.createElement('script'),
|
script.onload = script.onreadystatechange = function() {
|
||||||
r = false;
|
if (!r && (!this.readyState || this.readyState == 'complete')) {
|
||||||
script.type = 'text/javascript';
|
r = true;
|
||||||
script.charset = 'utf-8';
|
callback();
|
||||||
script.src = url;
|
}
|
||||||
if (callback) {
|
};
|
||||||
script.onload = script.onreadystatechange = function() {
|
}
|
||||||
if (!r && (!this.readyState || this.readyState == 'complete')) {
|
head.appendChild(script);
|
||||||
r = true;
|
};
|
||||||
callback();
|
(function() {
|
||||||
}
|
if (window.location.search.search("excludeform") !== -1) return false;
|
||||||
|
var getCookie = function(name) {
|
||||||
|
var match = document.cookie.match(new RegExp('(^|; )' + name + '=([^;]+)'));
|
||||||
|
return match ? match[2] : null;
|
||||||
|
}
|
||||||
|
var setCookie = function(name, value) {
|
||||||
|
var now = new Date();
|
||||||
|
var time = now.getTime();
|
||||||
|
var expireTime = time + 1000 * 60 * 60 * 24 * 365;
|
||||||
|
now.setTime(expireTime);
|
||||||
|
document.cookie = name + '=' + value + '; expires=' + now + ';path=/';
|
||||||
|
}
|
||||||
|
var addEvent = function(element, event, func) {
|
||||||
|
if (element.addEventListener) {
|
||||||
|
element.addEventListener(event, func);
|
||||||
|
} else {
|
||||||
|
var oldFunc = element['on' + event];
|
||||||
|
element['on' + event] = function() {
|
||||||
|
oldFunc.apply(this, arguments);
|
||||||
|
func.apply(this, arguments);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
head.appendChild(script);
|
}
|
||||||
|
var _removed = false;
|
||||||
|
var form_to_submit = document.getElementById('_form_3_');
|
||||||
|
var allInputs = form_to_submit.querySelectorAll('input, select, textarea'), tooltips = [], submitted = false;
|
||||||
|
|
||||||
|
var getUrlParam = function(name) {
|
||||||
|
var params = new URLSearchParams(window.location.search);
|
||||||
|
return params.get(name) || false;
|
||||||
};
|
};
|
||||||
(function() {
|
|
||||||
if (window.location.search.search("excludeform") !== -1) return false;
|
for (var i = 0; i < allInputs.length; i++) {
|
||||||
var getCookie = function(name) {
|
var regexStr = "field\\[(\\d+)\\]";
|
||||||
var match = document.cookie.match(new RegExp('(^|; )' + name + '=([^;]+)'));
|
var results = new RegExp(regexStr).exec(allInputs[i].name);
|
||||||
return match ? match[2] : null;
|
if (results != undefined) {
|
||||||
|
allInputs[i].dataset.name = window.cfields[results[1]];
|
||||||
|
} else {
|
||||||
|
allInputs[i].dataset.name = allInputs[i].name;
|
||||||
}
|
}
|
||||||
var setCookie = function(name, value) {
|
var fieldVal = getUrlParam(allInputs[i].dataset.name);
|
||||||
var now = new Date();
|
|
||||||
var time = now.getTime();
|
if (fieldVal) {
|
||||||
var expireTime = time + 1000 * 60 * 60 * 24 * 365;
|
if (allInputs[i].dataset.autofill === "false") {
|
||||||
now.setTime(expireTime);
|
continue;
|
||||||
document.cookie = name + '=' + value + '; expires=' + now + ';path=/';
|
|
||||||
}
|
|
||||||
var addEvent = function(element, event, func) {
|
|
||||||
if (element.addEventListener) {
|
|
||||||
element.addEventListener(event, func);
|
|
||||||
} else {
|
|
||||||
var oldFunc = element['on' + event];
|
|
||||||
element['on' + event] = function() {
|
|
||||||
oldFunc.apply(this, arguments);
|
|
||||||
func.apply(this, arguments);
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
}
|
if (allInputs[i].type == "radio" || allInputs[i].type == "checkbox") {
|
||||||
var _removed = false;
|
if (allInputs[i].value == fieldVal) {
|
||||||
var form_to_submit = document.getElementById('_form_3_');
|
allInputs[i].checked = true;
|
||||||
var allInputs = form_to_submit.querySelectorAll('input, select, textarea'),
|
|
||||||
tooltips = [],
|
|
||||||
submitted = false;
|
|
||||||
|
|
||||||
var getUrlParam = function(name) {
|
|
||||||
var params = new URLSearchParams(window.location.search);
|
|
||||||
return params.get(name) || false;
|
|
||||||
};
|
|
||||||
|
|
||||||
for (var i = 0; i < allInputs.length; i++) {
|
|
||||||
var regexStr = "field\\[(\\d+)\\]";
|
|
||||||
var results = new RegExp(regexStr).exec(allInputs[i].name);
|
|
||||||
if (results != undefined) {
|
|
||||||
allInputs[i].dataset.name = window.cfields[results[1]];
|
|
||||||
} else {
|
|
||||||
allInputs[i].dataset.name = allInputs[i].name;
|
|
||||||
}
|
|
||||||
var fieldVal = getUrlParam(allInputs[i].dataset.name);
|
|
||||||
|
|
||||||
if (fieldVal) {
|
|
||||||
if (allInputs[i].dataset.autofill === "false") {
|
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
if (allInputs[i].type == "radio" || allInputs[i].type == "checkbox") {
|
} else {
|
||||||
if (allInputs[i].value == fieldVal) {
|
allInputs[i].value = fieldVal;
|
||||||
allInputs[i].checked = true;
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var remove_tooltips = function() {
|
||||||
|
for (var i = 0; i < tooltips.length; i++) {
|
||||||
|
tooltips[i].tip.parentNode.removeChild(tooltips[i].tip);
|
||||||
|
}
|
||||||
|
tooltips = [];
|
||||||
|
};
|
||||||
|
var remove_tooltip = function(elem) {
|
||||||
|
for (var i = 0; i < tooltips.length; i++) {
|
||||||
|
if (tooltips[i].elem === elem) {
|
||||||
|
tooltips[i].tip.parentNode.removeChild(tooltips[i].tip);
|
||||||
|
tooltips.splice(i, 1);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
var create_tooltip = function(elem, text) {
|
||||||
|
var tooltip = document.createElement('div'), arrow = document.createElement('div'), inner = document.createElement('div'), new_tooltip = {};
|
||||||
|
if (elem.type != 'radio' && elem.type != 'checkbox') {
|
||||||
|
tooltip.className = '_error';
|
||||||
|
arrow.className = '_error-arrow';
|
||||||
|
inner.className = '_error-inner';
|
||||||
|
inner.innerHTML = text;
|
||||||
|
tooltip.appendChild(arrow);
|
||||||
|
tooltip.appendChild(inner);
|
||||||
|
elem.parentNode.appendChild(tooltip);
|
||||||
|
} else {
|
||||||
|
tooltip.className = '_error-inner _no_arrow';
|
||||||
|
tooltip.innerHTML = text;
|
||||||
|
elem.parentNode.insertBefore(tooltip, elem);
|
||||||
|
new_tooltip.no_arrow = true;
|
||||||
|
}
|
||||||
|
new_tooltip.tip = tooltip;
|
||||||
|
new_tooltip.elem = elem;
|
||||||
|
tooltips.push(new_tooltip);
|
||||||
|
return new_tooltip;
|
||||||
|
};
|
||||||
|
var resize_tooltip = function(tooltip) {
|
||||||
|
var rect = tooltip.elem.getBoundingClientRect();
|
||||||
|
var doc = document.documentElement, scrollPosition = rect.top - ((window.pageYOffset || doc.scrollTop) - (doc.clientTop || 0));
|
||||||
|
if (scrollPosition < 40) {
|
||||||
|
tooltip.tip.className = tooltip.tip.className.replace(/ ?(_above|_below) ?/g, '') + ' _below';
|
||||||
|
} else {
|
||||||
|
tooltip.tip.className = tooltip.tip.className.replace(/ ?(_above|_below) ?/g, '') + ' _above';
|
||||||
|
}
|
||||||
|
};
|
||||||
|
var resize_tooltips = function() {
|
||||||
|
if (_removed) return;
|
||||||
|
for (var i = 0; i < tooltips.length; i++) {
|
||||||
|
if (!tooltips[i].no_arrow) resize_tooltip(tooltips[i]);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
var validate_field = function(elem, remove) {
|
||||||
|
var tooltip = null, value = elem.value, no_error = true;
|
||||||
|
remove ? remove_tooltip(elem) : false;
|
||||||
|
if (elem.type != 'checkbox') elem.className = elem.className.replace(/ ?_has_error ?/g, '');
|
||||||
|
if (elem.getAttribute('required') !== null) {
|
||||||
|
if (elem.type == 'radio' || (elem.type == 'checkbox' && /any/.test(elem.className))) {
|
||||||
|
var elems = form_to_submit.elements[elem.name];
|
||||||
|
if (!(elems instanceof NodeList || elems instanceof HTMLCollection) || elems.length <= 1) {
|
||||||
|
no_error = elem.checked;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
no_error = false;
|
||||||
|
for (var i = 0; i < elems.length; i++) {
|
||||||
|
if (elems[i].checked) no_error = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!no_error) {
|
||||||
|
tooltip = create_tooltip(elem, "Please select an option.");
|
||||||
|
}
|
||||||
|
} else if (elem.type =='checkbox') {
|
||||||
|
var elems = form_to_submit.elements[elem.name], found = false, err = [];
|
||||||
|
no_error = true;
|
||||||
|
for (var i = 0; i < elems.length; i++) {
|
||||||
|
if (elems[i].getAttribute('required') === null) continue;
|
||||||
|
if (!found && elems[i] !== elem) return true;
|
||||||
|
found = true;
|
||||||
|
elems[i].className = elems[i].className.replace(/ ?_has_error ?/g, '');
|
||||||
|
if (!elems[i].checked) {
|
||||||
|
no_error = false;
|
||||||
|
elems[i].className = elems[i].className + ' _has_error';
|
||||||
|
err.push("Checking %s is required".replace("%s", elems[i].value));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!no_error) {
|
||||||
|
tooltip = create_tooltip(elem, err.join('<br/>'));
|
||||||
|
}
|
||||||
|
} else if (elem.tagName == 'SELECT') {
|
||||||
|
var selected = true;
|
||||||
|
if (elem.multiple) {
|
||||||
|
selected = false;
|
||||||
|
for (var i = 0; i < elem.options.length; i++) {
|
||||||
|
if (elem.options[i].selected) {
|
||||||
|
selected = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
allInputs[i].value = fieldVal;
|
for (var i = 0; i < elem.options.length; i++) {
|
||||||
|
if (elem.options[i].selected && (!elem.options[i].value || (elem.options[i].value.match(/\n/g)))) {
|
||||||
|
selected = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!selected) {
|
||||||
|
elem.className = elem.className + ' _has_error';
|
||||||
|
no_error = false;
|
||||||
|
tooltip = create_tooltip(elem, "Please select an option.");
|
||||||
|
}
|
||||||
|
} else if (value === undefined || value === null || value === '') {
|
||||||
|
elem.className = elem.className + ' _has_error';
|
||||||
|
no_error = false;
|
||||||
|
tooltip = create_tooltip(elem, "This field is required.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (no_error && elem.name == 'email') {
|
||||||
|
if (!value.match(/^[\+_a-z0-9-'&=]+(\.[\+_a-z0-9-']+)*@[a-z0-9-]+(\.[a-z0-9-]+)*(\.[a-z]{2,})$/i)) {
|
||||||
|
elem.className = elem.className + ' _has_error';
|
||||||
|
no_error = false;
|
||||||
|
tooltip = create_tooltip(elem, "Enter a valid email address.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (no_error && /date_field/.test(elem.className)) {
|
||||||
|
if (!value.match(/^\d\d\d\d-\d\d-\d\d$/)) {
|
||||||
|
elem.className = elem.className + ' _has_error';
|
||||||
|
no_error = false;
|
||||||
|
tooltip = create_tooltip(elem, "Enter a valid date.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
tooltip ? resize_tooltip(tooltip) : false;
|
||||||
|
return no_error;
|
||||||
|
};
|
||||||
|
var needs_validate = function(el) {
|
||||||
|
if(el.getAttribute('required') !== null){
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
if(el.name === 'email' && el.value !== ""){
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
};
|
||||||
|
var validate_form = function(e) {
|
||||||
|
var err = form_to_submit.querySelector('._form_error'), no_error = true;
|
||||||
|
if (!submitted) {
|
||||||
|
submitted = true;
|
||||||
|
for (var i = 0, len = allInputs.length; i < len; i++) {
|
||||||
|
var input = allInputs[i];
|
||||||
|
if (needs_validate(input)) {
|
||||||
|
if (input.type == 'text' || input.type == 'number' || input.type == 'time') {
|
||||||
|
addEvent(input, 'blur', function() {
|
||||||
|
this.value = this.value.trim();
|
||||||
|
validate_field(this, true);
|
||||||
|
});
|
||||||
|
addEvent(input, 'input', function() {
|
||||||
|
validate_field(this, true);
|
||||||
|
});
|
||||||
|
} else if (input.type == 'radio' || input.type == 'checkbox') {
|
||||||
|
(function(el) {
|
||||||
|
var radios = form_to_submit.elements[el.name];
|
||||||
|
for (var i = 0; i < radios.length; i++) {
|
||||||
|
addEvent(radios[i], 'click', function() {
|
||||||
|
validate_field(el, true);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
})(input);
|
||||||
|
} else if (input.tagName == 'SELECT') {
|
||||||
|
addEvent(input, 'change', function() {
|
||||||
|
validate_field(this, true);
|
||||||
|
});
|
||||||
|
} else if (input.type == 'textarea'){
|
||||||
|
addEvent(input, 'input', function() {
|
||||||
|
validate_field(this, true);
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
remove_tooltips();
|
||||||
var remove_tooltips = function() {
|
for (var i = 0, len = allInputs.length; i < len; i++) {
|
||||||
for (var i = 0; i < tooltips.length; i++) {
|
var elem = allInputs[i];
|
||||||
tooltips[i].tip.parentNode.removeChild(tooltips[i].tip);
|
if (needs_validate(elem)) {
|
||||||
}
|
if (elem.tagName.toLowerCase() !== "select") {
|
||||||
tooltips = [];
|
elem.value = elem.value.trim();
|
||||||
};
|
|
||||||
var remove_tooltip = function(elem) {
|
|
||||||
for (var i = 0; i < tooltips.length; i++) {
|
|
||||||
if (tooltips[i].elem === elem) {
|
|
||||||
tooltips[i].tip.parentNode.removeChild(tooltips[i].tip);
|
|
||||||
tooltips.splice(i, 1);
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
validate_field(elem) ? true : no_error = false;
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
var create_tooltip = function(elem, text) {
|
if (!no_error && e) {
|
||||||
var tooltip = document.createElement('div'),
|
|
||||||
arrow = document.createElement('div'),
|
|
||||||
inner = document.createElement('div'),
|
|
||||||
new_tooltip = {};
|
|
||||||
if (elem.type != 'radio' && elem.type != 'checkbox') {
|
|
||||||
tooltip.className = '_error';
|
|
||||||
arrow.className = '_error-arrow';
|
|
||||||
inner.className = '_error-inner';
|
|
||||||
inner.innerHTML = text;
|
|
||||||
tooltip.appendChild(arrow);
|
|
||||||
tooltip.appendChild(inner);
|
|
||||||
elem.parentNode.appendChild(tooltip);
|
|
||||||
} else {
|
|
||||||
tooltip.className = '_error-inner _no_arrow';
|
|
||||||
tooltip.innerHTML = text;
|
|
||||||
elem.parentNode.insertBefore(tooltip, elem);
|
|
||||||
new_tooltip.no_arrow = true;
|
|
||||||
}
|
|
||||||
new_tooltip.tip = tooltip;
|
|
||||||
new_tooltip.elem = elem;
|
|
||||||
tooltips.push(new_tooltip);
|
|
||||||
return new_tooltip;
|
|
||||||
};
|
|
||||||
var resize_tooltip = function(tooltip) {
|
|
||||||
var rect = tooltip.elem.getBoundingClientRect();
|
|
||||||
var doc = document.documentElement,
|
|
||||||
scrollPosition = rect.top - ((window.pageYOffset || doc.scrollTop) - (doc.clientTop || 0));
|
|
||||||
if (scrollPosition < 40) {
|
|
||||||
tooltip.tip.className = tooltip.tip.className.replace(/ ?(_above|_below) ?/g, '') + ' _below';
|
|
||||||
} else {
|
|
||||||
tooltip.tip.className = tooltip.tip.className.replace(/ ?(_above|_below) ?/g, '') + ' _above';
|
|
||||||
}
|
|
||||||
};
|
|
||||||
var resize_tooltips = function() {
|
|
||||||
if (_removed) return;
|
|
||||||
for (var i = 0; i < tooltips.length; i++) {
|
|
||||||
if (!tooltips[i].no_arrow) resize_tooltip(tooltips[i]);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
var validate_field = function(elem, remove) {
|
|
||||||
var tooltip = null,
|
|
||||||
value = elem.value,
|
|
||||||
no_error = true;
|
|
||||||
remove ? remove_tooltip(elem) : false;
|
|
||||||
if (elem.type != 'checkbox') elem.className = elem.className.replace(/ ?_has_error ?/g, '');
|
|
||||||
if (elem.getAttribute('required') !== null) {
|
|
||||||
if (elem.type == 'radio' || (elem.type == 'checkbox' && /any/.test(elem.className))) {
|
|
||||||
var elems = form_to_submit.elements[elem.name];
|
|
||||||
if (!(elems instanceof NodeList || elems instanceof HTMLCollection) || elems.length <= 1) {
|
|
||||||
no_error = elem.checked;
|
|
||||||
} else {
|
|
||||||
no_error = false;
|
|
||||||
for (var i = 0; i < elems.length; i++) {
|
|
||||||
if (elems[i].checked) no_error = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!no_error) {
|
|
||||||
tooltip = create_tooltip(elem, "Please select an option.");
|
|
||||||
}
|
|
||||||
} else if (elem.type == 'checkbox') {
|
|
||||||
var elems = form_to_submit.elements[elem.name],
|
|
||||||
found = false,
|
|
||||||
err = [];
|
|
||||||
no_error = true;
|
|
||||||
for (var i = 0; i < elems.length; i++) {
|
|
||||||
if (elems[i].getAttribute('required') === null) continue;
|
|
||||||
if (!found && elems[i] !== elem) return true;
|
|
||||||
found = true;
|
|
||||||
elems[i].className = elems[i].className.replace(/ ?_has_error ?/g, '');
|
|
||||||
if (!elems[i].checked) {
|
|
||||||
no_error = false;
|
|
||||||
elems[i].className = elems[i].className + ' _has_error';
|
|
||||||
err.push("Checking %s is required".replace("%s", elems[i].value));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!no_error) {
|
|
||||||
tooltip = create_tooltip(elem, err.join('<br/>'));
|
|
||||||
}
|
|
||||||
} else if (elem.tagName == 'SELECT') {
|
|
||||||
var selected = true;
|
|
||||||
if (elem.multiple) {
|
|
||||||
selected = false;
|
|
||||||
for (var i = 0; i < elem.options.length; i++) {
|
|
||||||
if (elem.options[i].selected) {
|
|
||||||
selected = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
for (var i = 0; i < elem.options.length; i++) {
|
|
||||||
if (elem.options[i].selected && (!elem.options[i].value || (elem.options[i].value.match(/\n/g)))) {
|
|
||||||
selected = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!selected) {
|
|
||||||
elem.className = elem.className + ' _has_error';
|
|
||||||
no_error = false;
|
|
||||||
tooltip = create_tooltip(elem, "Please select an option.");
|
|
||||||
}
|
|
||||||
} else if (value === undefined || value === null || value === '') {
|
|
||||||
elem.className = elem.className + ' _has_error';
|
|
||||||
no_error = false;
|
|
||||||
tooltip = create_tooltip(elem, "This field is required.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (no_error && elem.name == 'email') {
|
|
||||||
if (!value.match(/^[\+_a-z0-9-'&=]+(\.[\+_a-z0-9-']+)*@[a-z0-9-]+(\.[a-z0-9-]+)*(\.[a-z]{2,})$/i)) {
|
|
||||||
elem.className = elem.className + ' _has_error';
|
|
||||||
no_error = false;
|
|
||||||
tooltip = create_tooltip(elem, "Enter a valid email address.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (no_error && /date_field/.test(elem.className)) {
|
|
||||||
if (!value.match(/^\d\d\d\d-\d\d-\d\d$/)) {
|
|
||||||
elem.className = elem.className + ' _has_error';
|
|
||||||
no_error = false;
|
|
||||||
tooltip = create_tooltip(elem, "Enter a valid date.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
tooltip ? resize_tooltip(tooltip) : false;
|
|
||||||
return no_error;
|
|
||||||
};
|
|
||||||
var needs_validate = function(el) {
|
|
||||||
if (el.getAttribute('required') !== null) {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
if (el.name === 'email' && el.value !== "") {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
};
|
|
||||||
var validate_form = function(e) {
|
|
||||||
var err = form_to_submit.querySelector('._form_error'),
|
|
||||||
no_error = true;
|
|
||||||
if (!submitted) {
|
|
||||||
submitted = true;
|
|
||||||
for (var i = 0, len = allInputs.length; i < len; i++) {
|
|
||||||
var input = allInputs[i];
|
|
||||||
if (needs_validate(input)) {
|
|
||||||
if (input.type == 'text' || input.type == 'number' || input.type == 'time') {
|
|
||||||
addEvent(input, 'blur', function() {
|
|
||||||
this.value = this.value.trim();
|
|
||||||
validate_field(this, true);
|
|
||||||
});
|
|
||||||
addEvent(input, 'input', function() {
|
|
||||||
validate_field(this, true);
|
|
||||||
});
|
|
||||||
} else if (input.type == 'radio' || input.type == 'checkbox') {
|
|
||||||
(function(el) {
|
|
||||||
var radios = form_to_submit.elements[el.name];
|
|
||||||
for (var i = 0; i < radios.length; i++) {
|
|
||||||
addEvent(radios[i], 'click', function() {
|
|
||||||
validate_field(el, true);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
})(input);
|
|
||||||
} else if (input.tagName == 'SELECT') {
|
|
||||||
addEvent(input, 'change', function() {
|
|
||||||
validate_field(this, true);
|
|
||||||
});
|
|
||||||
} else if (input.type == 'textarea') {
|
|
||||||
addEvent(input, 'input', function() {
|
|
||||||
validate_field(this, true);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
remove_tooltips();
|
|
||||||
for (var i = 0, len = allInputs.length; i < len; i++) {
|
|
||||||
var elem = allInputs[i];
|
|
||||||
if (needs_validate(elem)) {
|
|
||||||
if (elem.tagName.toLowerCase() !== "select") {
|
|
||||||
elem.value = elem.value.trim();
|
|
||||||
}
|
|
||||||
validate_field(elem) ? true : no_error = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!no_error && e) {
|
|
||||||
e.preventDefault();
|
|
||||||
}
|
|
||||||
resize_tooltips();
|
|
||||||
return no_error;
|
|
||||||
};
|
|
||||||
addEvent(window, 'resize', resize_tooltips);
|
|
||||||
addEvent(window, 'scroll', resize_tooltips);
|
|
||||||
var _form_serialize = function(form) {
|
|
||||||
if (!form || form.nodeName !== "FORM") {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
var i, j, q = [];
|
|
||||||
for (i = 0; i < form.elements.length; i++) {
|
|
||||||
if (form.elements[i].name === "") {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
switch (form.elements[i].nodeName) {
|
|
||||||
case "INPUT":
|
|
||||||
switch (form.elements[i].type) {
|
|
||||||
case "text":
|
|
||||||
case "number":
|
|
||||||
case "date":
|
|
||||||
case "time":
|
|
||||||
case "hidden":
|
|
||||||
case "password":
|
|
||||||
case "button":
|
|
||||||
case "reset":
|
|
||||||
case "submit":
|
|
||||||
q.push(form.elements[i].name + "=" + encodeURIComponent(form.elements[i].value));
|
|
||||||
break;
|
|
||||||
case "checkbox":
|
|
||||||
case "radio":
|
|
||||||
if (form.elements[i].checked) {
|
|
||||||
q.push(form.elements[i].name + "=" + encodeURIComponent(form.elements[i].value))
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case "file":
|
|
||||||
break
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case "TEXTAREA":
|
|
||||||
q.push(form.elements[i].name + "=" + encodeURIComponent(form.elements[i].value));
|
|
||||||
break;
|
|
||||||
case "SELECT":
|
|
||||||
switch (form.elements[i].type) {
|
|
||||||
case "select-one":
|
|
||||||
q.push(form.elements[i].name + "=" + encodeURIComponent(form.elements[i].value));
|
|
||||||
break;
|
|
||||||
case "select-multiple":
|
|
||||||
for (j = 0; j < form.elements[i].options.length; j++) {
|
|
||||||
if (form.elements[i].options[j].selected) {
|
|
||||||
q.push(form.elements[i].name + "=" + encodeURIComponent(form.elements[i].options[j].value))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case "BUTTON":
|
|
||||||
switch (form.elements[i].type) {
|
|
||||||
case "reset":
|
|
||||||
case "submit":
|
|
||||||
case "button":
|
|
||||||
q.push(form.elements[i].name + "=" + encodeURIComponent(form.elements[i].value));
|
|
||||||
break
|
|
||||||
}
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return q.join("&")
|
|
||||||
};
|
|
||||||
var form_submit = function(e) {
|
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
if (validate_form()) {
|
}
|
||||||
// use this trick to get the submit button & disable it using plain javascript
|
resize_tooltips();
|
||||||
document.querySelector('#_form_3_submit').disabled = true;
|
return no_error;
|
||||||
var serialized = _form_serialize(document.getElementById('_form_3_')).replace(/%0A/g, '\\n');
|
};
|
||||||
var err = form_to_submit.querySelector('._form_error');
|
addEvent(window, 'resize', resize_tooltips);
|
||||||
err ? err.parentNode.removeChild(err) : false;
|
addEvent(window, 'scroll', resize_tooltips);
|
||||||
_load_script('https://ptcoffee.activehosted.com/proc.php?' + serialized + '&jsonp=true');
|
window['recaptcha_callback'] = function() {
|
||||||
}
|
// Get all recaptchas in the DOM (there may be more than one form on the page).
|
||||||
return false;
|
var recaptchas = document.getElementsByClassName("g-recaptcha");
|
||||||
};
|
for (var i in recaptchas) {
|
||||||
addEvent(form_to_submit, 'submit', form_submit);
|
// Set the recaptcha element ID, so the recaptcha can be applied to each element.
|
||||||
})();
|
var recaptcha_id = "recaptcha_" + i;
|
||||||
|
recaptchas[i].id = recaptcha_id;
|
||||||
|
var el = document.getElementById(recaptcha_id);
|
||||||
|
if (el != null) {
|
||||||
|
var sitekey = el.getAttribute("data-sitekey");
|
||||||
|
var stoken = el.getAttribute("data-stoken");
|
||||||
|
grecaptcha.render(recaptcha_id, {"sitekey":sitekey,"stoken":stoken});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}; _load_script("//www.google.com/recaptcha/api.js?onload=recaptcha_callback&render=explicit");
|
||||||
|
var _form_serialize = function(form){if(!form||form.nodeName!=="FORM"){return }var i,j,q=[];for(i=0;i<form.elements.length;i++){if(form.elements[i].name===""){continue}switch(form.elements[i].nodeName){case"INPUT":switch(form.elements[i].type){case"text":case"number":case"date":case"time":case"hidden":case"password":case"button":case"reset":case"submit":q.push(form.elements[i].name+"="+encodeURIComponent(form.elements[i].value));break;case"checkbox":case"radio":if(form.elements[i].checked){q.push(form.elements[i].name+"="+encodeURIComponent(form.elements[i].value))}break;case"file":break}break;case"TEXTAREA":q.push(form.elements[i].name+"="+encodeURIComponent(form.elements[i].value));break;case"SELECT":switch(form.elements[i].type){case"select-one":q.push(form.elements[i].name+"="+encodeURIComponent(form.elements[i].value));break;case"select-multiple":for(j=0;j<form.elements[i].options.length;j++){if(form.elements[i].options[j].selected){q.push(form.elements[i].name+"="+encodeURIComponent(form.elements[i].options[j].value))}}break}break;case"BUTTON":switch(form.elements[i].type){case"reset":case"submit":case"button":q.push(form.elements[i].name+"="+encodeURIComponent(form.elements[i].value));break}break}}return q.join("&")};
|
||||||
|
var form_submit = function(e) {
|
||||||
|
e.preventDefault();
|
||||||
|
if (validate_form()) {
|
||||||
|
// use this trick to get the submit button & disable it using plain javascript
|
||||||
|
document.querySelector('#_form_3_submit').disabled = true;
|
||||||
|
var serialized = _form_serialize(document.getElementById('_form_3_')).replace(/%0A/g, '\\n');
|
||||||
|
var err = form_to_submit.querySelector('._form_error');
|
||||||
|
err ? err.parentNode.removeChild(err) : false;
|
||||||
|
_load_script('https://ptcoffee.activehosted.com/proc.php?' + serialized + '&jsonp=true');
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
addEvent(form_to_submit, 'submit', form_submit);
|
||||||
|
})();
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@ -65,6 +65,7 @@ class CartView(TemplateView):
|
|||||||
class CartAddProductView(SingleObjectMixin, FormView):
|
class CartAddProductView(SingleObjectMixin, FormView):
|
||||||
model = Product
|
model = Product
|
||||||
form_class = AddToCartForm
|
form_class = AddToCartForm
|
||||||
|
http_method_names = ['post']
|
||||||
|
|
||||||
def get_success_url(self):
|
def get_success_url(self):
|
||||||
return reverse('storefront:cart-detail')
|
return reverse('storefront:cart-detail')
|
||||||
@ -90,6 +91,7 @@ class CartAddProductView(SingleObjectMixin, FormView):
|
|||||||
class CartUpdateProductView(SingleObjectMixin, FormView):
|
class CartUpdateProductView(SingleObjectMixin, FormView):
|
||||||
model = Product
|
model = Product
|
||||||
form_class = UpdateCartItemForm
|
form_class = UpdateCartItemForm
|
||||||
|
http_method_names = ['post']
|
||||||
|
|
||||||
def get_success_url(self):
|
def get_success_url(self):
|
||||||
return reverse('storefront:cart-detail')
|
return reverse('storefront:cart-detail')
|
||||||
@ -121,9 +123,9 @@ def cart_remove_product_view(request, pk, grind):
|
|||||||
|
|
||||||
|
|
||||||
class CouponApplyView(FormView):
|
class CouponApplyView(FormView):
|
||||||
template_name = 'contact.html'
|
|
||||||
form_class = CouponApplyForm
|
form_class = CouponApplyForm
|
||||||
success_url = reverse_lazy('storefront:cart-detail')
|
success_url = reverse_lazy('storefront:cart-detail')
|
||||||
|
http_method_names = ['post']
|
||||||
|
|
||||||
def form_valid(self, form):
|
def form_valid(self, form):
|
||||||
today = timezone.localtime(timezone.now()).date()
|
today = timezone.localtime(timezone.now()).date()
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user