yuuji@889: // 愛 yuuji@586: (function (){ yuuji@898: var isOlderJS; // Set in init(); yuuji@898: var hasTouchPad = yuuji@898: (navigator.maxTouchPoints && navigator.maxTouchPoints >0); yuuji@898: var myurl = document.URL, yuuji@898: mypath = myurl.substring(myurl.lastIndexOf("/")); yuuji@898: var art_m_list = []; yuuji@898: if (mypath.match(/(.*)\/(.*)/)) { yuuji@898: mypath = RegExp.$2; yuuji@898: mypath = mypath.substring(0, mypath.lastIndexOf("?")); yuuji@898: //alert("mypath="+mypath); yuuji@898: } yuuji@667: function collectElementsByAttr(elm, attr, val) { yuuji@586: var e = document.getElementsByTagName(elm); yuuji@586: if (!e) return null; yuuji@586: var list = []; yuuji@586: for (var i of e) { yuuji@667: if (i.getAttribute(attr) == val) yuuji@586: list.push(i) yuuji@586: } yuuji@586: return list; yuuji@586: } yuuji@675: function nthChildOf(parent, n, elem) { // Return Nth child of type ELEM yuuji@675: // N begins with 1 yuuji@675: var i=0; yuuji@675: var le = elem.toLowerCase(); yuuji@675: for (var c of parent.childNodes) { yuuji@675: if (!c.tagName) continue; yuuji@675: if (c.tagName.toLowerCase() == le) { yuuji@675: if (++i >= n) return c; yuuji@675: } yuuji@675: } yuuji@675: return null; yuuji@675: } yuuji@586: function insertRedirect(e) { yuuji@586: var articleId, textarea = document.getElementById("text"); yuuji@586: var p = e.target, checked = p.checked; yuuji@586: while (p = p.parentNode) yuuji@586: if (p.nodeName.match(/^td$/i)) break; yuuji@586: if (!p) return; yuuji@586: while (p = p.nextSibling) yuuji@586: if (p.nodeName.match(/^td$/i)) break; yuuji@586: if (!p) return; yuuji@586: articleId = p.getAttribute("id"); yuuji@586: if (textarea && articleId) { yuuji@586: var tv = textarea.value, lines; yuuji@586: if (tv) yuuji@586: lines = tv.split("\n"); yuuji@586: else yuuji@586: lines = [""]; yuuji@586: var re = new RegExp("[, ]*#"+articleId+"(?![0-9])"); yuuji@590: checked = (p.nodeName.match(/^input$/) yuuji@590: ? p.checked // checkbox obeys its status yuuji@590: : !lines[0].match(re)) // a-elment toggles redirection yuuji@586: if (checked) { yuuji@586: if (!lines[0].match(re)) { yuuji@586: var re2 = new RegExp(/>#[#0-9, ]+[0-9]/); yuuji@586: if (lines[0].match(re2)) yuuji@586: lines[0] = lines[0].replace( yuuji@586: re2, '$&, '+'#'+articleId); yuuji@586: else { yuuji@586: if (lines[0] > "") lines[0] = " "+lines[0]; yuuji@586: lines[0] = ">#"+articleId+lines[0]; yuuji@586: } yuuji@586: } yuuji@586: } else { // Remove #xxxxx yuuji@586: if (lines[0].match(/^>#[0-9 ,]+#/)) // 2 or more #id's yuuji@586: lines[0] = lines[0].replace( yuuji@586: new RegExp("^>#"+articleId+"[ ,]*"), ">").replace( yuuji@586: new RegExp("[ ,]*#"+articleId), ""); yuuji@586: else { yuuji@586: lines[0] = lines[0].replace( yuuji@586: new RegExp(">#"+articleId+"[ ,]*"), ""); yuuji@586: } yuuji@586: } yuuji@586: lines[0] = lines[0].replace(/^> *$/, ''); yuuji@586: textarea.value = lines.join("\n"); yuuji@586: } yuuji@586: } yuuji@898: function registPjaxViewers(aHrefList) { yuuji@898: let apos=art_m_list.length; yuuji@898: for (let a of aHrefList) { yuuji@898: let href = a.getAttribute("href"); yuuji@898: let localvar = apos; yuuji@898: let td = a.parentNode, yuuji@898: tr = td.parentNode, yuuji@898: id = td.id, yuuji@898: text = td.textContent, yuuji@898: author = tr.getElementsByTagName("a"); yuuji@898: if (author) author = author[0].getAttribute("title"); yuuji@898: if (href.match(/\?showattc\+article_m\+([0-9+])/)) { yuuji@898: if (td.innerHTML.match(/x読み取り不可/)) { yuuji@898: a.removeAttribute("href"); yuuji@898: continue; yuuji@898: } yuuji@898: let url = RegExp.lastMatch; yuuji@898: // console.log("pjaxView(e, "+href+", "+apos+")"); yuuji@898: a.addEventListener("click", function(e) { yuuji@898: // Shoud use closure local variable: localvar yuuji@898: pjaxView(e, href, localvar); yuuji@898: }, false); yuuji@898: apos++; yuuji@898: art_m_list.push({ yuuji@898: url: href, id: id, author: author, text: text yuuji@898: }); yuuji@898: } yuuji@898: } yuuji@898: } yuuji@906: function registInsertDirect(aHrefList) { yuuji@906: for (i of aHrefList) yuuji@906: if (i.getAttribute("href").match(/^#[0-9]+$/)) yuuji@906: if (RegExp.lastMatch == i.innerHTML) yuuji@906: i.addEventListener("click", insertRedirect, false) yuuji@906: } yuuji@898: var ajaxSubmit; yuuji@898: function replAddNews(newtable) { yuuji@898: let newids = [], idlist=[]; yuuji@898: let getArticleID = function (td) { yuuji@898: return parseInt(td.parentNode.getElementsByTagName("td")[1].id); yuuji@898: } yuuji@898: for (let i of newtable.querySelectorAll("td.repl")) yuuji@898: newids.push(i); yuuji@898: newids = newids.sort((a,b)=> { yuuji@898: return (getArticleID(a) - getArticleID(b)); yuuji@898: }); yuuji@898: for (i of newids) yuuji@898: idlist.push(getArticleID(i)); yuuji@898: console.log("IDList="+idlist.join()); yuuji@900: let cnt=0, ntr; yuuji@898: let current = collectElementsByAttr("td", "class", "repl"), yuuji@898: ncur=0, n, icur=0, o, oid, nid, otr; yuuji@898: current = document.querySelectorAll('td[class="repl"]'); yuuji@898: let last=current[current.length-1], yuuji@898: tbody = last.parentNode.parentNode; yuuji@906: let addEventsToNewTr = function(tr) { yuuji@906: let td = tr.getElementsByTagName("td"), yuuji@906: td0 = td[0], td1 = td[1]; yuuji@906: td0.classList.add("new"); yuuji@906: registInsertDirect(td0.querySelectorAll("a[href]")); yuuji@906: registPjaxViewers(td1.querySelectorAll("a[href]")); yuuji@906: } yuuji@898: // Now reconstruct articles with merge-sort like method yuuji@898: outer: for (; ncur= nid) { yuuji@906: addEventsToNewTr(ntr); yuuji@898: tbody.insertBefore(ntr, otr); yuuji@898: if (oid==nid) otr.remove(); yuuji@898: cnt++; yuuji@898: continue outer; yuuji@898: } yuuji@898: } yuuji@898: // Append absolutely new articles. yuuji@898: ntr = n.parentNode; yuuji@906: addEventsToNewTr(ntr) yuuji@898: tbody.appendChild(ntr); yuuji@898: ntr.classList.add("dissolving"); yuuji@900: let localntr = ntr; yuuji@898: setTimeout(() => { yuuji@900: localntr.classList.remove("dissolving"); yuuji@900: localntr.classList.add("emerging"); yuuji@898: }, 100); yuuji@898: cnt++; yuuji@898: } yuuji@900: ajaxSubmit.textContent = ajaxSubmit.back; yuuji@898: ajaxSubmit.disabled = false; yuuji@898: console.log("Update "+cnt+"rows"); yuuji@901: if (cnt>0 && ntr.scrollIntoView) { yuuji@901: let option = {behavior: "smooth"}; yuuji@901: if (!isOlderJS) option.block = "center"; yuuji@900: try { // Scroll to last updated row yuuji@901: ntr.scrollIntoView(option); yuuji@901: } catch (e1) {} yuuji@901: } yuuji@898: return cnt; yuuji@898: } yuuji@898: yuuji@898: function warnFileSize(form) { yuuji@898: let szmax = form.querySelector('input[name="filesize_max"]').value; yuuji@898: if (!szmax || szmax=="") return; yuuji@898: szmax = parseInt(szmax); yuuji@898: if (szmax <= 0) return; yuuji@898: // szmax = 10000 yuuji@898: let ng = "", rcval=false, fileexists=false; yuuji@898: for (let f of form.querySelectorAll('input[type="file"]')) { yuuji@898: let thiserr = false yuuji@898: for (let i of f.files) { yuuji@898: fileexists = true; yuuji@898: let fn = i.name, sz = i.size; yuuji@898: console.log("max="+szmax+", fn="+fn+", sz="+sz); yuuji@898: if (sz > szmax) { yuuji@898: thiserr = true; yuuji@898: ng += ((ng>"" ? ", " : "")+fn) yuuji@898: } yuuji@898: } yuuji@898: thiserr ? f.classList.add("warnbg") : f.classList.remove("warnbg"); yuuji@898: } yuuji@898: if (ng>"") { yuuji@898: rcval = "File-size Limit Error: "+ng+"\n"+ yuuji@898: "Should be less than "+szmax+"bytes.\n"+ yuuji@898: szmax+"バイト未満にしてください" yuuji@898: alert(rcval); yuuji@898: } yuuji@898: if (form.text.value == "") { yuuji@898: let w; yuuji@898: if (fileexists) yuuji@898: w = "Fill the text area\n" + yuuji@898: "添付したファイルに関する説明を入れてください。"; yuuji@898: else yuuji@898: w = "Enter your comment!\n何か書き込んでね!"; yuuji@898: alert(w); yuuji@898: rcval = (rcval || w); yuuji@898: form.text.classList.add("warnbg"); yuuji@898: setTimeout(() => {form.text.classList.remove("warnbg");}, 2000) yuuji@898: } yuuji@898: return rcval; yuuji@898: } yuuji@898: function ajaxPost(e) { yuuji@898: e.preventDefault(); yuuji@898: let rowid; yuuji@898: if (!myurl.match(/replyblog\+([0-9]+)/)) return; yuuji@898: rowid = RegExp.$1 yuuji@898: let myform = document.querySelector("form.replyblog"); yuuji@898: let data = new FormData(myform), yuuji@898: fetchtime = data.get("fetchtime"); yuuji@898: if (!fetchtime || fetchtime=="") return; yuuji@898: ///*XX*/fetchtime = "2020-06-14T00:00:00";data.set("fetchtime", fetchtime) yuuji@900: yuuji@900: ajaxSubmit = e.target; yuuji@900: ajaxSubmit.back = ajaxSubmit.textContent; yuuji@900: if (ajaxSubmit.id == "reload") { yuuji@900: ajaxSubmit.textContent = "更新中" yuuji@900: data.set("text", "") yuuji@900: } else { yuuji@900: if (warnFileSize(myform)) return; yuuji@900: ajaxSubmit.textContent = "送信中"; yuuji@900: } yuuji@900: ajaxSubmit.blur(); yuuji@900: ajaxSubmit.disabled = true; yuuji@898: let act = mypath+"?blog_fetch+"+rowid+"+f:"+fetchtime; yuuji@898: yuuji@898: function respUpdate(tbody) { yuuji@898: let div = document.createElement("div"), form, newform; yuuji@898: try { yuuji@898: div.innerHTML = tbody; yuuji@898: form = div.querySelector("form"); yuuji@898: } catch (er) { yuuji@898: alert("Cannot parse fetch data"); yuuji@898: return; yuuji@898: } yuuji@898: let update = replAddNews(form); yuuji@898: let dispelem = myform.querySelector("textarea").parentNode; yuuji@898: newform = new FormData(form); yuuji@900: if (data.get("text") > "") { // Called by submit button yuuji@900: myform.reset(); yuuji@900: // myform.text.value = ''; yuuji@900: } yuuji@898: myform.fetchtime.value = newform.get("fetchtime"); yuuji@898: myform.id.value = newform.get("id"); yuuji@898: if (update && update > 0) { yuuji@898: let s = update + " new article" + yuuji@898: (update>1 ? "s" : "") + " posted"; yuuji@898: dispInfoMomentary(s, dispelem); yuuji@898: } yuuji@898: } yuuji@898: fetch(act, { yuuji@898: method: "POST", body: data, yuuji@898: credentials: "include" // For older firefox yuuji@898: }).then((resp) => { yuuji@898: return resp.text(); yuuji@898: }).then((tbody) => { yuuji@898: respUpdate(tbody); yuuji@898: }) yuuji@898: } yuuji@898: function pjaxView(ev, url, mynum) { yuuji@898: ev.preventDefault(); yuuji@898: let box = document.createElement("div") yuuji@898: box.setAttribute("class", "pjaxview"); yuuji@898: let p1 = document.createElement("p"), yuuji@898: bt = document.createElement("button"), yuuji@898: sl = document.createElement("button"), yuuji@898: sr = document.createElement("button"), yuuji@898: loading = document.createElement("span"), yuuji@898: info = document.createElement("p"); yuuji@898: info1 = document.createElement("span"); yuuji@898: info2 = document.createElement("span"); yuuji@898: iframe = document.createElement("iframe"); yuuji@898: var curpos = mynum; yuuji@898: var historyBase = history.length; yuuji@898: yuuji@898: function _setPjaxCurposInfo() { yuuji@898: let len = art_m_list.length; yuuji@898: let cur = art_m_list[curpos] yuuji@898: info1.textContent = (1+curpos)+" of "+len+" article #"+cur.id+ yuuji@898: (cur.author ? " by "+cur.author : "") + ":"; yuuji@898: info2.textContent = cur.text.trim(); yuuji@898: info2.setAttribute("class", "border textdigest"); yuuji@898: } yuuji@898: function _resetPjax() { yuuji@898: // All we can do surely is to back 1 page, yuuji@898: // because we cannot move to desirable entry of history list. yuuji@898: history.back(); yuuji@898: } yuuji@898: function setSwipeAct(iframe) { yuuji@898: // We cannot use DOMContentLoaded nor iframe.contentWindow here. yuuji@898: // PDF.js does not construct contentWindow...? yuuji@898: iframe.addEventListener("load", () => { yuuji@898: loading.classList.remove("loading"); yuuji@898: if (!hasTouchPad) return; yuuji@898: let ifm = iframe.contentDocument; yuuji@898: let startX, moveX, thresh = 100; yuuji@898: ifm.addEventListener("touchstart", (e) => { yuuji@898: e.preventDefault(); yuuji@898: startX = e.touches[0].pageX; yuuji@898: }, false); yuuji@898: ifm.addEventListener("touchmove", (e) => { yuuji@898: e.preventDefault(); yuuji@898: moveX = e.touches[0].pageX; yuuji@898: }, false); yuuji@898: ifm.addEventListener("touchend", (e) => { yuuji@898: if (startX < moveX && startX + thresh < moveX) { yuuji@898: switchTo(e, -1); yuuji@898: } else if (startX > moveX && startX - thresh > moveX) { yuuji@898: switchTo(e, +1); yuuji@898: } yuuji@898: }, false); yuuji@898: }, false); yuuji@898: yuuji@898: } yuuji@898: function switchTo(e, direction) { yuuji@898: e.preventDefault(); yuuji@898: let len = art_m_list.length, cur, newpos, url; yuuji@898: newpos = (curpos+len+direction)%len; yuuji@898: if (curpos == newpos) return; // No need to switch to same one yuuji@898: curpos = newpos; yuuji@898: cur = art_m_list[curpos]; yuuji@898: url = cur.url; yuuji@898: // We should remove iframe once to preserve history Object yuuji@898: // https://inthetechpit.com/2019/04/20/update-iframe-without-affecting-browser-history/ yuuji@898: let parent = iframe.parentNode; yuuji@898: // alert("D = "+direction); yuuji@898: iframe.remove(); yuuji@898: parent.appendChild(iframe); yuuji@898: try { yuuji@898: loading.classList.add("loading"); yuuji@898: iframe.src = url; yuuji@898: // iframe.contentDocument.location.replace(url); yuuji@898: // location.replace cannot be used because PDF viewer.js yuuji@898: // does not have iframe.contentDocument yuuji@898: } catch (err) { yuuji@898: alert("Cannot load "+src+" : "+err.name); yuuji@898: } yuuji@898: _setPjaxCurposInfo(); yuuji@898: setSwipeAct(iframe); yuuji@898: } yuuji@898: function switchToByKey(e) { yuuji@898: // alert("KEY="+e.key); yuuji@898: switch (e.key) { yuuji@898: case "ArrowLeft": yuuji@898: switchTo(e, -1); break; yuuji@898: case "ArrowRight": yuuji@898: switchTo(e, +1); break; yuuji@898: case "Escape": yuuji@898: history.back(); yuuji@898: } yuuji@898: } yuuji@898: //

yuuji@898: // yuuji@898: //

info1 info2

yuuji@898: // yuuji@898: //
yuuji@898: // ==> [ << ][Dissmiss][ >> ] yuuji@898: // ==> ## of ## article #xxx by AUTHOR yuuji@898: sl.textContent = " << "; yuuji@898: sr.textContent = " >> "; yuuji@898: sl.addEventListener("click", (e) => {switchTo(e, -1);}); yuuji@898: sr.addEventListener("click", (e) => {switchTo(e, +1);}); yuuji@898: sl.setAttribute("title", "to="+(mynum-1)); yuuji@898: sr.setAttribute("title", "to="+(mynum+1)); yuuji@898: document.body.appendChild(box); yuuji@898: bt.textContent = "Click to dismiss / もどる"+mynum; yuuji@898: yuuji@898: box.appendChild(p1); yuuji@898: p1.appendChild(sl); p1.appendChild(bt); p1.appendChild(sr); yuuji@898: p1.appendChild(loading); yuuji@898: info.appendChild(info1); info.appendChild(info2); yuuji@898: loading.textContent=" Loading..."; yuuji@898: loading.classList.add("hidden"); yuuji@898: loading.classList.add("loading"); yuuji@898: box.appendChild(info); yuuji@898: iframe.src = url; yuuji@898: yuuji@898: document.addEventListener("keydown", switchToByKey); yuuji@898: //box.addEventListener("click", (e) => {_resetPjax();}); yuuji@898: bt.addEventListener("click", (e) => {_resetPjax();}); yuuji@898: // dp.addEventListener("click", (e) => {_resetPjax();}); yuuji@898: info.addEventListener("click", (e) => {_resetPjax();}); yuuji@898: box.appendChild(iframe); yuuji@898: yuuji@898: setSwipeAct(iframe); yuuji@898: yuuji@898: _setPjaxCurposInfo(); yuuji@898: bt.focus(); yuuji@898: setTimeout(() => {box.classList.add("pjaxview2");}, 10); yuuji@898: // Finally update history stack yuuji@898: if (history.pushState) { yuuji@898: let h = location.href.replace(/#.*/, '')+"#pjaxview"; yuuji@898: history.pushState({url: h}, null, h); yuuji@898: window.addEventListener("popstate", (e) => { yuuji@898: if (box) { yuuji@898: box.remove(); box = null; yuuji@898: } yuuji@898: }, false); yuuji@898: } yuuji@898: } yuuji@659: function reverseChecks() { yuuji@667: var names = collectElementsByAttr("input", "name", "usel"); yuuji@659: for (let u of names) { yuuji@659: u.checked = !u.checked; yuuji@659: } yuuji@659: } yuuji@852: function renumberOL(str, start) { yuuji@852: var stra = str.split("\n"); yuuji@852: for (var i=1; i")+1); yuuji@837: i.insertAdjacentHTML("afterend", newi) yuuji@898: i.nextSibling.nextSibling.addEventListener('change', () => { yuuji@898: // next==br next.next==input[type=file] yuuji@898: warnFileSize(document.forms[0]); yuuji@898: }); yuuji@837: } yuuji@837: } yuuji@837: } yuuji@837: function initFileInput() { // Multiplies "input type=file" yuuji@837: var el, morefile = document.getElementById("morefile"); yuuji@837: if (morefile) { yuuji@837: for (el of collectElementsByAttr("input", "name", "image")) { yuuji@837: el.addEventListener("change", function(ev) { yuuji@837: if (ev.target.value > "" && ev.target.files.length == 1) yuuji@837: morefile.style.visibility = "visible"; yuuji@837: // No need to hide again, sure? yuuji@837: }); yuuji@837: } yuuji@837: morefile.addEventListener("click", addFileInput, null); yuuji@837: } yuuji@837: // When renaming, select basename part yuuji@837: for (el of collectElementsByAttr("input", "class", "mv")) { yuuji@837: el.addEventListener("focus", function(ev) { yuuji@837: var i = ev.target; yuuji@837: if (i) { yuuji@837: i.setSelectionRange(0, i.value.lastIndexOf(".")); yuuji@837: } yuuji@837: }); yuuji@837: } yuuji@837: } yuuji@846: function initTextarea() { yuuji@846: var te = collectElementsByAttr("textarea", "name", "text"); yuuji@846: if (!te || !te[0]) return; yuuji@846: te[0].addEventListener("keydown", helpMarkdown, false); yuuji@846: } yuuji@659: function initBlogs() { yuuji@837: // Auto-complete #xxxx yuuji@900: let i, check = collectElementsByAttr("input", "name", "notifyto"); yuuji@586: if (check) yuuji@900: for (i of check) { yuuji@898: i.addEventListener("click", insertRedirect, false); yuuji@586: } yuuji@906: registInsertDirect(document.querySelectorAll("a[href]")); yuuji@900: for (i of document.querySelectorAll('input#c[value="送信"]')) { yuuji@900: let b = document.createElement("button"); yuuji@900: b.textContent = "送信!"; yuuji@898: console.log("b="+b+", tc="+b.textContent); yuuji@898: b.addEventListener("click", ajaxPost, false); yuuji@898: // i.insertAdjacentElement('afterend', b); yuuji@900: b.id = i.id; yuuji@900: i.parentNode.replaceChild(b, i); yuuji@900: i.remove(); yuuji@898: } yuuji@900: i = document.getElementById("reload"); yuuji@900: if (i) i.addEventListener("click", ajaxPost, false); yuuji@902: for (i of document.querySelectorAll('input[type="file"]')) { yuuji@902: i.addEventListener('change', (e) => { yuuji@902: warnFileSize(document.forms[0]); yuuji@898: }, false) yuuji@898: } yuuji@898: // Hack article_m links yuuji@898: registPjaxViewers(document.querySelectorAll("a[href]")); yuuji@586: } yuuji@659: function initGrpAction() { yuuji@659: var rev = document.getElementById("reverse"); yuuji@667: if (!rev) return; // Is not grpAction page yuuji@667: if (rev.tagName.match(/span/i)) { yuuji@659: rev.textContent = " 反転 "; yuuji@659: rev.addEventListener("click", reverseChecks, null); yuuji@659: } yuuji@667: var emailbtn = document.getElementById("email"); yuuji@667: emailbtn.addEventListener("click", function(ev){ yuuji@675: // Enlarge box and Select user's checkbox yuuji@667: if (!ev.target.checked) return; yuuji@673: var x = collectElementsByAttr("div", "class", "foldtabs"); yuuji@673: if (x && x[0] && x[0].style) { yuuji@673: x[0].style.height = "10em"; yuuji@673: } yuuji@667: let myuid = document.getElementById("myuid"); yuuji@667: if (myuid) { yuuji@667: let usel = collectElementsByAttr("input", "name", "usel"); yuuji@667: if (usel) { yuuji@667: for (u of usel) { yuuji@667: if (u.value == myuid.value) yuuji@667: u.checked = true; yuuji@667: } yuuji@667: } yuuji@667: } yuuji@667: }, null); yuuji@675: var teamsel = document.getElementById("selteam"); yuuji@675: if (teamsel) { yuuji@675: var usel, p, team; yuuji@675: // Select all members of the team yuuji@675: teamsel.addEventListener("change", function(ev) { yuuji@675: var teamname = teamsel.value, yuuji@676: selected = new RegExp('(^| )'+teamname+"($|,)"); yuuji@675: usel = collectElementsByAttr("input", "name", "usel"); yuuji@675: if (!usel) return; yuuji@675: for (u of usel) { yuuji@675: p = u.parentNode; // should be label yuuji@675: if (!p) continue; yuuji@675: if (teamname == "TEAM") { // Reset all checks yuuji@675: u.checked = false; // when "TEAM" is selected yuuji@675: } else { yuuji@675: p = p.parentNode.parentNode;// should be tr yuuji@675: team = nthChildOf(p, 3, "td") yuuji@675: if (team && team.textContent yuuji@675: && team.textContent.match(selected)) { yuuji@675: u.checked = true; yuuji@675: } yuuji@675: } yuuji@675: } yuuji@675: }, null); yuuji@675: } yuuji@659: } yuuji@893: function dispInfoMomentary(msg, elem) { yuuji@893: // Momentarily display MSG in tooltip-baloon relative to ELEM element. yuuji@893: let help = document.createElement("p"); yuuji@893: elem.style.position = 'relative'; yuuji@893: elem.style.overflow = 'visible'; yuuji@893: help.setAttribute("class", "info-tooltip"); yuuji@893: help.innerHTML = msg; yuuji@893: elem.appendChild(help); yuuji@893: setTimeout(() => { yuuji@893: help.classList.add("dissolving"); yuuji@893: setTimeout(() => help.remove(), 3000); yuuji@893: }, 1000); yuuji@893: } yuuji@889: function initGrphome() { yuuji@889: console.log("initGrphome"); yuuji@894: // (1)Setup Frozen State Changing Button yuuji@893: var ja = navigator.language.match(/ja/i); yuuji@889: yuuji@889: function toggleFrozen(e, rowid) { yuuji@889: let tgt = mypath+"?blog_setfrozen+"+rowid; yuuji@893: let td = e.target.parentNode; yuuji@893: let tr = td.parentNode; yuuji@889: fetch(tgt, { yuuji@889: method: "POST", yuuji@889: headers: {'Content-Type': 'text/html; charset=utf-8'}, yuuji@898: credentials: "include" yuuji@889: }).then(function(resp) { yuuji@889: return resp.text(); yuuji@889: }).then(function(tbody) { yuuji@889: try { yuuji@889: var json = JSON.parse(tbody); yuuji@889: } catch (e) { yuuji@889: return; yuuji@889: } yuuji@893: let state = json.state, newstate, info; yuuji@889: if (json.alert) { yuuji@889: alert(json.alert) yuuji@889: } yuuji@889: if (state.match(/frozen/i)) { yuuji@889: newstate = "凍結"; yuuji@893: info = ja ? newstate+"に設定しました" : 'Set Frozen'; yuuji@889: } else { yuuji@889: newstate = null; yuuji@893: info = ja ? '稼動に設定しました' : 'Set Running'; yuuji@889: } yuuji@889: tr.setAttribute("class", newstate); yuuji@893: dispInfoMomentary(info, td); yuuji@889: }); yuuji@889: } yuuji@894: let btn = document.querySelectorAll("button.toggle-frozen"); yuuji@889: for (let b of btn) { yuuji@889: let rowid = null; yuuji@893: let td=b.parentNode, tr = td.parentNode, fr, ru; yuuji@893: ru = ja ? "動" : "Running"; yuuji@893: fr = ja ? "凍" : "Frozen"; yuuji@893: b.setAttribute('frozen-marker', fr); yuuji@893: b.setAttribute('running-marker', ru); yuuji@889: for (let a of tr.querySelectorAll("a[href]")) { yuuji@889: if (a.getAttribute("href").match(/\?replyblog\+([0-9]+)/)) { yuuji@889: rowid = parseInt(RegExp.$1); yuuji@889: break; yuuji@889: } yuuji@889: } yuuji@889: if (rowid && rowid>0) { yuuji@889: b.addEventListener("click", function(e) { yuuji@889: if (!btn) return; yuuji@889: toggleFrozen(e, rowid); yuuji@889: }, false); yuuji@889: b.setAttribute("title", "稼動/凍結をその場で切り替えます\n\ yuuji@889: Toggle Running/Frozen ("+rowid+")"); yuuji@889: } yuuji@889: } yuuji@894: // (2)Setup Column Collapse Button yuuji@894: // INCOMPLETE: Cannot restore original state, but it's enough... yuuji@894: function toggleColmnWidth(th) { yuuji@894: let tbl = document.querySelector("table.dumpblogs"); yuuji@894: let colname = th.textContent, newwidth; yuuji@894: if (th.style.width) { yuuji@894: newwidth = null yuuji@894: // https://developer.mozilla.org/ja/docs/Web/CSS/table-layout yuuji@894: tbl.style.tableLayout = 'auto'; yuuji@894: tbl.style.width = null; yuuji@894: } else { yuuji@894: newwidth = "2em"; yuuji@894: tbl.style.tableLayout = 'fixed'; yuuji@894: tbl.style.width = '100%'; yuuji@894: } yuuji@894: th.style.width = newwidth; yuuji@894: th.style.overflow = "hidden"; yuuji@894: for (let td of document.querySelectorAll("td."+colname)) { yuuji@894: console.log(td.tagName); yuuji@894: td.style.width = newwidth; yuuji@894: console.log(td.style.width); yuuji@894: } yuuji@894: } yuuji@894: let row1 = document.querySelector("table.dumpblogs tr:first-child"); yuuji@894: if (row1) { yuuji@894: let heads = row1.querySelectorAll("th"); yuuji@894: for (let h of heads) { yuuji@894: h.addEventListener("click", function(e) { yuuji@894: toggleColmnWidth(h); yuuji@894: }, false); yuuji@894: h.setAttribute("title", "Click to shrink these columns"); yuuji@894: } yuuji@894: } yuuji@889: } yuuji@659: function init() { yuuji@898: isOlderJS = !("insertAdjacentElement" in document.body); yuuji@659: initGrpAction(); yuuji@659: initBlogs(); yuuji@837: initFileInput(); yuuji@846: initTextarea(); yuuji@889: initGrphome(); yuuji@659: } yuuji@586: document.addEventListener('DOMContentLoaded', init, null); yuuji@586: })();