Skip to content

Commit face387

Browse files
Jan LohageJan Lohage
authored andcommitted
Propagate changes of md-rendered checkboxes on an issue page to the server
1 parent 126c933 commit face387

File tree

2 files changed

+74
-0
lines changed

2 files changed

+74
-0
lines changed

web_src/js/index.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import initHeatmap from './features/heatmap.js';
1515
import initProject from './features/projects.js';
1616
import initServiceWorker from './features/serviceworker.js';
1717
import initMarkdownAnchors from './markdown/anchors.js';
18+
import initMarkdownCheckboxes from './markdown/checkboxes.js';
1819
import renderMarkdownContent from './markdown/content.js';
1920
import attachTribute from './features/tribute.js';
2021
import createColorPicker from './features/colorpicker.js';
@@ -2571,6 +2572,8 @@ $(document).ready(async () => {
25712572
renderMarkdownContent(),
25722573
initGithook(),
25732574
]);
2575+
2576+
initMarkdownCheckboxes();
25742577
});
25752578

25762579
function changeHash(hash) {

web_src/js/markdown/checkboxes.js

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
/**
2+
* Affects first comment of issue page only!
3+
*
4+
* Attaches `change` handlers to the markdown rendered checkboxes.
5+
* When a checkbox value changes, the corresponding [ ] or [x] in the markdown string is set accordingly and sent to the server.
6+
* On success it updates the raw-content on error it resets the checkbox to its original value.
7+
*/
8+
export default function initMarkdownCheckboxes() {
9+
const $segment = $('.page-content.issue .comment.first .segment');
10+
const $checkboxes = $segment.find('.render-content.markdown input:checkbox');
11+
const $rawContent = $segment.find('.raw-content');
12+
13+
const url = $segment.find('.edit-content-zone').data('update-url');
14+
const context = $segment.find('.edit-content-zone').data('context');
15+
16+
const checkboxMarkdownPattern = /\[[ x]]/g;
17+
18+
const enableAll = () => $checkboxes.removeAttr('disabled');
19+
const disableAll = () => $checkboxes.attr('disabled', 'disabled');
20+
21+
const onChange = async (ev, cbIndex) => {
22+
const $cb = $(ev.target);
23+
const checkboxMarkdown = $cb.is(':checked') ? '[x]' : '[ ]';
24+
25+
const oldContent = $rawContent.text();
26+
const newContent = oldContent.replace(checkboxMarkdownPattern, replaceNthMatchWith(cbIndex, checkboxMarkdown));
27+
28+
if (newContent !== oldContent) {
29+
disableAll();
30+
31+
try {
32+
await submit(newContent, url, context);
33+
$rawContent.text(newContent);
34+
} catch (e) {
35+
$cb.prop('checked', !$cb.is(':checked'));
36+
37+
console.error(e);
38+
} finally {
39+
enableAll();
40+
}
41+
}
42+
};
43+
44+
enableAll();
45+
$checkboxes.each((cbIndex, cb) => {
46+
$(cb).on('change', (ev) => onChange(ev, cbIndex));
47+
});
48+
}
49+
50+
function submit (content, url, context) {
51+
const csrf = window.config.csrf;
52+
53+
return $.post(url, {
54+
_csrf: csrf,
55+
context,
56+
content,
57+
});
58+
}
59+
60+
61+
function replaceNthMatchWith(n, replaceWith) {
62+
let matchIndex = 0;
63+
64+
return (match) => {
65+
if (n === matchIndex++) {
66+
return replaceWith;
67+
}
68+
69+
return match;
70+
};
71+
}

0 commit comments

Comments
 (0)