forked from CGM_Public/pretix_original
Only warn about bad-contrasat colors
This commit is contained in:
@@ -5,7 +5,6 @@ from django import forms
|
||||
from django.conf import settings
|
||||
from django.core.exceptions import ValidationError
|
||||
from django.forms.utils import from_current_timezone
|
||||
from django.utils.deconstruct import deconstructible
|
||||
from django.utils.html import conditional_escape
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
|
||||
@@ -186,44 +185,3 @@ class SplitDateTimeField(forms.SplitDateTimeField):
|
||||
result = datetime.datetime.combine(*data_list)
|
||||
return from_current_timezone(result)
|
||||
return None
|
||||
|
||||
|
||||
@deconstructible
|
||||
class ColorContrastValidator:
|
||||
message = _('This color is too bright to allow for proper contrast when used for text on white ground.')
|
||||
code = 'contrast'
|
||||
|
||||
def __init__(self, message=None, code=None):
|
||||
if message is not None:
|
||||
self.message = message
|
||||
if code is not None:
|
||||
self.code = code
|
||||
|
||||
def __call__(self, value):
|
||||
# See https://www.w3.org/TR/2008/REC-WCAG20-20081211/#relativeluminancedef
|
||||
fg_color = [int(str(value)[1:3], 16), int(str(value)[1:3], 16), int(str(value)[1:3], 16)]
|
||||
bg_color = [255, 255, 255]
|
||||
fg_lum = [
|
||||
(float(cc) / 255) / 12.92
|
||||
if (float(cc) / 255) < 0.03928
|
||||
else (((float(cc) / 255) + 0.055) / 1.055) ** 2.4
|
||||
for cc in fg_color
|
||||
]
|
||||
bg_lum = [
|
||||
(float(cc) / 255) / 12.92
|
||||
if (float(cc) / 255) < 0.03928
|
||||
else (((float(cc) / 255) + 0.055) / 1.055) ** 2.4
|
||||
for cc in bg_color
|
||||
]
|
||||
fg_rel_lum = 0.2126 * fg_lum[0] + 0.7152 * fg_lum[1] + 0.0722 * fg_lum[2]
|
||||
bg_rel_lum = 0.2126 * bg_lum[0] + 0.7152 * bg_lum[1] + 0.0722 * bg_lum[2]
|
||||
contrast_ratio = (bg_rel_lum + 0.05) / (fg_rel_lum + 0.05)
|
||||
if contrast_ratio < 1.4:
|
||||
raise ValidationError(self.message, code=self.code)
|
||||
|
||||
def __eq__(self, other):
|
||||
return (
|
||||
isinstance(other, ColorContrastValidator) and
|
||||
(self.message == other.message) and
|
||||
(self.code == other.code)
|
||||
)
|
||||
|
||||
@@ -22,9 +22,8 @@ from pretix.base.models.event import EventMetaValue, SubEvent
|
||||
from pretix.base.reldate import RelativeDateField, RelativeDateTimeField
|
||||
from pretix.base.settings import PERSON_NAME_SCHEMES
|
||||
from pretix.control.forms import (
|
||||
ColorContrastValidator, ExtFileField, MultipleLanguagesWidget,
|
||||
SingleLanguageWidget, SlugWidget, SplitDateTimeField,
|
||||
SplitDateTimePickerWidget,
|
||||
ExtFileField, MultipleLanguagesWidget, SingleLanguageWidget, SlugWidget,
|
||||
SplitDateTimeField, SplitDateTimePickerWidget,
|
||||
)
|
||||
from pretix.multidomain.urlreverse import build_absolute_uri
|
||||
from pretix.plugins.banktransfer.payment import BankTransfer
|
||||
@@ -936,37 +935,30 @@ class MailSettingsForm(SettingsForm):
|
||||
class DisplaySettingsForm(SettingsForm):
|
||||
primary_color = forms.CharField(
|
||||
label=_("Primary color"),
|
||||
help_text=_("We strongly suggest to use a dark shade that has a good contrast for text on white ground."),
|
||||
required=False,
|
||||
validators=[
|
||||
RegexValidator(regex='^#[0-9a-fA-F]{6}$',
|
||||
message=_('Please enter the hexadecimal code of a color, e.g. #990000.')),
|
||||
ColorContrastValidator()
|
||||
],
|
||||
widget=forms.TextInput(attrs={'class': 'colorpickerfield'})
|
||||
)
|
||||
theme_color_success = forms.CharField(
|
||||
label=_("Accent color for success"),
|
||||
help_text=_("We strongly suggest to use a dark shade of green that has a good contrast for text on white "
|
||||
"ground."),
|
||||
help_text=_("We strongly suggest to use a shade of green."),
|
||||
required=False,
|
||||
validators=[
|
||||
RegexValidator(regex='^#[0-9a-fA-F]{6}$',
|
||||
message=_('Please enter the hexadecimal code of a color, e.g. #990000.')),
|
||||
ColorContrastValidator()
|
||||
],
|
||||
widget=forms.TextInput(attrs={'class': 'colorpickerfield'})
|
||||
)
|
||||
theme_color_danger = forms.CharField(
|
||||
label=_("Accent color for errors"),
|
||||
help_text=_("We strongly suggest to use a dark shade of red that has a good contrast for text on white "
|
||||
"ground."),
|
||||
help_text=_("We strongly suggest to use a dark shade of red."),
|
||||
required=False,
|
||||
validators=[
|
||||
RegexValidator(regex='^#[0-9a-fA-F]{6}$',
|
||||
message=_('Please enter the hexadecimal code of a color, e.g. #990000.')),
|
||||
|
||||
ColorContrastValidator()
|
||||
],
|
||||
widget=forms.TextInput(attrs={'class': 'colorpickerfield'})
|
||||
)
|
||||
|
||||
@@ -10,9 +10,7 @@ from pretix.api.models import WebHook
|
||||
from pretix.api.webhooks import get_all_webhook_events
|
||||
from pretix.base.forms import I18nModelForm, SettingsForm
|
||||
from pretix.base.models import Device, Organizer, Team
|
||||
from pretix.control.forms import (
|
||||
ColorContrastValidator, ExtFileField, MultipleLanguagesWidget,
|
||||
)
|
||||
from pretix.control.forms import ExtFileField, MultipleLanguagesWidget
|
||||
from pretix.multidomain.models import KnownDomain
|
||||
from pretix.presale.style import get_fonts
|
||||
|
||||
@@ -181,32 +179,27 @@ class OrganizerDisplaySettingsForm(SettingsForm):
|
||||
validators=[
|
||||
RegexValidator(regex='^#[0-9a-fA-F]{6}$',
|
||||
message=_('Please enter the hexadecimal code of a color, e.g. #990000.')),
|
||||
ColorContrastValidator()
|
||||
],
|
||||
widget=forms.TextInput(attrs={'class': 'colorpickerfield'})
|
||||
)
|
||||
theme_color_success = forms.CharField(
|
||||
label=_("Accent color for success"),
|
||||
help_text=_("We strongly suggest to use a dark shade of green that has a good contrast for text on white "
|
||||
"ground."),
|
||||
help_text=_("We strongly suggest to use a shade of green."),
|
||||
required=False,
|
||||
validators=[
|
||||
RegexValidator(regex='^#[0-9a-fA-F]{6}$',
|
||||
message=_('Please enter the hexadecimal code of a color, e.g. #990000.')),
|
||||
ColorContrastValidator()
|
||||
],
|
||||
widget=forms.TextInput(attrs={'class': 'colorpickerfield'})
|
||||
)
|
||||
theme_color_danger = forms.CharField(
|
||||
label=_("Accent color for errors"),
|
||||
help_text=_("We strongly suggest to use a dark shade of red that has a good contrast for text on white "
|
||||
"ground."),
|
||||
help_text=_("We strongly suggest to use a shade of red."),
|
||||
required=False,
|
||||
validators=[
|
||||
RegexValidator(regex='^#[0-9a-fA-F]{6}$',
|
||||
message=_('Please enter the hexadecimal code of a color, e.g. #990000.')),
|
||||
|
||||
ColorContrastValidator()
|
||||
],
|
||||
widget=forms.TextInput(attrs={'class': 'colorpickerfield'})
|
||||
)
|
||||
|
||||
@@ -157,6 +157,22 @@ var form_handlers = function (el) {
|
||||
fill_field.on("dp.show", show);
|
||||
});
|
||||
|
||||
function luminanace(r, g, b) {
|
||||
var a = [r, g, b].map(function (v) {
|
||||
v /= 255;
|
||||
return v <= 0.03928
|
||||
? v / 12.92
|
||||
: Math.pow( (v + 0.055) / 1.055, 2.4 );
|
||||
});
|
||||
return a[0] * 0.2126 + a[1] * 0.7152 + a[2] * 0.0722;
|
||||
}
|
||||
function contrast(rgb1, rgb2) {
|
||||
var l1 = luminanace(rgb1[0], rgb1[1], rgb1[2]) + 0.05,
|
||||
l2 = luminanace(rgb2[0], rgb2[1], rgb2[2]) + 0.05,
|
||||
ratio = l1/l2
|
||||
if (l2 > l1) {ratio = 1/ratio}
|
||||
return ratio.toFixed(1)
|
||||
}
|
||||
el.find(".colorpickerfield").colorpicker({
|
||||
format: 'hex',
|
||||
align: 'left',
|
||||
@@ -173,6 +189,32 @@ var form_handlers = function (el) {
|
||||
maxTop: 200
|
||||
}
|
||||
}
|
||||
}).on('changeColor create', function (e) {
|
||||
var rgb = $(this).colorpicker('color').toRGB();
|
||||
var c = contrast([255,255,255], [rgb.r, rgb.g, rgb.b]);
|
||||
var mark = 'times';
|
||||
if ($(this).parent().find(".contrast-state").length === 0) {
|
||||
$(this).parent().append("<div class='help-block contrast-state'></div>");
|
||||
}
|
||||
var $note = $(this).parent().find(".contrast-state");
|
||||
if ($(this).val() === "") {
|
||||
$note.remove();
|
||||
}
|
||||
if (c > 7) {
|
||||
$note.html("<span class='fa fa-fw fa-check-circle'></span>")
|
||||
.append(gettext('Your color has great contrast and is very easy to read!'));
|
||||
$note.addClass("text-success").removeClass("text-warning").removeClass("text-danger");
|
||||
} else if (c > 2.5) {
|
||||
$note.html("<span class='fa fa-fw fa-info-circle'></span>")
|
||||
.append(gettext('Your color has decent contrast and is probably good-enough to read!'));
|
||||
$note.removeClass("text-success").removeClass("text-warning").removeClass("text-danger");
|
||||
} else {
|
||||
$note.html("<span class='fa fa-fw fa-warning'></span>")
|
||||
.append(gettext('Your color has bad contrast for text on white background, please choose a darker ' +
|
||||
'shade.'));
|
||||
$note.addClass("text-danger").removeClass("text-success").removeClass("text-warning");
|
||||
}
|
||||
console.log(c);
|
||||
});
|
||||
|
||||
el.find("input[data-checkbox-dependency]").each(function () {
|
||||
|
||||
Reference in New Issue
Block a user