Skip to content

Commit 0d8d350

Browse files
committed
ARIA paper sidebar
1 parent 6bba55d commit 0d8d350

File tree

5 files changed

+165
-122
lines changed

5 files changed

+165
-122
lines changed

devel/manual/css.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,5 +70,6 @@ Generic values
7070
* `#n-prev`
7171
* `#n-search`
7272
* `#n-list`
73+
* `id^=s-` is for submission elements
7374
* `id^=k-` is for inputs and for programmatically assigned IDs, e.g., elements
7475
that need IDs for reference by `label`

scripts/script.js

Lines changed: 76 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -4318,47 +4318,44 @@ hotcrp.onload = (function ($) {
43184318
})(jQuery);
43194319

43204320

4321-
function fold_storage() {
4322-
if (!this || this === window || this === hotcrp) {
4323-
$(".need-fold-storage").each(fold_storage);
4324-
} else {
4325-
removeClass(this, "need-fold-storage");
4326-
var sn = this.getAttribute("data-fold-storage"), smap, k;
4327-
if (sn.charAt(0) === "-") { // default is open, use storage to close
4328-
sn = sn.substring(1);
4329-
}
4330-
if (sn.charAt(0) === "{" || sn.charAt(0) === "[") {
4331-
smap = JSON.parse(sn) || {};
4332-
} else {
4333-
var m = this.className.match(/\bfold(\d*)[oc]\b/),
4334-
n = m[1] === "" ? 0 : +m[1];
4335-
smap = {};
4336-
smap[n] = sn;
4337-
}
4338-
sn = hotcrp.wstorage.json(true, "fold") || hotcrp.wstorage.json(false, "fold") || {};
4339-
for (k in smap) {
4340-
if (sn[smap[k]]) {
4341-
foldup.call(this, null, {open: true, n: +k});
4342-
} else if (sn[smap[k]] != null) {
4343-
foldup.call(this, null, {open: false, n: +k});
4344-
}
4345-
}
4346-
}
4347-
}
4348-
4349-
function fold_session_for(foldnum, type) {
4350-
var s = this.getAttribute("data-fold-" + type), p, flip = false;
4321+
function fold_map(e, type) {
4322+
let s = e.getAttribute("data-fold-" + (type || "storage"));
43514323
if (s && (s.charAt(0) === "{" || s.charAt(0) === "[")) {
4352-
s = (JSON.parse(s) || {})[foldnum];
4324+
s = JSON.parse(s);
4325+
} else if (s) {
4326+
s = [s];
43534327
}
4354-
if (s && s.charAt(0) === "-") {
4355-
s = s.substring(1);
4356-
flip = true;
4328+
const m = {};
4329+
for (const k in s || {}) {
4330+
const v = s[k];
4331+
m[k] = v.charAt(0) === "-" ? [v.substring(1), true] : [v, false];
43574332
}
4358-
if (s && (p = this.getAttribute("data-fold-" + type + "-prefix"))) {
4359-
s = p + s;
4333+
return m;
4334+
}
4335+
4336+
function fold_storage() {
4337+
if (!this || this === window || this === hotcrp) {
4338+
$(".need-fold-storage").each(fold_storage);
4339+
return;
43604340
}
4361-
return s ? [s, flip] : null;
4341+
removeClass(this, "need-fold-storage");
4342+
removeClass(this, "fold-storage-hidden");
4343+
const smap = fold_map(this),
4344+
sn = hotcrp.wstorage.json(true, "fold") || hotcrp.wstorage.json(false, "fold") || {};
4345+
for (const k in smap) {
4346+
if (sn[smap[k][0]] != null) {
4347+
foldup.call(this, null, {open: !sn[smap[k][0]], n: +k});
4348+
}
4349+
}
4350+
this.addEventListener("foldtoggle", function (evt) {
4351+
const info = smap[evt.detail.n || 0], wstor = hotcrp.wstorage;
4352+
let sj = wstor.json(true, "fold") || {};
4353+
evt.detail.open === info[1] ? delete sj[info[0]] : sj[info[0]] = evt.detail.open ? 0 : 1;
4354+
wstor(true, "fold", $.isEmptyObject(sj) ? null : sj);
4355+
sj = wstor.json(false, "fold") || {};
4356+
evt.detail.open === info[1] ? delete sj[info[0]] : sj[info[0]] = evt.detail.open ? 0 : 1;
4357+
wstor(false, "fold", $.isEmptyObject(sj) ? null : sj);
4358+
});
43624359
}
43634360

43644361
function fold(elt, dofold, foldnum) {
@@ -4387,7 +4384,7 @@ function fold(elt, dofold, foldnum) {
43874384
toggleClass(elt, closetxt, wasopen);
43884385

43894386
// check for session
4390-
let s = fold_session_for.call(elt, foldnum, "storage");
4387+
let s = fold_map(elt)[foldnum];
43914388
if (s) {
43924389
const wstor = hotcrp.wstorage;
43934390
let sj = wstor.json(true, "fold") || {};
@@ -4396,7 +4393,7 @@ function fold(elt, dofold, foldnum) {
43964393
sj = wstor.json(false, "fold") || {};
43974394
wasopen === !s[1] ? delete sj[s[0]] : sj[s[0]] = wasopen ? 0 : 1;
43984395
wstor(false, "fold", $.isEmptyObject(sj) ? null : sj);
4399-
} else if ((s = fold_session_for.call(elt, foldnum, "session"))) {
4396+
} else if ((s = fold_map(elt, "session")[foldnum])) {
44004397
$.post(hoturl("=api/session", {v: s[0] + (wasopen ? "=1" : "=0")}));
44014398
}
44024399
}
@@ -4416,23 +4413,30 @@ function foldup(evt, opts) {
44164413
&& !opts.required) {
44174414
return;
44184415
}
4416+
let acting;
4417+
if (this.tagName === "DIV") {
4418+
acting = this.querySelector("[aria-expanded]");
4419+
}
4420+
acting = acting || this;
44194421
// determine targets
44204422
// XXX only partial support for ARIA method
44214423
let foldname, m;
4422-
if (this.ariaControlsElements && this.ariaControlsElements.length > 0) {
4423-
const p = this.closest(".expanded, .collapsed");
4424+
if (acting.ariaControlsElements && acting.ariaControlsElements.length > 0) {
4425+
const p = acting.closest(".expanded, .collapsed");
44244426
if (!("open" in opts)) {
4425-
opts.open = this.ariaExpanded !== "true";
4427+
opts.open = acting.ariaExpanded !== "true";
44264428
}
4427-
this.ariaExpanded = opts.open ? "true" : "false";
4428-
for (const e of this.ariaControlsElements) {
4429-
e.hidden = !opts.open;
4430-
$(e).trigger($.Event("foldtoggle", {which: opts, open: opts.open}));
4429+
acting.ariaExpanded = opts.open ? "true" : "false";
4430+
for (const e of acting.ariaControlsElements) {
4431+
if (e.hidden !== !opts.open) {
4432+
e.hidden = !opts.open;
4433+
e.dispatchEvent(new CustomEvent("foldtoggle", {detail: opts}));
4434+
}
44314435
}
44324436
if (p && hasClass(p, "expanded") !== opts.open) {
44334437
removeClass(p, opts.open ? "collapsed" : "expanded");
44344438
addClass(p, opts.open ? "expanded" : "collapsed");
4435-
$(p).trigger($.Event("foldtoggle", {which: opts, open: opts.open}));
4439+
p.dispatchEvent(new CustomEvent("foldtoggle", {detail: opts}));
44364440
}
44374441
} else {
44384442
let target = this;
@@ -4494,7 +4498,7 @@ function foldup(evt, opts) {
44944498
if (!("open" in opts) || !!opts.open === wantopen) {
44954499
opts.open = wantopen;
44964500
fold(target, !wantopen, opts.n || 0);
4497-
$(target).trigger($.Event("foldtoggle", {which: opts, open: opts.open}));
4501+
$(target).trigger($.Event("foldtoggle", {detail: opts}));
44984502
}
44994503
if (this.hasAttribute("aria-expanded")) {
45004504
this.ariaExpanded = wantopen ? "true" : "false";
@@ -4511,24 +4515,25 @@ function foldup(evt, opts) {
45114515

45124516
handle_ui.on("js-foldup", foldup);
45134517
handle_ui.on("foldtoggle.js-fold-focus", function (evt) {
4514-
if (evt.which.nofocus)
4518+
if (evt.detail.nofocus)
45154519
return;
4516-
var ns = evt.which.n || "";
4517-
if (!hasClass(this, "fold".concat(ns, "c"))
4518-
&& !hasClass(this, "fold".concat(ns, "o")))
4520+
var ns = evt.detail.n || "";
4521+
if (!hasClass(this, `fold${ns}c`)
4522+
&& !hasClass(this, `fold${ns}o`)) {
45194523
return;
4520-
if (evt.which.open) {
4524+
}
4525+
if (evt.open) {
45214526
if (!document.activeElement
45224527
|| !this.contains(document.activeElement)
45234528
|| !document.activeElement.offsetParent) {
4524-
focus_within(this, ".fx".concat(ns, " *"));
4529+
focus_within(this, `.fx${ns} *`);
45254530
}
45264531
} else if (document.activeElement
45274532
&& this.contains(document.activeElement)
45284533
&& document.activeElement.closest(".fx" + ns)) {
4529-
focus_within(this, ":not(.fx".concat(ns, " *)"), true);
4534+
focus_within(this, `:not(.fx${ns} *)`, true);
45304535
}
4531-
evt.which.nofocus = true;
4536+
evt.detail.nofocus = true;
45324537
});
45334538
$(function () {
45344539
$(".uich.js-foldup").each(function () {
@@ -4646,13 +4651,15 @@ handle_ui.on("js-aufoldup", function (evt) {
46464651
});
46474652

46484653
handle_ui.on("js-click-child", function (evt) {
4649-
if (evt.target.closest("a[href], input, select, textarea, button"))
4654+
if (evt.target.closest("a[href], input, select, textarea, button")) {
46504655
return;
4651-
var a = this.querySelector("a[href], input[type=checkbox], input[type=radio]");
4652-
if (!a || a.disabled)
4656+
}
4657+
const a = this.querySelector("a[href], input[type=checkbox], input[type=radio]");
4658+
if (!a || a.disabled) {
46534659
return;
4660+
}
46544661
if (evt.type === "click") {
4655-
var newEvent = new MouseEvent("click", {
4662+
const newEvent = new MouseEvent("click", {
46564663
view: window, bubbles: true, cancelable: true,
46574664
button: evt.button, buttons: evt.buttons,
46584665
ctrlKey: evt.ctrlKey, shiftKey: evt.shiftKey,
@@ -4696,12 +4703,12 @@ handle_ui.on("lla", function () {
46964703
f = e.closest(".linelinks");
46974704
$(f).find(".linelink").removeClass("active");
46984705
addClass(e, "active");
4699-
$(e).trigger($.Event("foldtoggle", {which: {open: true}}));
4706+
$(e).trigger($.Event("foldtoggle", {detail: {open: true}}));
47004707
focus_within(e, ".lld *");
47014708
});
47024709

47034710
$(function () {
4704-
$(".linelink.active").trigger($.Event("foldtoggle", {which: {open: true}}));
4711+
$(".linelink.active").trigger($.Event("foldtoggle", {detail: {open: true}}));
47054712
});
47064713

47074714

@@ -4721,7 +4728,7 @@ function tla_select(self, focus) {
47214728
addClass(tll, "active");
47224729
tll.setAttribute("aria-selected", "true");
47234730
push_history_state(this.href);
4724-
$(e).trigger($.Event("foldtoggle", {which: {open: true}}));
4731+
$(e).trigger($.Event("foldtoggle", {detail: {open: true}}));
47254732
focus && focus_within(e);
47264733
}
47274734

@@ -12779,7 +12786,7 @@ function prepare_pstags() {
1277912786
});
1278012787
$f.on("submit", save_pstags);
1278112788
$f.closest(".foldc, .foldo").on("foldtoggle", function (evt) {
12782-
if (!evt.which.open)
12789+
if (!evt.detail.open)
1278312790
return;
1278412791
$f.data("everOpened", true);
1278512792
$f.find("input").prop("disabled", false);
@@ -13863,7 +13870,7 @@ handle_ui.on("js-named-search", function (evt) {
1386313870

1386413871
handle_ui.on("foldtoggle.js-named-search-tabpanel", function (evt) {
1386513872
const self = this;
13866-
if (!evt.which.open) {
13873+
if (!evt.detail.open) {
1386713874
return;
1386813875
}
1386913876
removeClass(this, "js-named-search-tabpanel");
@@ -13889,7 +13896,7 @@ handle_ui.on("js-select-all", function () {
1388913896
});
1389013897

1389113898
handle_ui.on("js-tag-list-action", function (evt) {
13892-
if (evt.type === "foldtoggle" && !evt.which.open)
13899+
if (evt.type === "foldtoggle" && !evt.detail.open)
1389313900
return;
1389413901
removeClass(this, "js-tag-list-action");
1389513902
$("select.js-submit-action-info-tag").on("change", function () {
@@ -13904,7 +13911,7 @@ handle_ui.on("js-tag-list-action", function (evt) {
1390413911
});
1390513912

1390613913
handle_ui.on("js-assign-list-action", function (evt) {
13907-
if (evt.type === "foldtoggle" && !evt.which.open)
13914+
if (evt.type === "foldtoggle" && !evt.detail.open)
1390813915
return;
1390913916
var self = this;
1391013917
removeClass(self, "js-assign-list-action");
@@ -14183,7 +14190,7 @@ handle_ui.on("js-selector-summary", function () {
1418314190

1418414191

1418514192
handle_ui.on("foldtoggle.js-unfold-pcselector", function (evt) {
14186-
if (evt.which.open) {
14193+
if (evt.detail.open) {
1418714194
removeClass(this, "js-unfold-pcselector");
1418814195
$(this).find("select[data-pcselector-options]").each(populate_pcselector);
1418914196
}
@@ -14643,7 +14650,7 @@ function render_events(e, rows) {
1464314650
}
1464414651

1464514652
handle_ui.on("js-open-activity", function (evt) {
14646-
if (evt.which.open) {
14653+
if (evt.detail.open) {
1464714654
removeClass(this, "js-open-activity");
1464814655
this.append($e("div", "fx20 has-events"));
1464914656
events ? render_events(this, events) : load_more_events();

src/helpers.php

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -366,6 +366,11 @@ function expander($open, $foldnum = null, $open_tooltip = null) {
366366
return $t . '</span>';
367367
}
368368

369+
function aria_expander() {
370+
return '<span class="expander" role="none"><span class="ifx">' . Icons::ui_triangle(2)
371+
. '</span><span class="ifnx">' . Icons::ui_triangle(1) . '</span></span>';
372+
}
373+
369374

370375
/** @param Contact|Author|ReviewInfo|CommentInfo $userlike
371376
* @return string */

0 commit comments

Comments
 (0)