s4

view s4-main.js @ 846:9c4e16c173db

Add support for small help on describing markdown
author HIROSE Yuuji <yuuji@gentei.org>
date Fri, 26 Jun 2020 19:55:14 +0900
parents a6462eea48be
children a9e147e355fd
line source
1 (function (){
2 function collectElementsByAttr(elm, attr, val) {
3 var e = document.getElementsByTagName(elm);
4 if (!e) return null;
5 var list = [];
6 for (var i of e) {
7 if (i.getAttribute(attr) == val)
8 list.push(i)
9 }
10 return list;
11 }
12 function nthChildOf(parent, n, elem) { // Return Nth child of type ELEM
13 // N begins with 1
14 var i=0;
15 var le = elem.toLowerCase();
16 for (var c of parent.childNodes) {
17 if (!c.tagName) continue;
18 if (c.tagName.toLowerCase() == le) {
19 if (++i >= n) return c;
20 }
21 }
22 return null;
23 }
24 function insertRedirect(e) {
25 var articleId, textarea = document.getElementById("text");
26 var p = e.target, checked = p.checked;
27 while (p = p.parentNode)
28 if (p.nodeName.match(/^td$/i)) break;
29 if (!p) return;
30 while (p = p.nextSibling)
31 if (p.nodeName.match(/^td$/i)) break;
32 if (!p) return;
33 articleId = p.getAttribute("id");
34 if (textarea && articleId) {
35 var tv = textarea.value, lines;
36 if (tv)
37 lines = tv.split("\n");
38 else
39 lines = [""];
40 var re = new RegExp("[, ]*#"+articleId+"(?![0-9])");
41 checked = (p.nodeName.match(/^input$/)
42 ? p.checked // checkbox obeys its status
43 : !lines[0].match(re)) // a-elment toggles redirection
44 if (checked) {
45 if (!lines[0].match(re)) {
46 var re2 = new RegExp(/>#[#0-9, ]+[0-9]/);
47 if (lines[0].match(re2))
48 lines[0] = lines[0].replace(
49 re2, '$&, '+'#'+articleId);
50 else {
51 if (lines[0] > "") lines[0] = " "+lines[0];
52 lines[0] = ">#"+articleId+lines[0];
53 }
54 }
55 } else { // Remove #xxxxx
56 if (lines[0].match(/^>#[0-9 ,]+#/)) // 2 or more #id's
57 lines[0] = lines[0].replace(
58 new RegExp("^>#"+articleId+"[ ,]*"), ">").replace(
59 new RegExp("[ ,]*#"+articleId), "");
60 else {
61 lines[0] = lines[0].replace(
62 new RegExp(">#"+articleId+"[ ,]*"), "");
63 }
64 }
65 lines[0] = lines[0].replace(/^> *$/, '');
66 textarea.value = lines.join("\n");
67 }
68 }
69 function reverseChecks() {
70 var names = collectElementsByAttr("input", "name", "usel");
71 for (let u of names) {
72 u.checked = !u.checked;
73 }
74 }
75 function helpMarkdown(e) {
76 //alert(e.keyCode);
77 if (e.keyCode == 13) {
78 e.preventDefault();
79 var area = e.target;
80 var pos = area.selectionStart, text = area.value;
81 var last = text.lastIndexOf("\n", pos-1);
82 var line = last ? text.substring(last+1) : text;
83 var tail = text.substring(pos-2, pos);
84 var add = "", offset = 0;
85 if (line.startsWith("* ")) {
86 add = (tail==" ") ? " " : "* ";
87 } else if (line.match(/^([1-9][0-9]*)\. /)) {
88 ln = parseInt(RegExp.$1);
89 add = (tail==" ") ? " ".repeat(RegExp.$1.length+2)
90 : (ln+1)+". ";
91 } else if (line.match(/^\|( *).+\|/)) {
92 add = "|" + RegExp.$1 + " |";
93 offset = -2;
94 }
95 area.value = text.substring(0, pos) + "\n" + add;
96 //area.setSelectionRange(pos+length(add));
97 area.selectionStart=area.selectionEnd
98 = (area.selectionStart + offset);
99 }
100 }
101 /* Init event listeners */
102 function addFileInput() {
103 var inpfile = collectElementsByAttr("input", "name", "image");
104 if (!inpfile) return;
105 var filled = true;
106 var i, ih;
107 for (i of inpfile) {
108 if (! i.value) filled=false;
109 }
110 if (filled) {
111 ih = i.parentNode.innerHTML;
112 if (ih) {
113 var inpf = ih.substring(ih.indexOf("<input")),
114 newi = "<br>"+inpf.substring(0, inpf.indexOf(">")+1);
115 i.insertAdjacentHTML("afterend", newi)
116 // alert(newi);
117 }
118 }
119 }
120 function initFileInput() { // Multiplies "input type=file"
121 var el, morefile = document.getElementById("morefile");
122 if (morefile) {
123 for (el of collectElementsByAttr("input", "name", "image")) {
124 el.addEventListener("change", function(ev) {
125 if (ev.target.value > "" && ev.target.files.length == 1)
126 morefile.style.visibility = "visible";
127 // No need to hide again, sure?
128 });
129 }
130 morefile.addEventListener("click", addFileInput, null);
131 }
132 // When renaming, select basename part
133 for (el of collectElementsByAttr("input", "class", "mv")) {
134 el.addEventListener("focus", function(ev) {
135 var i = ev.target;
136 if (i) {
137 i.setSelectionRange(0, i.value.lastIndexOf("."));
138 }
139 });
140 }
141 }
142 function initTextarea() {
143 var te = collectElementsByAttr("textarea", "name", "text");
144 if (!te || !te[0]) return;
145 te[0].addEventListener("keydown", helpMarkdown, false);
146 }
147 function initBlogs() {
148 // Auto-complete #xxxx
149 var check = collectElementsByAttr("input", "name", "notifyto");
150 if (check)
151 for (let i of check) {
152 i.addEventListener("click", insertRedirect, null);
153 }
154 for (let i of document.getElementsByTagName("a"))
155 if (i.getAttribute("href").match(/^#[0-9]+$/))
156 if (RegExp.lastMatch == i.innerHTML)
157 i.addEventListener("click", insertRedirect, null)
158 }
159 function initGrpAction() {
160 var rev = document.getElementById("reverse");
161 if (!rev) return; // Is not grpAction page
162 if (rev.tagName.match(/span/i)) {
163 rev.textContent = " 反転 ";
164 rev.addEventListener("click", reverseChecks, null);
165 }
166 var emailbtn = document.getElementById("email");
167 emailbtn.addEventListener("click", function(ev){
168 // Enlarge box and Select user's checkbox
169 if (!ev.target.checked) return;
170 var x = collectElementsByAttr("div", "class", "foldtabs");
171 if (x && x[0] && x[0].style) {
172 x[0].style.height = "10em";
173 }
174 let myuid = document.getElementById("myuid");
175 if (myuid) {
176 let usel = collectElementsByAttr("input", "name", "usel");
177 if (usel) {
178 for (u of usel) {
179 if (u.value == myuid.value)
180 u.checked = true;
181 }
182 }
183 }
184 }, null);
185 var teamsel = document.getElementById("selteam");
186 if (teamsel) {
187 var usel, p, team;
188 // Select all members of the team
189 teamsel.addEventListener("change", function(ev) {
190 var teamname = teamsel.value,
191 selected = new RegExp('(^| )'+teamname+"($|,)");
192 usel = collectElementsByAttr("input", "name", "usel");
193 if (!usel) return;
194 for (u of usel) {
195 p = u.parentNode; // should be label
196 if (!p) continue;
197 if (teamname == "TEAM") { // Reset all checks
198 u.checked = false; // when "TEAM" is selected
199 } else {
200 p = p.parentNode.parentNode;// should be tr
201 team = nthChildOf(p, 3, "td")
202 if (team && team.textContent
203 && team.textContent.match(selected)) {
204 u.checked = true;
205 }
206 }
207 }
208 }, null);
209 }
210 }
211 function init() {
212 initGrpAction();
213 initBlogs();
214 initFileInput();
215 initTextarea();
216 }
217 document.addEventListener('DOMContentLoaded', init, null);
218 })();