improve game creation accessibility for blind players
parent
555e5d970f
commit
7f347bde6d
|
@ -11,6 +11,24 @@ import lila.tournament.System
|
|||
|
||||
trait SetupHelper { self: I18nHelper =>
|
||||
|
||||
type SelectChoice = (String, String, Option[String])
|
||||
|
||||
val clockTimeChoices: List[SelectChoice] = List(
|
||||
("0", "0", none),
|
||||
("0.25", "¼", none),
|
||||
("0.5", "½", none),
|
||||
("0.75", "¾", none)
|
||||
) ::: List(
|
||||
"1", "1.5", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "14", "15", "16",
|
||||
"17", "18", "19", "20", "25", "30", "35", "40", "45", "60", "90", "120", "150", "180"
|
||||
).map { v => (v.toString, v.toString, none) }
|
||||
|
||||
val clockIncrementChoices: List[SelectChoice] = {
|
||||
(0 to 20).toList ::: List(25, 30, 35, 40, 45, 60, 90, 120, 150, 180)
|
||||
} map { s =>
|
||||
(s.toString, s.toString, none)
|
||||
}
|
||||
|
||||
def translatedTimeModeChoices(implicit ctx: Context) = List(
|
||||
(TimeMode.RealTime.id.toString, I18nKeys.realTime.txt(), none),
|
||||
(TimeMode.Correspondence.id.toString, I18nKeys.correspondence.txt(), none),
|
||||
|
@ -38,7 +56,7 @@ trait SetupHelper { self: I18nHelper =>
|
|||
System.Arena.id.toString -> "Arena"
|
||||
)
|
||||
|
||||
private def variantTuple(variant: chess.variant.Variant)(implicit ctx: Context): (String, String, Option[String]) =
|
||||
private def variantTuple(variant: chess.variant.Variant)(implicit ctx: Context): SelectChoice =
|
||||
(variant.id.toString, variant.name, variant.title.some)
|
||||
|
||||
def translatedVariantChoices(implicit ctx: Context) = List(
|
||||
|
|
|
@ -10,6 +10,8 @@ import controllers.routes
|
|||
|
||||
private object bits {
|
||||
|
||||
val prefix = "sf_"
|
||||
|
||||
def fenInput(field: Field, strict: Boolean, validFen: Option[lila.setup.ValidFen])(implicit ctx: Context) = {
|
||||
val url = field.value.fold(routes.Editor.index)(routes.Editor.load).url
|
||||
div(cls := "fen_position optional_config")(
|
||||
|
@ -34,31 +36,33 @@ private object bits {
|
|||
)
|
||||
}
|
||||
|
||||
def renderVariant(form: Form[_], variants: List[(String, String, Option[String])])(implicit ctx: Context) =
|
||||
def renderVariant(form: Form[_], variants: List[SelectChoice])(implicit ctx: Context) =
|
||||
div(cls := "variant label_select")(
|
||||
label(`for` := "variant")(trans.variant.frag()),
|
||||
renderLabel(form("variant"), trans.variant.frag()),
|
||||
renderSelect(form("variant"), variants)
|
||||
)
|
||||
|
||||
def renderSelect(field: Field, options: Seq[(String, String, Option[String])]) =
|
||||
select(id := field.id, name := field.name)(
|
||||
options.map {
|
||||
case (value, name, title) => option(
|
||||
st.value := value,
|
||||
cls := s"${field.name}_$value",
|
||||
st.title := title,
|
||||
selected := field.value.has(value).option(true)
|
||||
)(name)
|
||||
}
|
||||
)
|
||||
def renderSelect(
|
||||
field: Field,
|
||||
options: Seq[SelectChoice],
|
||||
compare: (String, String) => Boolean = (a, b) => a == b
|
||||
) = select(id := s"$prefix${field.id}", name := field.name)(
|
||||
options.map {
|
||||
case (value, name, title) => option(
|
||||
st.value := value,
|
||||
st.title := title,
|
||||
selected := field.value.exists(v => compare(v, value)).option(true)
|
||||
)(name)
|
||||
}
|
||||
)
|
||||
|
||||
def renderRadios(field: Field, options: Seq[(String, String, Option[String])]) =
|
||||
def renderRadios(field: Field, options: Seq[SelectChoice]) =
|
||||
st.group(cls := "radio")(
|
||||
options.map {
|
||||
case (key, name, hint) => div(
|
||||
input(
|
||||
`type` := "radio",
|
||||
id := s"${field.id}_${key}",
|
||||
id := s"$prefix${field.id}_${key}",
|
||||
st.name := field.name,
|
||||
value := key,
|
||||
checked := field.value.has(key).option(true)
|
||||
|
@ -66,32 +70,47 @@ private object bits {
|
|||
label(
|
||||
cls := List("required" -> true, "hint--top" -> hint.isDefined),
|
||||
dataHint := hint,
|
||||
`for` := s"${field.id}_$key"
|
||||
`for` := s"$prefix${field.id}_$key"
|
||||
)(name)
|
||||
)
|
||||
}
|
||||
)
|
||||
|
||||
def renderInput(field: Field) =
|
||||
input(id := field.id, name := field.name, value := field.value)
|
||||
input(name := field.name, value := field.value, `type` := "hidden")
|
||||
|
||||
def renderLabel(field: Field, content: Frag) =
|
||||
label(`for` := s"$prefix${field.id}")(content)
|
||||
|
||||
def renderTimeMode(form: Form[_], config: lila.setup.BaseConfig)(implicit ctx: Context) =
|
||||
div(cls := "time_mode_config optional_config")(
|
||||
div(cls := "label_select")(
|
||||
label(`for` := "timeMode")(trans.timeControl()),
|
||||
renderLabel(form("timeMode"), trans.timeControl()),
|
||||
renderSelect(form("timeMode"), translatedTimeModeChoices)
|
||||
),
|
||||
div(cls := "time_choice slider")(
|
||||
trans.minutesPerSide(),
|
||||
": ",
|
||||
span(chess.Clock.Config(~form("time").value.map(x => (x.toDouble * 60).toInt), 0).limitString.toString),
|
||||
renderInput(form("time"))
|
||||
),
|
||||
div(cls := "increment_choice slider")(
|
||||
trans.incrementInSeconds(),
|
||||
": ",
|
||||
span(form("increment").value),
|
||||
renderInput(form("increment"))
|
||||
if (ctx.blindMode) frag(
|
||||
div(cls := "time_choice")(
|
||||
renderLabel(form("time"), trans.minutesPerSide()),
|
||||
renderSelect(form("time"), clockTimeChoices, (a, b) => a.replace(".0", "") == b)
|
||||
),
|
||||
div(cls := "increment_choice")(
|
||||
renderLabel(form("increment"), trans.incrementInSeconds()),
|
||||
renderSelect(form("increment"), clockIncrementChoices)
|
||||
)
|
||||
)
|
||||
else frag(
|
||||
div(cls := "time_choice slider")(
|
||||
trans.minutesPerSide(),
|
||||
": ",
|
||||
span(chess.Clock.Config(~form("time").value.map(x => (x.toDouble * 60).toInt), 0).limitString.toString),
|
||||
renderInput(form("time"))
|
||||
),
|
||||
div(cls := "increment_choice slider")(
|
||||
trans.incrementInSeconds(),
|
||||
": ",
|
||||
span(form("increment").value),
|
||||
renderInput(form("increment"))
|
||||
)
|
||||
),
|
||||
div(cls := "correspondence")(
|
||||
div(cls := "days_choice slider")(
|
||||
|
|
|
@ -30,14 +30,13 @@ object forms {
|
|||
div(cls := "mode_choice buttons")(
|
||||
renderRadios(form("mode"), translatedModeChoices)
|
||||
),
|
||||
div(cls := "optional_config")(
|
||||
!ctx.blindMode option div(cls := "optional_config")(
|
||||
div(cls := "rating_range_config slider")(
|
||||
trans.ratingRange(),
|
||||
": ",
|
||||
span(cls := "range")("? - ?"),
|
||||
div(cls := "rating_range")(
|
||||
renderInput(form("ratingRange"))(
|
||||
`type` := "hidden",
|
||||
dataMin := RatingRange.min,
|
||||
dataMax := RatingRange.max
|
||||
)
|
||||
|
@ -54,15 +53,21 @@ object forms {
|
|||
renderVariant(form, translatedAiVariantChoices),
|
||||
fenInput(form("fen"), true, validFen),
|
||||
renderTimeMode(form, lila.setup.AiConfig),
|
||||
trans.level(),
|
||||
div(cls := "level buttons")(
|
||||
div(id := "config_level")(
|
||||
renderRadios(form("level"), lila.setup.AiConfig.levelChoices)
|
||||
),
|
||||
div(cls := "ai_info")(
|
||||
ratings.toList.map {
|
||||
case (level, rating) => div(cls := s"level_$level")(trans.aiNameLevelAiLevel("A.I.", level))
|
||||
}
|
||||
if (ctx.blindMode) frag(
|
||||
renderLabel(form("level"), trans.level()),
|
||||
renderSelect(form("level"), lila.setup.AiConfig.levelChoices)
|
||||
)
|
||||
else frag(
|
||||
trans.level(),
|
||||
div(cls := "level buttons")(
|
||||
div(id := "config_level")(
|
||||
renderRadios(form("level"), lila.setup.AiConfig.levelChoices)
|
||||
),
|
||||
div(cls := "ai_info")(
|
||||
ratings.toList.map {
|
||||
case (level, rating) => div(cls := s"${prefix}level_$level")(trans.aiNameLevelAiLevel("A.I.", level))
|
||||
}
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
|
@ -125,11 +130,11 @@ object forms {
|
|||
case (key, name) => button(
|
||||
disabled := typ == "hook" option true,
|
||||
`type` := "submit",
|
||||
dataHint := name,
|
||||
dataHint := !ctx.blindMode option name,
|
||||
cls := s"button hint--bottom $key",
|
||||
st.name := form("color").id,
|
||||
value := key
|
||||
)(i)
|
||||
)(if (ctx.blindMode) name else i)
|
||||
}
|
||||
)
|
||||
)
|
||||
|
|
|
@ -20,17 +20,6 @@ ul.ui-autocomplete li a.ui-state-focus {
|
|||
border-color: #b84400 !important;
|
||||
box-shadow: 0 3px 4px rgba(0, 0, 0, 0.15) inset !important;
|
||||
}
|
||||
.ui-corner-right {
|
||||
border-top-right-radius: 2px;
|
||||
border-bottom-right-radius: 2px;
|
||||
}
|
||||
.ui-corner-left {
|
||||
border-top-left-radius: 2px;
|
||||
border-bottom-left-radius: 2px;
|
||||
}
|
||||
.ui-corner-all {
|
||||
border-radius: 2px;
|
||||
}
|
||||
/* slider */
|
||||
|
||||
.ui-slider {
|
||||
|
|
|
@ -100,8 +100,8 @@ module.exports = function(cfg, element) {
|
|||
var $startButtons = $('#start_buttons');
|
||||
|
||||
var sliderTimes = [
|
||||
0, 0.25, 0.5, 0.75, 1, 1.5, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
|
||||
16, 17, 18, 19, 20, 25, 30, 35, 40, 45, 60, 90, 120, 150, 180
|
||||
0, 1/4, 1/2, 3/4, 1, 3/2, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
|
||||
15, 16, 17, 18, 19, 20, 25, 30, 35, 40, 45, 60, 90, 120, 150, 180
|
||||
];
|
||||
|
||||
function sliderTime(v) {
|
||||
|
@ -175,16 +175,16 @@ module.exports = function(cfg, element) {
|
|||
|
||||
function prepareForm() {
|
||||
var $form = $('.lichess_overboard');
|
||||
var $timeModeSelect = $form.find('#timeMode');
|
||||
var $timeModeSelect = $form.find('#sf_timeMode');
|
||||
var $modeChoicesWrap = $form.find('.mode_choice');
|
||||
var $modeChoices = $modeChoicesWrap.find('input');
|
||||
var $casual = $modeChoices.eq(0),
|
||||
$rated = $modeChoices.eq(1);
|
||||
var $variantSelect = $form.find('#variant');
|
||||
var $variantSelect = $form.find('#sf_variant');
|
||||
var $fenPosition = $form.find(".fen_position");
|
||||
var $timeInput = $form.find('.time_choice input');
|
||||
var $incrementInput = $form.find('.increment_choice input');
|
||||
var $daysInput = $form.find('.days_choice input');
|
||||
var $timeInput = $form.find('.time_choice [name=time]');
|
||||
var $incrementInput = $form.find('.increment_choice [name=increment]');
|
||||
var $daysInput = $form.find('.days_choice [name=days]');
|
||||
var typ = $form.data('type');
|
||||
var $ratings = $form.find('.ratings > div');
|
||||
var randomColorVariants = $form.data('random-color-variants').split(',');
|
||||
|
@ -196,6 +196,8 @@ module.exports = function(cfg, element) {
|
|||
var rated = $rated.prop('checked');
|
||||
var limit = $timeInput.val();
|
||||
var inc = $incrementInput.val();
|
||||
console.log($timeInput, $incrementInput);
|
||||
console.log(limit, inc);
|
||||
// no rated variants with less than 30s on the clock
|
||||
var cantBeRated = (timeMode == '1' && variantId != '1' && limit < 0.5 && inc == 0) ||
|
||||
(variantId != '1' && timeMode != '1');
|
||||
|
@ -285,12 +287,17 @@ module.exports = function(cfg, element) {
|
|||
} else $formTag.one('submit', function() {
|
||||
$submits.hide().end().append(lichess.spinnerHtml);
|
||||
});
|
||||
lichess.slider().done(function() {
|
||||
if ($('body').hasClass('blind_mode')) {
|
||||
$timeInput.add($incrementInput).on('change', function() {
|
||||
toggleButtons();
|
||||
showRating();
|
||||
});
|
||||
} else lichess.slider().done(function() {
|
||||
$timeInput.add($incrementInput).each(function() {
|
||||
var $input = $(this),
|
||||
$value = $input.siblings('span');
|
||||
var isTimeSlider = $input.parent().hasClass('time_choice');
|
||||
$input.hide().after($('<div>').slider({
|
||||
$input.after($('<div>').slider({
|
||||
value: sliderInitVal(parseFloat($input.val()), isTimeSlider ? sliderTime : sliderIncrement, 100),
|
||||
min: 0,
|
||||
max: isTimeSlider ? 34 : 30,
|
||||
|
@ -308,7 +315,7 @@ module.exports = function(cfg, element) {
|
|||
$daysInput.each(function() {
|
||||
var $input = $(this),
|
||||
$value = $input.siblings('span');
|
||||
$input.hide().after($('<div>').slider({
|
||||
$input.after($('<div>').slider({
|
||||
value: sliderInitVal(parseInt($input.val()), sliderDays, 20),
|
||||
min: 1,
|
||||
max: 7,
|
||||
|
@ -401,7 +408,7 @@ module.exports = function(cfg, element) {
|
|||
});
|
||||
$(this).find('#config_level').mouseleave(function() {
|
||||
var level = $(this).find('input:checked').val();
|
||||
$infos.hide().filter('.level_' + level).show();
|
||||
$infos.hide().filter('.sf_level_' + level).show();
|
||||
}).trigger('mouseout');
|
||||
});
|
||||
|
||||
|
|
Loading…
Reference in New Issue