diff --git "a/\1331-10\135\346\234\254\350\254\233\347\276\251\04316 \345\234\260\347\220\206\343\201\250\346\203\205\345\240\261 _JDs4 - JD-Chokai.html" "b/\1331-10\135\346\234\254\350\254\233\347\276\251\04316 \345\234\260\347\220\206\343\201\250\346\203\205\345\240\261 _JDs4 - JD-Chokai.html"
new file mode 100644
index 0000000..dab99be
--- /dev/null
+++ "b/\1331-10\135\346\234\254\350\254\233\347\276\251\04316 \345\234\260\347\220\206\343\201\250\346\203\205\345\240\261 _JDs4 - JD-Chokai.html"
@@ -0,0 +1,191 @@
+
+
+
+
+
+[1-10]本講義#16 地理と情報
+|JDs4 - JD-Chokai
+
+
+
+
+
+
+
+[1-10]本講義#16 地理と情報
+
+
+
+
+
+
+Driven by
+s4
+©2015-2024 by
+yuuji
+
+
+
Loading...
4 of 5 article #3747 by c122132:サンプルプログラム2
+講義前にダウンロードしておきましょう。kensaku.csv(198B)[Direct]
+kensaku2.rb(491B)[Direct]
\ No newline at end of file
diff --git "a/\1331-10\135\346\234\254\350\254\233\347\276\251\04316 \345\234\260\347\220\206\343\201\250\346\203\205\345\240\261 _JDs4 - JD-Chokai_files/229-QRyobichokai.jpeg" "b/\1331-10\135\346\234\254\350\254\233\347\276\251\04316 \345\234\260\347\220\206\343\201\250\346\203\205\345\240\261 _JDs4 - JD-Chokai_files/229-QRyobichokai.jpeg"
new file mode 100644
index 0000000..a087361
--- /dev/null
+++ "b/\1331-10\135\346\234\254\350\254\233\347\276\251\04316 \345\234\260\347\220\206\343\201\250\346\203\205\345\240\261 _JDs4 - JD-Chokai_files/229-QRyobichokai.jpeg"
Binary files differ
diff --git "a/\1331-10\135\346\234\254\350\254\233\347\276\251\04316 \345\234\260\347\220\206\343\201\250\346\203\205\345\240\261 _JDs4 - JD-Chokai_files/S_blueimpulse.jpg" "b/\1331-10\135\346\234\254\350\254\233\347\276\251\04316 \345\234\260\347\220\206\343\201\250\346\203\205\345\240\261 _JDs4 - JD-Chokai_files/S_blueimpulse.jpg"
new file mode 100644
index 0000000..54e9658
--- /dev/null
+++ "b/\1331-10\135\346\234\254\350\254\233\347\276\251\04316 \345\234\260\347\220\206\343\201\250\346\203\205\345\240\261 _JDs4 - JD-Chokai_files/S_blueimpulse.jpg"
Binary files differ
diff --git "a/\1331-10\135\346\234\254\350\254\233\347\276\251\04316 \345\234\260\347\220\206\343\201\250\346\203\205\345\240\261 _JDs4 - JD-Chokai_files/S_flower04.jpg" "b/\1331-10\135\346\234\254\350\254\233\347\276\251\04316 \345\234\260\347\220\206\343\201\250\346\203\205\345\240\261 _JDs4 - JD-Chokai_files/S_flower04.jpg"
new file mode 100644
index 0000000..cd097de
--- /dev/null
+++ "b/\1331-10\135\346\234\254\350\254\233\347\276\251\04316 \345\234\260\347\220\206\343\201\250\346\203\205\345\240\261 _JDs4 - JD-Chokai_files/S_flower04.jpg"
Binary files differ
diff --git "a/\1331-10\135\346\234\254\350\254\233\347\276\251\04316 \345\234\260\347\220\206\343\201\250\346\203\205\345\240\261 _JDs4 - JD-Chokai_files/default.css" "b/\1331-10\135\346\234\254\350\254\233\347\276\251\04316 \345\234\260\347\220\206\343\201\250\346\203\205\345\240\261 _JDs4 - JD-Chokai_files/default.css"
new file mode 100644
index 0000000..45dc30b
--- /dev/null
+++ "b/\1331-10\135\346\234\254\350\254\233\347\276\251\04316 \345\234\260\347\220\206\343\201\250\346\203\205\345\240\261 _JDs4 - JD-Chokai_files/default.css"
@@ -0,0 +1,592 @@
+/*
+ * Default CSS definitions
+ */
+@media print {
+ div.blogcomment, div.blogcomment *, div.topmenu,
+ table.bloghead button {
+ display: none
+ }
+ a {text-decoration: none;}
+}
+body {background: #eff; margin: 2px; padding: 6px;}
+h2, h3, hr {clear: both;}
+*.warn {color: red;}
+*.warnbg {background: red;}
+*.hidden {visibility: hidden;}
+*.border {border: 1px solid #113;}
+div.topmenu {
+ margin: 0; padding: 0; width: 100%; height: 2em;
+}
+div.topmenu ul {width: 100%; position: fixed; z-index: 5; margin: 0;
+ margin: 0 auto;}
+div.topmenu ul li {
+ float: left; width: 18%;
+ background: rgba(68,255,102,0.8); border: #3e5 2px groove; margin: 0;
+ text-align: center; font-size: 80%; list-style: none;
+ box-shadow: #242 2px 3px 5px;
+ text-shadow: #fff 0px 0px 10px;
+}
+div.topmenu ul li.worldname {background: #eeeeff;}
+div.topmenu ul li:hover {background: #8fa;}
+div.topmenu ul a {text-decoration: none;}
+
+ldiv.topmenu + h1 {clear: both; margin-top: 3em;}
+pre.list {
+ overflow: auto; width: 96%; height: 40%; background: white;
+ border: 2px inset;
+}
+p.copyright {
+ border-top: 2px inset #555; text-align: right; clear: both;
+ font-size: 50%;
+}
+p.copyright a, a#reload {text-decoration: none;}
+
+td {padding-left: 0.5ex; padding-right: 0.5ex;}
+table.td2r td:nth-child(2) {text-align: right;}
+table.td3r td:nth-child(3) {text-align: right;}
+table.td3rr td:nth-child(n+3) {text-align: right;}
+table.td3evw th:nth-child(2n+4), span.textdigest {
+ background: white;
+}
+table.td4r td:nth-child(4) {text-align: right;}
+table.thl th {text-align: left;}
+span#reverse {background: white; padding: 0 0 0 0.4ex; border: outset;}
+
+table.form, table.b, table.b tr, table.b td, table.b th {
+ border: 1px solid black; border-collapse: collapse;
+}
+table.b, table.bloghead {
+ border-radius: 1ex; box-shadow: rgb(250,222,222) 1px 2px 3px;
+}
+td.warn {background: #fcc;}
+input[type="checkbox"][name="rm"]:checked ~ table {background: red;}
+input[type="checkbox"][name="rm"] ~ span {display: none;}
+input[type="checkbox"][name="rm"]:checked ~ span {display: inline;}
+
+input[type="radio"][value="replace"] + input.replace[type="file"] {
+ visibility: hidden;}
+input[type="radio"][value="replace"]:checked + input.replace[type="file"] {
+ visibility: visible;
+}
+button#morefile {visibility: hidden; background: #fe9;}
+label.admin span {border-bottom: 1px solid blue;}
+label.admin:after {content: "(ADMIN)"; color: red; text-decoration: none;}
+span.fileinput {
+ display: inline-block; height: 3.2ex;
+ border: 1px solid #4444; border-radius: 1ex;
+ position: relative; width: 16em; background: #e7e7ea; text-align: center;
+}
+span.fileinput input[type="file"] {
+ position: absolute; width: 100%; height: 100%; left: 0; top: 0;
+ padding: 0;
+}
+span.fileinput:hover {background: #efc;}
+/* keep/edit/rm action selector */
+input.action ~ input:not(.action), input.action ~ textarea {
+ display: none;
+}
+input.action[value="edit"]:checked ~ input[class="edit"],
+input.action[value="mv"]:checked ~ input[type="text"] {display: inline;}
+input.action[value="edit"]:checked ~ textarea {display: block;}
+input.action[value="edit"]:checked ~ span:not(.fileinput),
+input.action[value="mv"]:checked ~ span {display: none;}
+input.action[value="rm"]:checked ~ span {background: red;}
+label.confirm {display: none;}
+*.inline,
+input.action[value="rm"]:checked ~ label.confirm {
+ display: inline;
+}
+
+input.hidesub ~ input[type="submit"] {visibility: hidden;}
+input.hidesub:focus ~ input[type="submit"],
+p:active input[type="submit"]
+{visibility: visible;}
+input[type=text]:focus {background: #ffa;}
+
+form.replyblog {xxx-margin-bottom: 40%;}
+div.blogcomment {
+ position: fixed; bottom: 0; left: 0;
+ z-index: 2; background-color: rgba(250,222,222,0.6);
+}
+/* div.blogcomment textarea:focus {background: yellow;
+ position: fixed; top: 0; bottom: auto; } Need to consider narrow display */
+div.blogcomment * {opacity: 1.0;}
+table.bloghead, .bloghead tr, .bloghead td {
+ border: 1px solid black; border-collapse: collapse;
+ min-width: 30em;
+}
+table.bloghead tr.preface {
+ font-size: 150%; background: yellow; /* text-align: center; */
+ white-space: pre-wrap;
+}
+tr.preface em {color: navy; text-decoration: underline; padding-right: 0.3ex;}
+tr.preface strong {color: navy; background: #eea;}
+table.bloghead tr.frozen {
+ background: #ccf; border: blue thick solid; color: navy;
+}
+
+table.bloghead { /* Blog head - preface */
+ margin-bottom: 1em;
+ tr.preface {
+ h2, h3, h4, h5, h6 {display: inline-block;}
+ }
+}
+table.bloghead tr.preface :is(td :is(td, ul, ol), h1, h2, h3, h4, h5, h6),
+table.blog_replies :is(video, iframe, ul, ol, :is(tr, td) :is(ul, ol)) {
+ text-align: left; white-space: normal; margin: 1ex 0;
+}
+
+table.blog_replies, .blog_replies tr, .blog_replies td {
+ border: 1px solid #999; border-collapse: collapse;
+ white-space: pre-wrap;
+}
+table.blog_replies p.proficon {
+ float: right; margin: 0 1ex 0 0;
+}
+table.blog_replies+p.update_link {margin-top: 0; margin-bottom: 14em;}
+.blog_replies td.repl {
+ vertical-align: top; min-width: 30em; height: 3em;
+ max-width: 50em;
+}
+.blog_replies td.repl img {max-width: 30%;}
+td.repl h2, td.repl h3, td.repl h4 {
+ display: inline; /* Because td.repl's white space is pre-wrap */
+ /* text-shadow: blue 0px 1px; */
+}
+td.repl hr {display: inline-block; width: 95%; color: #cde}
+td.repl em {color: #a00; text-decoration: underline; padding-right: 0.3ex;}
+td.repl strong {color: white; background: #00a; padding: 0 0.5ex;}
+:root {--repl-heading-color: #a22;}
+td.repl h2:before {content: "■"; color: var(--repl-heading-color);}
+td.repl h3:before {content: "◆"; color: var(--repl-heading-color);}
+td.repl h4:before {content: "◎"; color: var(--repl-heading-color);}
+td.repl div.atall {
+ color: white; background: #66f; padding: 0 0.8ex;
+ display: inline-block; border-radius: 0.8ex;
+}
+td.repl.atall:first-line {font-size: 125%;}
+p.filter { /* is located after .blog_replies */
+ margin: 0; padding: 0 1ex;
+}
+body.general details { /* tricks */
+ padding-left: 1em; border: #4444 solid thin; background: #ffea;
+ border-radius: 0.5rem;
+ summary:after {
+ display: inline-block; border: solid 1px #999; border-radius: 0.3ex;
+ margin-left: 1em; padding: 0 2ex;
+ background: ivory;
+ content: "Open/クリックして詳細";
+ }
+ &[open] div.detail-content { /* Means body.general details[open] */
+ /* transition: cannot be used with [open] attribute */
+ animation: dispDetail 2s ease; padding-left: 1em;
+ }
+ &[open] summary:after {content: "Close/閉じる";}
+}
+@keyframes dispDetail {
+ from {background: #fff;}
+}
+/*
+ * INFO / WARN / ALERT info-box definitions here
+ */
+body.general {
+ div:is(.info, .warn, .alert) {
+ position: relative; border: 1px solid; border-radius: 0.8ex;
+ border-left-width: 1ex; padding: 1ex 3em; margin: 0 0.5ex;
+ display: flex; align-items: center;
+ flex-wrap: wrap; width: 85%; margin-right: 1em;
+ tr.preface & {width: 80%;}
+ }
+ div:is(.info, .warn, .alert)::before,
+ div:is(.info, .warn, .alert)::after {
+ position: absolute; content: "";
+ }
+ div:is(.info, .warn, .alert)::before {
+ left: 0.5em; width: 1.5em; height: 1.5em; border-radius: 50%;
+ }
+ div:is(.info, .warn, .alert)::after {
+ left: 0.84em; width: 0.5em; height: 0.3em;
+ }
+ div.info {
+ color: #141; border-color: green; background: #cfc8;
+ &::before {background: green;}
+ &::after {
+ background: transparent; border: white solid;
+ border-width: 0 0 5px 5px;
+ transform: translateY(-0.1em) rotate(-45deg);
+ }
+ }
+ div.warn {
+ color: #441; border-color: orange; background: #ffd8;
+ &::before {
+ background: white;
+ left: 0.5rem; border: 0.8em double orange;
+ width: 0px; height: 0px;
+ border-radius: 50%;
+ }
+ }
+ div.alert {
+ color: red; border-color: red; background: #fdd8;
+ &::before {
+ border: red 0.75em solid; border-radius: 0;
+ border-color: white red white red; width: 0; height: 0;
+ content: "";
+ }
+ &::after {display: none;}
+ }
+}
+
+/* table.blog_replies */
+.blog_replies td.repatt {min-width: 12em;}
+.blog_replies td.hideauthor, .hide {display: none;}
+table.blog_replies iframe {
+ width: 80%; min-height: 300px; max-width: 50em; max-height: 80vw;
+ padding: 0; border: 0;
+}
+table.blog_replies td.new { /* New Article from last visit */
+ background: white
+}
+table.mini, table.mini tr, table.mini th, table.mini td {
+ margin: 0; border-width: 0;
+ border-collapse: collapse;
+ vertical-align: top; width: auto; height: 1em;
+}
+table.mini th {background: #cee; white-space: pre;}
+table.mini tr {border-bottom: solid 1px #bcc;}
+table.mini th, table.mini td {
+ text-align: justify; border-right: 2px dotted #4848;
+}
+table.mini td, table.mini th {padding: 1px 0.5ex; min-width: 1em;}
+table.mini {margin-left: 1em; border-left: 2px solid #686;}
+table.mini th[colspan], table.mini td[colspan] {text-align: center;}
+table.mini th[rowspan], table.mini td[rowspan] {vertical-align: middle;}
+form.replyblog table s {
+ text-decoration: line-through #ff111180 0.3ex solid;
+}
+
+div.pjaxview, div.pjaxview2 {
+ position: fixed; top: 1ex; left: 0; width: 9vw; height: 9vh;
+ background: #ffffee; border: 1px double navy; border-radius: 2em;
+ z-index: 7;
+}
+div.pjaxview2 {
+ width: 100vw; height: 98vh; transition: 0.5s;
+}
+div.pjaxview iframe {
+ width: 98%; height: 90%; object-fit: scale-down;
+}
+div.pjaxview p {
+ padding: 0.5ex; text-align: left; margin: 0 2em;
+ white-space: nowrap; overflow: hidden;
+}
+div.pjaxview p button { font-size: large; padding: 0 1em;}
+div.pjaxview p button { background: #eeeee0; }
+div.pjaxview p button:focus { background: #fffff8; }
+
+/* "visibility: collapse" not working on chromium browser */
+div.noprofimg tr.profimg {visibility: collapse; display: none;}
+div.noprofimg tr:hover + tr.profimg, div.noprofimg tr:active + tr.profimg,
+div.noprofimg tr.profimg:hover, div.noprofimg tr.profimg:active {
+ visibility: visible; display: table-row;}
+
+/* Used for overlapping image */
+img.overlap {position: absolute; top: 40px; left: 50px; z-index: 2;}
+
+/* Used in user's home page */
+p.profimg {float: left; max-width: 50%; max-height: 400px;
+ overflow: hidden; margin: 0 1em 1ex;
+ padding: 0; border: white 1px solid; box-shadow: 2px 3px 4px
+ }
+p.profimg img {max-width: 400px;}
+div.home+* {clear: both;}
+body.grouphome p.groupimg {
+ float: right; margin: 0 1em 1ex;
+ overflow: hidden;}
+body.grouphome p.groupimg img {
+ max-width: 380px; max-height: 380px;}
+
+@media screen {
+ div.fold {margin-top: 1em; border-top: 1px solid black; padding-top: 1em;}
+ div.noborder {border: 0px; margin: 0;}
+ div.fold > div {
+ xxdisplay: none; max-height: 80%; overflow: auto;
+ height: 0px; opacity: 0; padding: 0 1ex;
+ }
+ div.fold input[type="checkbox"]:checked ~ div,
+ div.fold input[type="radio"]:checked ~ div {
+ display: block; background: #fadede;
+ height: auto; opacity: 1.0; transition: 1s;
+ }
+ input.fold + label + *.folded {opacity: 0; display: none; hight: 0;}
+ input[type="checkbox"].fold:checked + label + *.folded {
+ opacity: 1.0; transition: 2s;
+ }
+ input[type="checkbox"].fold:checked + label + div.folded {
+ display: block; hight: auto; transition: 2s;
+ }
+
+ /* fold2!! */
+ div.foldtabs {
+ position: relative; height: 5em; margin-top: 1em;
+ border-top: 1px solid black; padding-top: 1em;
+ }
+ div.foldtabs > div {
+ position: absolute; top: 2.5em; opacity: 0.0; background: pink;
+ margin: 2px; overflow: auto;
+ }
+ div.foldtabs input[type="radio"] {display: none;}
+ div.foldtabs input[type="radio"]:checked + label + div {
+ display: block; opacity: 1.0; transition: 0.2s; width: 100%;
+ margin: 0; z-index: 2;
+ }
+ div.foldtabs > label {
+ border: 1px outset #ddd; background: #ddd; xbackground: pink;
+ border-top-left-radius: 0.8em; border-top-right-radius: 0.8em;
+ margin: 0;
+ padding: 0.2ex 0.5em; height: 3em;
+ }
+ div.foldtabs > input:active + label {background: white;}
+ div.foldtabs input:checked + label {
+ background: pink; border: pink 1px solid; border-bottom-width: 6px;
+ }
+ div.foldtabs input:checked + label:last-of-type {border-width: 1px;}
+ input[type="checkbox"] + label + input[type="submit"] {display: none;}
+ input[type="checkbox"]:checked + label + input[type="submit"] {
+ display: inline;}
+ div.foldtabs p {margin: 0;}
+}
+
+/* ToDo List CheckBox inspired by https://cultureacademia.jp/webcreate/303/ */
+input.s4-checkbox {display: none;} /* Do not show real checkbox */
+input.s4-checkbox + label {
+ position: relative; padding-left: 0.8em; margin-right: 1em;
+}
+input.s4-checkbox + label:before,
+input.s4-checkbox + label:after {
+ content: ""; display: block; /* Mimic Checkbox by absolute box */
+ position: absolute; top: 0; left: 0; margin: 0;
+}
+input.s4-checkbox + label:before { /* checkbox frame */
+ width: 0.8em; height: 0.8em; border: 1px solid #aaa; border-radius: 20%;
+ background: #ddd;
+}
+input.s4-checkbox:checked + label:before { /* checked frame bg */
+ background: pink;
+}
+input.s4-checkbox:checked + label { /* checked text */
+ /* text-shadow: red 1px 1px; */
+}
+input.s4-checkbox:checked + label:after { /* checked mark */
+ width: 0.6em; height: 0.4em; top: 0.05em; left: 0.1em;
+ border-bottom: 3px solid navy;
+ border-left: 3px solid navy;
+ transform: rotate(-40deg);
+}
+/* ---------------------------------------------------- */
+
+div.dumptable {max-height: 70vw; overflow: auto;}
+div.dumptable tr:hover {background-color: #fee;}
+table.dumpblogs td,
+div.lcto td { /* LINK + CTIME + TITLE + OWNER + something... */
+ white-space: nowrap; overflow: hidden;}
+table.dumpblogs td:nth-child(4),
+div.lcto td:nth-child(2) {max-width: 8em;}
+table.dumpblogs td:nth-child(5), /* team */
+table.dumpblogs td:nth-child(6), /* title */
+table.dumpblogs td:nth-child(7), /* heading */
+div.lcto td:nth-child(3), /* title */
+div.lcto td:nth-child(4) /* owner */
+ {max-width: 14em;}
+/* https://curecode.jp/tech/css-table-position-sticky-with-background-border-vanished/ */
+div.dumptable table.dumpblogs th {
+ position: sticky; top: 0; z-index: 1; background: #fcf0f0;
+ border: 1px solid black; border-collapse: collapse;
+ background-clip: padding-box;
+}
+div.dumptable table.dumpblogs th.rev {background: white;}
+div.dumptable table.dumpblogs th.rev:after {content: "▼";}
+
+table.dumpblogs tr.凍結 td:nth-child(n+2) {opacity: 0.5;}
+table.dumpblogs tr.凍結 td:last-child {opacity: 1.0; color: blue;}
+*.frozen, *.凍結 {color: blue;}
+
+/*
+table.dumpblogs td:nth-child(4) {
+ max-width: 7.6em; overflow: hidden;}
+table.dumpblogs td:nth-child(5),
+table.dumpblogs td:nth-child(6) {
+ max-width: 12em; overflow: hidden;}
+table.dumpblogs td:nth-child(7) {
+ min-width: 5em; overflow: hidden;}
+*/
+
+/********************* icon list *********************/
+div.iconholder {display: flex; flex-wrap: wrap;}
+div.iconlist {
+ text-align: center; margin: 1ex 1em;
+ border: dotted #dfd 2px; padding: 1ex;
+}
+div.iconlist p {margin: 0; padding: 0;}
+div.iconlist p.tag {background: #ffa; border-radius: 4em;}
+div.iconlist p._temp {background: cyan;}
+div.iconlist p._lecture {background: pink;}
+div.iconlist p._admin {background: yellow;}
+div.iconlist p._friend {background: fuchsia;}
+div.iconlist p._fellows {background: #9f9;} /* light green */
+div.iconlist p._club {background: #4bb;} /* light teal */
+div.iconlist p._event {background: maroon; color: white;}
+div.iconlist p._misc {background: purple; color: white;}
+div.iconlist p._record {background: red; color: white;}
+div.iconlist p._info {background: #eff;} /* light cyan */
+div.iconlist p._support {background: #ffe;} /* light yellow */
+div.iconlist p._test {background: #ffb6c1;} /* light pink */
+input#ismembtn:checked ~ div.iconholder > div.iconlist,
+input#isadmbtn:checked ~ div.iconholder > div.iconlist {display: none;}
+input#ismembtn:checked ~ div.iconholder > div.iconlist.Member,
+input#isadmbtn:checked ~ div.iconholder > div.iconlist.ADMIN,
+input#ismembtn:checked ~ div.iconholder > div.iconlist.ADMIN {display: block;}
+div.xy120x120 {min-width: 120px; min-height: 140px;}
+div.xy96x96 {min-width: 96px; min-height: 116px;}
+div.xy96x96 img {max-width: 96px;}
+div.xy50x50 {min-width: 50px; min-height: 70px;}
+div.xy50x50 img {max-width: 50px;}
+div.moderated {background: rgba(255, 215, 0, 0.3);} /* gold */
+body.moderated {background: #fffec4;} /* #faed8a */
+body.ismember, div.ismember {border-top: 4px red solid; margin-top: 0;}
+div.right, div.search {clear: both; float: right;}
+*.clear {clear: both;}
+div.search input[type="text"] {
+ border: solid 1px #bbb; border-radius: 0.5ex; min-height: 20px;
+ margin: 1em; padding: 0 0.5ex; padding-left: 18px;
+ background: url("../../img/loupe.png") left center no-repeat
+ rgba(242,240,240,0.7);
+ position: relative;
+}
+div.search div.fr, *.relative {position: relative;}
+div.search p.help, textarea + p.help {display: none;}
+div.search input:focus + p.help,
+textarea:focus + p.help {
+ display: block; background: white;
+ position: absolute; right: 15em; white-space: pre;
+ border: 1px solid #888; border-radius: 1em; padding: 1ex;
+ box-shadow: #555 2px 2px;
+}
+textarea:focus + p.help {
+ position: fixed;
+ top: 0em; left: 0;
+}
+form.summary input[type=submit],
+input[type="submit"].all, button.all {
+ background: #cfc; padding: 0.4ex 2ex;
+}
+button#c {
+ padding: 0.2ex 4em; border-radius: 0.5ex;
+}
+input#cmt input[type="submit"] {height: 4em;}
+
+input[type="reset"] {margin-left: 4em;}
+
+/*
+ * World List
+ */
+li.casmenu div {display: none; position: relative; width: 200%;
+ min-width: 80%; margin-right: 0;}
+li.casmenu div table {
+ background: white; position: absolute; top: 0em; border: 3px solid navy;
+ max-width: 100%;
+}
+li.casmenu div table td {text-align: left; padding: 0.5ex 1em;}
+li.casmenu:hover div, li.casmenu:active div,
+li.casmenu div:hover, li.casmenu div:active
+{display: block;}
+span.pre {white-space: pre;}
+
+/*
+ * Frozen toggle button
+ */
+td.稼動状態 {text-align: center;}
+button.toggle-frozen {
+ padding: 0 1emex;
+ background: #fdb585;
+ border-radius: 1ex;
+ border-bottom: solid 2px #d27d88;
+ box-shadow: inset 0 2px 0 rgba(255,255,255,0.2), 0 2px 2px rgba(0,0,0, 0.19);
+ background: linear-gradient(#fdeaea, #fdb2b2); // ffc8a8
+}
+.凍結 button.toggle-frozen, .凍結 button.toggle-frozen::before {
+ background: linear-gradient(#d8e2ea, #83bbea);
+}
+.凍結 button.toggle-frozen::before {
+ content: attr(frozen-marker); color: blue;
+}
+.toggle-frozen::before {
+ content: attr(running-marker);
+}
+.info-tooltip {
+ position: absolute; padding: 1ex;
+ background: ivory;
+ border-radius: 1em; border: double 5px blue;
+ min-width: 10em; right: 0; bottom: 0;
+}
+.dissolving {opacity: 0; transition: 3.0s;}
+.emerging {opacity: 1; transition: 3s;}
+button#c, button#reload {display: inline-block;}
+span.loading, button#c:disabled, button#reload:disabled {
+ visibility: visible; transform: rotateX(3600deg); transition: 30s;
+}
+span.loading {padding: 0 1em;}
+input.aux, input[type="reset"] {margin-left: 10em; transform: scale(0.7);}
+
+/*
+ * Listing
+ */
+button.copy, button.printpdf {
+ padding: 0 0.2em; font-size: 50%; background: ivory;
+}
+button.copy, pre.listing {margin: 0 16px;} /* Should be px, as fontSize=50% */
+pre.listing {
+ counter-reset linenum; background: #fffe;
+ border: 1px solid #777; position: relative;
+ max-height: 50vh; overflow: auto;
+ span {counter-increment: linenum; text-align: right;}
+ code {
+ padding-left: 5.6ex; display: block;
+ &::before {
+ position: absolute; top: -0; right: 0; display: inline-block;
+ content: attr(class); color: blue; background: ivory;
+ padding: 0 0.5ex; text-transform: uppercase;
+ }
+ span::before {
+ position: absolute; left: 0px; width: 4.2ex;
+ margin-right: 0.5em; padding: 0 0.2ex;
+ background: #eee; text-align: right; color: black;
+ content: counter(linenum) ":";
+ }
+ &:hover::before {opacity: 0; transition: 1s;}
+ &.sh, &.zsh, &.bash, &.csh, &.terminal, &.root {
+ background: #333; padding: 0 0.6ex; color: #fff;
+ em {background: #ccb;}
+ span::before {display: none;}
+ }
+ }
+}
+div.relativebox {
+ position: relative;
+ button.copy, button.printpdf {
+ position: absolute; top: 0; margin: 0.5ex;
+ z-index: 2; opacity: 0.2;
+ animation: fadeButton 6s ease;
+ &:hover {opacity: 1.0;}
+ }
+ button.copy {right: 0; width: 12em;}
+ button.printpdf {right: 13em;}
+}
+@keyframes fadeButton {from {opacity: 1.0;} 50% {opacity: 1.0;}}
+/*
+ * PR Web
+ */
+body.pr {font-size: 200%;}
+body.pr h1 {
+ text-align: center; width: 80%; padding: 3ex 0; margin: 0 auto;
+ background: #ffefef; border: double 5px navy;
+}
diff --git "a/\1331-10\135\346\234\254\350\254\233\347\276\251\04316 \345\234\260\347\220\206\343\201\250\346\203\205\345\240\261 _JDs4 - JD-Chokai_files/file-icon.png" "b/\1331-10\135\346\234\254\350\254\233\347\276\251\04316 \345\234\260\347\220\206\343\201\250\346\203\205\345\240\261 _JDs4 - JD-Chokai_files/file-icon.png"
new file mode 100644
index 0000000..d82f259
--- /dev/null
+++ "b/\1331-10\135\346\234\254\350\254\233\347\276\251\04316 \345\234\260\347\220\206\343\201\250\346\203\205\345\240\261 _JDs4 - JD-Chokai_files/file-icon.png"
Binary files differ
diff --git "a/\1331-10\135\346\234\254\350\254\233\347\276\251\04316 \345\234\260\347\220\206\343\201\250\346\203\205\345\240\261 _JDs4 - JD-Chokai_files/index.txt" "b/\1331-10\135\346\234\254\350\254\233\347\276\251\04316 \345\234\260\347\220\206\343\201\250\346\203\205\345\240\261 _JDs4 - JD-Chokai_files/index.txt"
new file mode 100644
index 0000000..63d7f0b
--- /dev/null
+++ "b/\1331-10\135\346\234\254\350\254\233\347\276\251\04316 \345\234\260\347\220\206\343\201\250\346\203\205\345\240\261 _JDs4 - JD-Chokai_files/index.txt"
@@ -0,0 +1,20 @@
+#!/usr/bin/env ruby
+# coding: utf-8
+
+require 'csv'
+data = CSV.read("kensaku.csv", headers: true)
+
+puts "学校で探す:1"
+print "どれにしますか:"
+sel = gets.to_i
+if sel == 1
+ print "探したい学校名を入れてください:"
+ ptn = Regexp.new(gets.chomp)
+ data.each do |row|
+ if ptn =~ row["gakko"]
+ printf("%sさんは%s%s年です\n", row["name"], row["gakko"], row["gakunen"])
+ end
+ end
+else
+ printf("%d番はありません。さようなら。\n", sel)
+end
diff --git "a/\1331-10\135\346\234\254\350\254\233\347\276\251\04316 \345\234\260\347\220\206\343\201\250\346\203\205\345\240\261 _JDs4 - JD-Chokai_files/j2025.css" "b/\1331-10\135\346\234\254\350\254\233\347\276\251\04316 \345\234\260\347\220\206\343\201\250\346\203\205\345\240\261 _JDs4 - JD-Chokai_files/j2025.css"
new file mode 100644
index 0000000..7f6a8f9
--- /dev/null
+++ "b/\1331-10\135\346\234\254\350\254\233\347\276\251\04316 \345\234\260\347\220\206\343\201\250\346\203\205\345\240\261 _JDs4 - JD-Chokai_files/j2025.css"
@@ -0,0 +1,11 @@
+@import url("default.css");
+body {background: url("img/jds4_bg_2025.png") #f9a317 no-repeat center fixed;
+ background-size: cover; margin: 2px; padding: 6px;
+}
+body.moderated {background: #dcdfe1; border: 3px gold solid;}
+
+body.moderated {background: #c8e2c1; border: 3px gold solid;}
+div.topmenu ul li {
+ background: #f6d8b8; border: #ed8 2px groove; margin: 0
+}
+div.topmenu ul li:hover {background: #fdeab6;}
diff --git "a/\1331-10\135\346\234\254\350\254\233\347\276\251\04316 \345\234\260\347\220\206\343\201\250\346\203\205\345\240\261 _JDs4 - JD-Chokai_files/s4-main.js" "b/\1331-10\135\346\234\254\350\254\233\347\276\251\04316 \345\234\260\347\220\206\343\201\250\346\203\205\345\240\261 _JDs4 - JD-Chokai_files/s4-main.js"
new file mode 100644
index 0000000..64e341e
--- /dev/null
+++ "b/\1331-10\135\346\234\254\350\254\233\347\276\251\04316 \345\234\260\347\220\206\343\201\250\346\203\205\345\240\261 _JDs4 - JD-Chokai_files/s4-main.js"
@@ -0,0 +1,1524 @@
+// 愛
+(function (){
+ var isOlderJS; // Set in init();
+ var hoverTextLines = 10;
+ var hasTouchPad =
+ (navigator.maxTouchPoints && navigator.maxTouchPoints >0);
+ var myurl = document.URL,
+ mypath = myurl.substring(myurl.lastIndexOf("/"));
+ var art_m_list = [];
+ var mathjax = false;
+ var mmScript = null;
+ var filterSelect, filterOption = null;
+ let input_pdfsw = 'input[name="comppdf"]';
+ if (mypath.match(/(.*)\/(.*)/)) {
+ mypath = RegExp.$2;
+ mypath = mypath.substring(0, mypath.lastIndexOf("?"));
+ //alert("mypath="+mypath);
+ }
+ function escapeChars(old) {
+ return old.replaceAll('&', '&')
+ .replaceAll('"', '"')
+ .replaceAll("<", '<')
+ .replaceAll(">", '>');
+ }
+ function collectElementsByAttr(elm, attr, val) {
+ var e = document.getElementsByTagName(elm);
+ if (!e) return null;
+ var list = [];
+ for (var i of e) {
+ if (i.getAttribute(attr) == val)
+ list.push(i)
+ }
+ return list;
+ }
+ function loadJS(js, hook) {
+ let script = document.createElement("script");
+ script.src = js;
+ script.addEventListener("load", hook);
+ document.head.appendChild(script);
+ }
+ function nthChildOf(parent, n, elem) { // Return Nth child of type ELEM
+ // N begins with 1
+ var i=0;
+ var le = elem.toLowerCase();
+ for (var c of parent.childNodes) {
+ if (!c.tagName) continue;
+ if (c.tagName.toLowerCase() == le) {
+ if (++i >= n) return c;
+ }
+ }
+ return null;
+ }
+ function insertRedirect(e) {
+ var articleId, textarea = document.getElementById("text");
+ var p = e.target, checked = p.checked;
+ while (p = p.parentNode)
+ if (p.nodeName.match(/^td$/i)) break;
+ if (!p) return;
+ while (p = p.nextSibling)
+ if (p.nodeName.match(/^td$/i)) break;
+ if (!p) return;
+ articleId = p.getAttribute("id");
+ if (textarea && articleId) {
+ var tv = textarea.value, lines;
+ if (tv)
+ lines = tv.split("\n");
+ else
+ lines = [""];
+ var re = new RegExp("[, ]*#"+articleId+"(?![0-9])");
+ checked = (p.nodeName.match(/^input$/)
+ ? p.checked // checkbox obeys its status
+ : !lines[0].match(re)) // a-elment toggles redirection
+ if (checked) {
+ if (!lines[0].match(re)) {
+ var re2 = new RegExp(/>#[#0-9, ]+[0-9]/);
+ if (lines[0].match(re2))
+ lines[0] = lines[0].replace(
+ re2, '$&, '+'#'+articleId);
+ else {
+ if (lines[0] > "") lines[0] = " "+lines[0];
+ lines[0] = ">#"+articleId+lines[0];
+ }
+ }
+ } else { // Remove #xxxxx
+ if (lines[0].match(/^>#[0-9 ,]+#/)) // 2 or more #id's
+ lines[0] = lines[0].replace(
+ new RegExp("^>#"+articleId+"[ ,]*"), ">").replace(
+ new RegExp("[ ,]*#"+articleId), "");
+ else {
+ lines[0] = lines[0].replace(
+ new RegExp(">#"+articleId+"[ ,]*"), "");
+ }
+ }
+ lines[0] = lines[0].replace(/^> *$/, '');
+ textarea.value = lines.join("\n");
+ }
+ }
+ function registPjaxViewers(aHrefList) {
+ let apos=art_m_list.length;
+ for (let a of aHrefList) {
+ let href = a.getAttribute("href");
+ let localvar = apos;
+ let td = a.parentNode,
+ tr = td.parentNode,
+ id = td.id,
+ text = td.textContent,
+ author = tr.getElementsByTagName("a");
+ if (author) author = author[0].getAttribute("title");
+ if (href.match(/\?showattc\+article_m\+([0-9]+)$/)) {
+ if (td.innerHTML.match(/読み取り不可/)) {
+ a.removeAttribute("href");
+ continue;
+ }
+ let url = RegExp.lastMatch;
+ // console.log("pjaxView(e, "+href+", "+apos+")");
+ a.addEventListener("click", function(e) {
+ // Shoud use closure local variable: localvar
+ pjaxView(e, href, localvar);
+ }, false);
+ apos++;
+ art_m_list.push({
+ url: href, id: id, author: author, text: text
+ });
+ }
+ }
+ }
+ function resetPjaxViewers(arefs) {
+ art_m_list = [];
+ registPjaxViewers(arefs)
+ }
+ function registInsertDirect(aHrefList) {
+ for (i of aHrefList)
+ if (i.getAttribute("href").match(/^#[0-9]+$/))
+ if (RegExp.lastMatch == i.innerHTML)
+ i.addEventListener("click", insertRedirect, false)
+ }
+ function mathjaxUpdate(arg) {
+ try {
+ if (MathJax && MathJax.typesetPromise) {
+ MathJax.texReset(); // Reset Math counters
+ MathJax.typesetPromise(arg); // MathJax v3
+ }
+ } catch (err) {console.log(err);}
+ }
+ var ajaxSubmit;
+ function replAddNews(newtable) {
+ let newids = [], idlist=[];
+ let getArticleID = function (td) {
+ return parseInt(td.parentNode.getElementsByTagName("td")[1].id);
+ }
+ for (let i of newtable.querySelectorAll("td.repl"))
+ newids.push(i);
+ newids = newids.sort((a,b)=> {
+ return (getArticleID(a) - getArticleID(b));
+ });
+ for (i of newids)
+ idlist.push(getArticleID(i));
+ console.log("IDList="+idlist.join());
+ let cnt=0, ntr;
+ let current = collectElementsByAttr("td", "class", "repl"),
+ ncur=0, n, icur=0, o, oid, nid, otr;
+ current = document.querySelectorAll('td[class~="repl"]');
+ let last=current[current.length-1],
+ tbody = last.parentNode.parentNode;
+ let addEventsToNewTr = function(tr) {
+ let td = tr.getElementsByTagName("td"),
+ td0 = td[0], td1 = td[1];
+ td0.classList.add("new");
+ registInsertDirect(td0.querySelectorAll("a[href]"));
+ registPjaxViewers(td1.querySelectorAll("a[href]"));
+ }
+ // Erase all "new article" flags before merging
+ for (let i of document.querySelectorAll("td.new"))
+ i.classList.remove("new");
+ // Now reconstruct articles with merge-sort like method
+ outer: for (; ncur= nid) {
+ addEventsToNewTr(ntr);
+ tbody.insertBefore(ntr, otr);
+ if (oid==nid) otr.remove();
+ cnt++;
+ continue outer;
+ }
+ }
+ // Append absolutely new articles.
+ ntr = n.parentNode;
+ addEventsToNewTr(ntr)
+ tbody.appendChild(atMarkView(ntr));
+ ntr.classList.add("dissolving");
+ let localntr = ntr;
+ setTimeout(() => {
+ localntr.classList.remove("dissolving");
+ localntr.classList.add("emerging");
+ }, 100);
+ rewriteReplyHover(ntr);
+ cnt++;
+ }
+ mathjaxUpdate(newids);
+ console.log("Update "+cnt+"rows");
+ if (cnt>0 && ntr.scrollIntoView) {
+ let option = {behavior: "smooth"};
+ if (!isOlderJS) option.block = "center";
+ try { // Scroll to last updated row
+ ntr.scrollIntoView(option);
+ } catch (e1) {}
+ }
+ return cnt;
+ }
+
+ function warnFileSize(form) {
+ let szmax = form.querySelector('input[name="filesize_max"]').value;
+ if (!szmax || szmax=="") return;
+ szmax = parseInt(szmax);
+ if (szmax <= 0) return;
+ // szmax = 10000
+ let ng = "", rcval=false, fileexists=false,
+ pdfsw = form.querySelector(input_pdfsw),
+ pdfmsg = "Try compressing PDF?\nPDFを圧縮してみますか?\n" +
+ "(それでも収まらない場合もあります)";
+ for (let f of form.querySelectorAll('input[type="file"]')) {
+ let thiserr = false;
+ for (let i of f.files) {
+ fileexists = true;
+ let fn = i.name, sz = i.size;
+ console.log("max="+szmax+", fn="+fn+", sz="+sz);
+ if (sz > szmax) {
+ if (fn.match(/\.pdf/i)
+ && sz < szmax*3 // XXX : x3 reasonable?
+ && (pdfsw || confirm(pdfmsg))) {
+ if (!pdfsw) {
+ pdfsw = document.createElement("input");
+ pdfsw.name = "comppdf";
+ pdfsw.type = "hidden";
+ f.parentNode.insertBefore(pdfsw, f);
+ pdfsw.value = "yes";
+ }
+ } else {
+ thiserr = true;
+ ng += ((ng>"" ? ", " : "")+fn)
+ }
+ }
+ }
+ thiserr ? f.classList.add("warnbg") : f.classList.remove("warnbg");
+ }
+ if (ng>"") {
+ rcval = "File-size Limit Error: "+ng+"\n"+
+ "Should be less than "+szmax+"bytes.\n"+
+ szmax+"バイト未満にしてください"
+ alert(rcval);
+ }
+ if (form.text.value == "") {
+ let w;
+ if (fileexists)
+ w = "Fill the text area\n" +
+ "添付したファイルに関する説明を入れてください。";
+ else
+ w = "Enter your comment!\n何か書き込んでね!";
+ alert(w);
+ rcval = (rcval || w);
+ form.text.classList.add("warnbg");
+ setTimeout(() => {form.text.classList.remove("warnbg");}, 2000)
+ }
+ return rcval;
+ }
+ function ajaxPost(e) {
+ e.preventDefault();
+ let rowid;
+ if (!myurl.match(/replyblog\+([0-9]+)/)) return;
+ rowid = RegExp.$1
+ let myform = document.querySelector("form.replyblog");
+ let data = new FormData(myform),
+ fetchtime = data.get("fetchtime");
+ if (!fetchtime || fetchtime=="") return;
+ ///*XX*/fetchtime = "2020-06-14T00:00:00";data.set("fetchtime", fetchtime)
+
+ ajaxSubmit = e.target;
+ ajaxSubmit.back = ajaxSubmit.textContent;
+ if (ajaxSubmit.id == "reload") {
+ ajaxSubmit.textContent = "更新中"
+ data.set("text", "")
+ } else {
+ if (warnFileSize(myform)) return;
+ ajaxSubmit.textContent = "送信中";
+ }
+ ajaxSubmit.blur();
+ ajaxSubmit.disabled = true;
+ let act = mypath+"?blog_fetch+"+rowid+"+f:"+fetchtime;
+
+ function respUpdate(tbody) {
+ ajaxSubmit.textContent = ajaxSubmit.back;
+ ajaxSubmit.disabled = false;
+ let div = document.createElement("div"), form, newform;
+ try {
+ div.innerHTML = tbody;
+ form = div.querySelector("form");
+ } catch (er) {
+ alert("Cannot parse fetch data");
+ return;
+ }
+ let update = replAddNews(form);
+ let dispelem = myform.querySelector("textarea").parentNode;
+ if (div.querySelector('input[name="user"]')) { // is login form
+ dispInfoMomentary("Login Again Please", dispelem)
+ return;
+ }
+ newform = new FormData(form);
+ if (data.get("text") > "") { // Called by submit button
+ myform.reset();
+ if (filterOption) { // Restore TEAM filterin if any
+ filterSelect.selectedIndex = filterOption;
+ }
+ let pdfsw = myform.querySelector(input_pdfsw);
+ if (pdfsw) pdfsw.remove();
+ // myform.text.value = '';
+ }
+ myform.fetchtime.value = newform.get("fetchtime");
+ myform.id.value = newform.get("id");
+ if (update && update > 0) {
+ let s = update + " new article" +
+ (update>1 ? "s" : "") + " posted";
+ dispInfoMomentary(s, dispelem);
+ }
+ initMermaid();
+ }
+ fetch(act, {
+ method: "POST", body: data,
+ credentials: "include" // For older firefox
+ }).then((resp) => {
+ return resp.text();
+ }).then((tbody) => {
+ respUpdate(tbody);
+ })
+ }
+ function pjaxView(ev, url, mynum) {
+ if (ev.ctrlKey||ev.shiftKey) return;
+ ev.preventDefault();
+ let box = document.createElement("div")
+ box.setAttribute("class", "pjaxview");
+ let p1 = document.createElement("p"),
+ bt = document.createElement("button"),
+ sl = document.createElement("button"),
+ sr = document.createElement("button"),
+ loading = document.createElement("span"),
+ info = document.createElement("p");
+ info1 = document.createElement("span");
+ info2 = document.createElement("span");
+ iframe = document.createElement("iframe");
+ var curpos = mynum;
+ var historyBase = history.length;
+
+ function _setPjaxCurposInfo() {
+ let len = art_m_list.length;
+ let cur = art_m_list[curpos]
+ info1.textContent = (1+curpos)+" of "+len+" article #"+cur.id+
+ (cur.author ? " by "+cur.author : "") + ":";
+ info2.textContent = cur.text.trim();
+ info2.setAttribute("class", "border textdigest");
+ }
+ function _resetPjax() {
+ // All we can do surely is to back 1 page,
+ // because we cannot move to desirable entry of history list.
+ history.back();
+ }
+ function setSwipeAct(iframe) {
+ // We cannot use DOMContentLoaded nor iframe.contentWindow here.
+ // PDF.js does not construct contentWindow...?
+ iframe.addEventListener("load", () => {
+ loading.classList.remove("loading");
+ if (!hasTouchPad) return;
+ let ifm = iframe.contentDocument;
+ let startX, moveX, thresh = 400;
+ ifm.addEventListener("touchstart", (e) => {
+ e.preventDefault();
+ startX = e.touches[0].pageX;
+ }, false);
+ ifm.addEventListener("touchmove", (e) => {
+ e.preventDefault();
+ moveX = e.touches[0].pageX;
+ }, false);
+ ifm.addEventListener("touchend", (e) => {
+ if (startX < moveX && startX + thresh < moveX) {
+ switchTo(e, -1);
+ } else if (startX > moveX && startX - thresh > moveX) {
+ switchTo(e, +1);
+ }
+ }, false);
+ }, false);
+
+ }
+ function switchTo(e, direction) {
+ e.preventDefault();
+ let len = art_m_list.length, cur, newpos, url;
+ newpos = (curpos+len+direction)%len;
+ if (curpos == newpos) return; // No need to switch to same one
+ curpos = newpos;
+ cur = art_m_list[curpos];
+ url = cur.url;
+ // We should remove iframe once to preserve history Object
+ // https://inthetechpit.com/2019/04/20/update-iframe-without-affecting-browser-history/
+ let parent = iframe.parentNode;
+ // alert("D = "+direction);
+ iframe.remove();
+ parent.appendChild(iframe);
+ try {
+ loading.classList.add("loading");
+ iframe.src = url;
+ // iframe.contentDocument.location.replace(url);
+ // location.replace cannot be used because PDF viewer.js
+ // does not have iframe.contentDocument
+ } catch (err) {
+ alert("Cannot load "+src+" : "+err.name);
+ }
+ _setPjaxCurposInfo();
+ setSwipeAct(iframe);
+ }
+ function switchToByKey(e) {
+ // alert("KEY="+e.key);
+ switch (e.key) {
+ case "ArrowLeft":
+ switchTo(e, -1); break;
+ case "ArrowRight":
+ switchTo(e, +1); break;
+ case "Escape":
+ history.back();
+ }
+ }
+ //
+ //
+ //
info1 info2
+ //
+ //
+ // ==> [ << ][Dissmiss][ >> ]
+ // ==> ## of ## article #xxx by AUTHOR
+ sl.textContent = " << ";
+ sr.textContent = " >> ";
+ sl.addEventListener("click", (e) => {switchTo(e, -1);});
+ sr.addEventListener("click", (e) => {switchTo(e, +1);});
+ sl.setAttribute("title", "to="+(mynum-1));
+ sr.setAttribute("title", "to="+(mynum+1));
+ document.body.appendChild(box);
+ bt.textContent = "Click to dismiss / もどる"+mynum;
+
+ box.appendChild(p1);
+ p1.appendChild(sl); p1.appendChild(bt); p1.appendChild(sr);
+ { // TEST: Normal mode
+ let only = document.createElement("button"),
+ h = location.href;
+ only.textContent = ".oO□";
+ only.setAttribute("title", "Open in Normal Window");
+ only.addEventListener("click", function() {
+ location.replace(iframe.src);
+ });
+ p1.appendChild(only);
+ }
+ p1.appendChild(loading);
+ info.appendChild(info1); info.appendChild(info2);
+ loading.textContent=" Loading...";
+ loading.classList.add("hidden");
+ loading.classList.add("loading");
+ box.appendChild(info);
+ iframe.src = url;
+
+ box.addEventListener("keydown", switchToByKey);
+ //box.addEventListener("click", (e) => {_resetPjax();});
+ bt.addEventListener("click", (e) => {_resetPjax();});
+ // dp.addEventListener("click", (e) => {_resetPjax();});
+ info.addEventListener("click", (e) => {_resetPjax();});
+ box.appendChild(iframe);
+
+ setSwipeAct(iframe);
+
+ _setPjaxCurposInfo();
+ bt.focus();
+ setTimeout(() => {box.classList.add("pjaxview2");}, 10);
+ // Finally update history stack
+ pjaxHistoryPush(box);
+ }
+ function pjaxHistoryPush(box) {
+ if (history.pushState) {
+ let h = location.href.replace(/#.*/, '')+"#pjaxview";
+ history.pushState({url: h}, null, h);
+ window.addEventListener("popstate", (e) => {
+ if (box) {
+ box.remove(); box = null;
+ }
+ }, false);
+ }
+ }
+ function reverseChecks() {
+ var names = collectElementsByAttr("input", "name", "usel");
+ for (let u of names) {
+ u.checked = !u.checked;
+ }
+ }
+ function renumberOL(str, start) {
+ var stra = str.split("\n");
+ for (var i=1; i1 && area.value.charCodeAt(pos)==10)
+ b = area.value.lastIndexOf("\n", pos-1);;
+ return b>=0 ? b : 0;
+ }
+ function isInBeginEnd(area, pos){
+ pos = pos||area.selectionStart;
+ let bol = beginningOfLine(area, pos);
+ let thisline = area.value.substr(bol);
+ console.log("curchar="+area.value.charCodeAt(pos));
+ console.log("prechar="+area.value.charCodeAt(pos-1));
+ console.log("bol="+bol+", thisline="+thisline);
+ let match = thisline.search(/\\(begin|end){([A-Za-z]*)/), lm, be;
+ if (match >= 0) {
+ lm = RegExp.lastMatch;
+ be = RegExp.$1;
+ return RegExp.$2
+ }
+ return null;
+ }
+ function helpMarkdownBrace(e) {
+ if (!mathjax) return;
+ var area = e.target, pos = area.selectionStart, text = area.value,
+ begin = "\\begin", end = "\\end";
+ if (pos < end.length) return;
+ if (text.substr(pos-end.length).startsWith(end)) {
+ let beg = text.lastIndexOf(begin, pos);
+ if (beg >= 0) {
+ let env = text.substr(beg).search(/\\begin{(.*?)}/);
+ if (env >= 0) {
+ textInsert(area, "{"+RegExp.$1+"}", pos);
+ e.preventDefault();
+ }
+ }
+ }
+ }
+ function helpMarkdownBraceClose(e) {
+ if (!mathjax) return;
+ let area = e.target, pos = area.selectionStart, text = area.value,
+ begin = "\\begin", end = "\\end";
+ if (text.substr(pos).startsWith("}")) {
+ area.setRangeText("", pos, pos+1);
+ // e.preventDefault();
+ }
+ let inbegend = isInBeginEnd(area, pos);
+ if (!inbegend) return;
+ let nextendpos = text.substr(pos).indexOf("\\end{");
+ let nextcurend = text.substr(pos).indexOf("\\end{"+inbegend+"}");
+ if (nextcurend<0 || nextendpos!=nextcurend) {
+ area.setRangeText("}\n\n\\end{"+inbegend+"}", pos, pos);
+ area.selectionStart = pos+2;
+ e.preventDefault();
+ }
+ console.log(inbegend);
+
+ }
+ function helpMarkdownPreview(area) {
+ if (!mathjax && !mmScript) {
+ alert("no"+e.target)
+ dispInfoMomentary("This board has no Preview mode.\n"+
+ "この掲示板は数式またはMermaidモードOFFです。",
+ e.target.parentNode);
+ return;
+ }
+ let text = area.value;
+ let preview = document.createElement("div");
+ let bp = document.createElement("p");
+ let btn = document.createElement("button");
+ btn.innerText = "Click or ESC to Dissmiss / クリックかESCで戻る";
+ bp.classList.add("c");
+ preview.classList.add("pjaxview");
+ preview.classList.add("pjaxview2");
+ let pre = document.createElement("p");
+ bp.appendChild(btn);
+ preview.appendChild(bp);
+ preview.appendChild(pre);
+ pre.innerText = text;
+ document.body.appendChild(preview);
+ function dismiss(t) {
+ history.back();
+ preview.remove();
+ area.focus();
+ }
+ preview.addEventListener("click", dismiss, false);
+ preview.addEventListener("keydown", dismiss, false);
+ MathJax.typesetPromise([pre]);
+ //
+ (async function() {
+ let newtext = text.replace(
+ /!!!(mm|mermaid)\n(.*?)!!!/gs, (m, pfx, body) => {
+ return `\n${body}`;
+ });
+ pre.innerHTML = newtext;
+ initMermaid();
+ })();
+ //
+ pjaxHistoryPush(preview);
+ btn.focus();
+ }
+ function helpMarkdownAt(e) {
+ var area = e.target, pos = area.selectionStart;
+ if (pos == 0) {
+ area.value = "@all" + area.value;
+ area.selectionStart = area.selectionEnd = 4;
+ dispInfoMomentary("@all で全員に通知します", area.parentNode);
+ e.preventDefault();
+ }
+ }
+ function helpMarkdownTriple(e, mark, defSuffix, tooltip) {
+ let area = e.target, pos=area.selectionStart, text=area.value,
+ last = text.lastIndexOf("\n", pos-1),
+ line = last ? text.substring(last+1, pos) : text,
+ prev = text.substring(0, last),
+ triple = mark+mark+mark,
+ add1 = mark+defSuffix,
+ add2 = `\n\n${mark}${mark}${mark}`;
+ if (line == mark+mark) { // is like "<<"
+ let oprx = RegExp(`(?<=^|\n)${triple} *.*(?=\n|$)`, "g"),
+ clrx = RegExp(`(?<=\n)${triple} *.*(?=\n|$)`, "g"),
+ r = prev.match(oprx);
+ if (r && r.pop() != triple) return; // If recent <<< is header
+ r = text.substring(pos).match(clrx);
+ if (r && r[0] == triple) return; // If already closed
+ e.preventDefault();
+ if (!document.execCommand("insertText", false, add1+add2)) {
+ //To enable undo, use deperecated function once.
+ // setRangeText breaks undo ring...
+ area.setRangeText(add1+add2, pos, pos);
+ }
+ area.selectionStart = pos+1;
+ area.selectionEnd = pos+1+defSuffix.length;
+ if (tooltip) {
+ dispInfoMomentary(tooltip, area.parentNode);
+ }
+ }
+ }
+ function helpMarkdownLT(e) {
+ helpMarkdownTriple(e, "<", " See more...");
+ }
+ function helpMarkdownExclamation(e) {
+ helpMarkdownTriple(e, "!", "info", "!!!info / !!!warn / !!!alert / !!!mermaid");
+ }
+ function helpMarkdownCodeblock(e) {
+ helpMarkdownTriple(e, "`", "code",
+ "code terminal zsh bash csh root, others...");
+ }
+ function helpMarkdown(e) {
+ switch (e.key) {
+ case "Backspace": helpMarkdownBS(e); break;
+ case "Enter": helpMarkdownEnter(e); break;
+ case "(": helpMarkdownParen(e); break;
+ case "p": if (e.metaKey) helpMarkdownPreview(e.target); break;
+ case "{": helpMarkdownBrace(e); break;
+ case "}": helpMarkdownBraceClose(e); break;
+ case "@": helpMarkdownAt(e); break;
+ case "<": helpMarkdownLT(e); break;
+ case "!": helpMarkdownExclamation(e); break;
+ case "`": helpMarkdownCodeblock(e); break;
+ }
+ }
+ /* Init event listeners */
+ function addFileInput() {
+ var inpfile = collectElementsByAttr("input", "name", "image");
+ if (!inpfile) return;
+ var filled = true;
+ var i, ih;
+ for (i of inpfile) {
+ if (! i.value) filled=false;
+ }
+ if (filled) {
+ ih = i.parentNode.innerHTML;
+ let ipph = i.parentNode.parentNode.innerHTML; //Entire td inside
+ if (ipph) {
+ let ip = i.parentNode;
+ var inpf = ipph.substring(ipph.indexOf('"+inpf.substring(0, inpf.indexOf("/span>")+6);
+ ip.insertAdjacentHTML("afterend", newi)
+ ip.nextSibling.nextSibling.addEventListener('change', () => {
+ warnFileSize(document.forms[0]);
+ });
+ }
+ }
+ }
+ function initFileInput() { // Multiplies "input type=file"
+ var el, morefile = document.getElementById("morefile");
+ if (morefile) {
+ for (el of collectElementsByAttr("input", "name", "image")) {
+ el.addEventListener("change", function(ev) {
+ if (ev.target.value > "" && ev.target.files.length == 1)
+ morefile.style.visibility = "visible";
+ // No need to hide again, sure?
+ });
+ }
+ morefile.addEventListener("click", addFileInput, null);
+ }
+ // When renaming, select basename part
+ for (el of collectElementsByAttr("input", "class", "mv")) {
+ el.addEventListener("focus", function(ev) {
+ var i = ev.target;
+ if (i) {
+ i.setSelectionRange(0, i.value.lastIndexOf("."));
+ }
+ });
+ }
+ }
+ function initTextarea() {
+ let te = collectElementsByAttr("textarea", "name", "text"),
+ th = collectElementsByAttr("textarea", "name", "heading");
+ if (!te || !te[0]) te = th;
+ if (!te || !te[0]) return;
+ te[0].addEventListener("keydown", helpMarkdown, false);
+ }
+ function atMarkView(elem) {
+ // Enclose "@all" with span
+ for (i of elem.querySelectorAll("td.repl")) {
+ if (i.textContent.startsWith("@all")) {
+ i.firstChild.nodeValue = i.firstChild.nodeValue.substring(4);
+ i.insertAdjacentHTML(
+ 'afterbegin', '@all
'
+ );
+ i.classList.add("atall");
+ }
+ }
+ return elem;
+ }
+ var authVisible = false;
+ function toggleAuthorVisibility(e) {
+ // Click to hideauth button toggles visibility of author columns
+ e.stopPropagation();
+ let b = document.getElementById("hideauth");
+ if (authVisible) {
+ for (let i of document.querySelectorAll("td.repatt")) {
+ i.classList.remove("hideauthor");
+ }
+ authVisible = false;
+ } else {
+ for (let i of document.querySelectorAll("td.repatt")) {
+ i.classList.add("hideauthor");
+ }
+ authVisible = true;
+ }
+ b.textContent = b.textContent.replace(/OFF|ON/, authVisible ? "ON" : "OFF");
+ }
+ function downloadFile(filename, content, BOM) {
+ let bom = new Uint8Array([0xEF, 0xBB, 0xBF]);
+ let str = new Blob(BOM ? [bom, content] : [content],
+ {type: "text/csv"});
+ var uri = URL.createObjectURL(str);
+ let a = document.createElement("a");
+ a.download = (BOM ? "BOM-" : "")+filename;
+ a.href = uri;
+ document.body.appendChild(a);
+ a.click();
+ document.body.removeChild(a);
+ }
+ function getTextContentCSV_1(e) {
+ let blogtbl = document.querySelector("table.blog_replies");
+ let needBOM = e.ctrlKey;
+ if (!blogtbl) return;
+ let trw = blogtbl.querySelector("tr.warn"), a;
+ if (trw && (a=document.getElementById("showall"))) {
+ if (window.confirm(`50件以下に表示制限されています。
+取得し直しますか?
+Cancelを押すとこのまま取得します。
+Seen articles limited to 50 items.
+Push OK to get all articles, Cancel to get only seen articles.`)) {
+ a.click();
+ return;
+ }
+ }
+ if (navigator.userAgent.match(/Windows/)) {
+ if (!e.ctrlKey && !e.shiftKey && !window.confirm(`Excelで読ませるCSVの場合はBOMが必要です。
+その場合は一度キャンセルして Ctrl キーを押しながらボタンクリックして下さい。
+逆にExcel以外(GoogleスプレッドシートやLibreOfficeや他のツール)で読む場合はBOMをつけるとファイルの1行目の先頭にゴミのようなものが見える場合あるのでそのときは除去する必要があります。
+今後もBOM不要の場合はShiftキーを押しながらクリックして下さい。
+If you feed this CSV into Microsoft Excel, consider adding BOM sequence that can be prepended by pressing Control key with click.
+In this case, click CSVget with ctrl key after Cancel this dialog.
+If you never need BOM, press Shift key with click.`))
+ return;
+ }
+ outcsv = []
+ for (let row of blogtbl.querySelectorAll("tr[id]")) {
+ let tds = row.querySelectorAll("td"),
+ a = tds[0].querySelector("a.author"),
+ author = a.title,
+ name = a.innerText,
+ time = tds[0].querySelector("span").title,
+ id = tds[1].id,
+ body = tds[1].textContent;
+ //console.log(`${author},${name},${time},#${id},${body}`);
+ outcsv.push({
+ "author": author, "name": name, "time": time,
+ "id": "#"+id, "body": body});
+ }
+ let line = new CSV(outcsv, {header:true}).encode(),
+ fn = myurl.replace(/.*\?/, "").replaceAll("+", "-")
+ .replace(/#.*/, "").replace("-n:all", "");
+ downloadFile(fn+".csv", line, needBOM);
+ }
+ function getTextContentCSV(e) {
+ if (!document.getElementById("csvminjs")) {
+ let csvmin = document.createElement("script");
+ csvmin.src="https://www.yatex.org/libcache/csv.min.js";
+ csvmin.id = "csvminjs";
+ // https://stackoverflow.com/questions/14521108/dynamically-load-js-inside-js
+ csvmin.addEventListener("load", ()=>{
+ getTextContentCSV_1(e)}, 10);
+ document.querySelector("head").appendChild(csvmin);
+ } else {
+ getTextContentCSV_1(e);
+ }
+ }
+ function initBlogs() {
+ // (1)Auto-complete #xxxx, (2)Prepare sort
+
+ // (1)Complete #xxxx
+ let i, check = collectElementsByAttr("input", "name", "notifyto");
+ let blogheadtd = document.querySelector("table.bloghead tr td");
+ if (check)
+ for (i of check) {
+ i.addEventListener("click", insertRedirect, false);
+ }
+ registInsertDirect(document.querySelectorAll("a[href]"));
+ if (myurl.match(/replyblog\+[0-9]/)
+ && document.querySelector("td.repl")) {
+ // There's no need to provide ajax posting when
+ // no replies written to the blog. Therefore we
+ // assign ajax post when td.repl exists.
+ for (i of document.querySelectorAll('input#c[value="送信"]')) {
+ let b = document.createElement("button");
+ b.textContent = "送信!";
+ b.addEventListener("click", ajaxPost, false);
+ // i.insertAdjacentElement('afterend', b);
+ b.setAttribute("class", i.getAttribute("class"))
+ b.setAttribute("title", i.getAttribute("title"))
+ i.parentNode.replaceChild(b, i);
+ b.id = i.id;
+ // i.remove();
+ i.classList.add("aux");
+ i.value = "送信(予備)"
+ b.parentNode.appendChild(i);
+ }
+ i = document.getElementById("reload");
+ if (i) i.addEventListener("click", ajaxPost, false);
+ // Add CSV download button
+ if (blogheadtd) {
+ let btn = document.createElement("button");
+ btn.innerText = "CSVget";
+ btn.type = "button";
+ btn.accessKey = "g";
+ btn.title = `Shortcut: G
+見えている書き込みをCSVで取得します
+全件表示されていることを確認してから利用して下さい。
+Excelで利用する場合は Ctrl を押しながらクリックして下さい。
+Get seen TEXT content as CSV.`;
+ btn.addEventListener("click", getTextContentCSV, false);
+ let artlink = blogheadtd.querySelector('a[accesskey="f"]');
+ let spacer = document.createElement("span");
+ if (artlink) {
+ spacer.innerText = "|";
+ artlink.insertAdjacentElement('beforebegin', btn);
+ artlink.insertAdjacentElement('beforebegin', spacer);
+ } else {
+ spacer.innerText = " ";
+ blogheadtd.appendChild(spacer);
+ blogheadtd.appendChild(btn);
+ }
+ }
+ }
+ for (i of document.querySelectorAll('input[type="file"]')) {
+ i.addEventListener('change', (e) => {
+ warnFileSize(document.forms[0]);
+ }, false)
+ }
+ if (i=document.getElementById("hideauth")) {
+ i.addEventListener('click', toggleAuthorVisibility, false);
+ }
+ // Hack article_m links
+ registPjaxViewers(document.querySelectorAll("a[href]"));
+ atMarkView(document);
+ /*****************************************************************/
+ //(2) Prepare sort
+ let limit50 = document.getElementById("showall");
+ if (blogheadtd && limit50==null) {
+ let umode = "byUser", amode = "byArticle";
+ let sbtn = document.createElement("button");
+ sbtn.textContent = umode;
+ sbtn.type = 'button';
+ sbtn.accessKey = "o";
+ sbtn.title = `Shortcut: O
+書き込みを著者順に並べ替えます(全件表示時のみ)。
+特定のユーザの書き込みを探すときに有用です。
+Sort articles by UserID or ArticleID.
+Handy at searching for articles by certain user.`;
+ let spacer = document.createElement("span");
+ spacer.textContent = " ";
+ let hide = document.getElementById("hideauth");
+ if (hide) {
+ hide.insertAdjacentElement('afterend', sbtn);
+ hide.insertAdjacentElement('afterend', spacer);
+ } else {
+ blogheadtd.appendChild(spacer);
+ blogheadtd.appendChild(sbtn);
+ }
+ function compareRowsByUid(a, b) {
+ if (a.key1 < b.key1) return -1;
+ if (a.key1 > b.key1) return 1;
+ if (a.key2 < b.key2) return -1;
+ if (a.key2 > b.key2) return 1;
+ return 0;
+ }
+ function compareRowsByAid(a, b) {
+ if (a.key2 < b.key2) return -1;
+ if (a.key2 > b.key2) return 1;
+ return 0;
+ }
+ sbtn.addEventListener("click", (e)=>{
+ let uidsort = (sbtn.textContent.indexOf(umode) >= 0);
+ let rows = [], elm, i=0,
+ tbl = document.querySelector("table.blog_replies");
+ for (let tr of tbl.rows) {
+ elm = {};
+ elm.tr = tr;
+ elm.key1 = tr.querySelector("a.author").title; // userid
+ tr.innerHTML.match(/\1); // ArticleID
+ elm.key2 = RegExp.$1;
+ rows.push(elm);
+ }
+ rows.sort(uidsort ? compareRowsByUid : compareRowsByAid);
+ for (let r of rows) {
+ tbl.appendChild(r.tr);
+ r.tr.title = ++i;
+ }
+ sbtn.textContent = uidsort ? amode : umode;
+ // Re-sort pjax viewer links
+ resetPjaxViewers(document.querySelectorAll("a[href]"));
+ });
+ }
+ /*****************************************************************/
+ //(3) Prepare Filtering by Team
+ let teamfilter = document.getElementById("team4filter");
+ if (blogheadtd && teamfilter) {
+ let teams = {};
+ for (let row of teamfilter.querySelectorAll("tr")) {
+ let cols = row.querySelectorAll("td");
+ if (cols.length == 2) {
+ // TeamName | ["user1@dom1","user2@dom2"] |
+ teams[cols[0].textContent] = cols[1].textContent;
+ }
+ }
+ if (Object.keys(teams).length > 0) {
+ function filterArticles(e) {
+ if (limit50) {
+ if (window.confirm(`表示数制限があります。
+全件表示に切り替えますか。Cencel すると限定表示のまま絞り込みます。
+Not all articles are seen.
+Push OK to switch to all-articles mode, Cencel to continue without limit.`)) {
+ limit50.click();
+ return;
+ }
+ }
+ let userlist;
+ try {
+ userlist = JSON.parse(e.target.value);
+ } catch (e) {
+ return;
+ }
+ let showall = (userlist == "");
+ let tbl = document.querySelector("table.blog_replies");
+ for (let row of tbl.querySelectorAll("tr")) {
+ let author = row.querySelector("a[title]");
+ let visible = true;
+ if (!showall && author) {
+ let home = author.href;
+ if (home && home.match(/home\+([0-9]+)/)) {
+ let uid = RegExp.$1;
+ visible = userlist.find(e=>e==uid)
+ }
+ }
+ if (visible)
+ row.classList.remove("hide")
+ else
+ row.classList.add("hide")
+ filterOption = e.target.selectedIndex;
+ }
+
+ }
+ // Do Filter Addition
+ let optall = document.createElement("option");
+ filterSelect = document.createElement("select");
+ optall.textContent = "-- ALL(全件) --";
+ optall.value = '""'; // -> showall=true
+ filterSelect.appendChild(optall);
+ filterSelect.addEventListener('change', filterArticles, false)
+ for (let k in teams) {
+ let o = document.createElement("option");
+ o.textContent = k;
+ o.value = teams[k];
+ filterSelect.appendChild(o);
+ }
+ let table = document.querySelector("table.blog_replies");
+ if (table) {
+ let p = document.createElement("p");
+ p.textContent = "Filter by TEAM: ";
+ p.classList.add("filter");
+ p.appendChild(filterSelect);
+ table.insertAdjacentElement('beforebegin', p)
+ }
+ }
+ }
+ // Setup EventListener for Copy buttons, if any
+ for (let b of document.querySelectorAll("button.copy")) {
+ b.addEventListener("click", (e)=>{
+ e.preventDefault();
+ let pre = b.nextSibling;
+ if (pre && pre.tagName.match(/pre/i)) {
+ navigator.clipboard.writeText(pre.innerText);
+ dispInfoMomentary("Copied to clipboard", b);
+ }
+ }, false);
+ b.title = "Copy source text to Clipboard"
+ }
+ }
+ function initGrpAction() {
+ var rev = document.getElementById("reverse");
+ if (!rev) return; // Is not grpAction page
+ if (rev.tagName.match(/span/i)) {
+ rev.textContent = " 反転 ";
+ rev.addEventListener("click", reverseChecks, null);
+ }
+ var emailbtn = document.getElementById("email");
+ emailbtn.addEventListener("click", function(ev){
+ // Enlarge box and Select user's checkbox
+ if (!ev.target.checked) return;
+ var x = collectElementsByAttr("div", "class", "foldtabs");
+ if (x && x[0] && x[0].style) {
+ x[0].style.height = "10em";
+ }
+ let myuid = document.getElementById("myuid");
+ if (myuid) {
+ let usel = collectElementsByAttr("input", "name", "usel");
+ if (usel) {
+ for (u of usel) {
+ if (u.value == myuid.value)
+ u.checked = true;
+ }
+ }
+ }
+ }, null);
+ var teamsel = document.getElementById("selteam");
+ if (teamsel) {
+ var usel, p, team;
+ // Select all members of the team
+ teamsel.addEventListener("change", function(ev) {
+ var teamname = teamsel.value,
+ selected = new RegExp('(^| )'+teamname+"($|,)");
+ usel = collectElementsByAttr("input", "name", "usel");
+ if (!usel) return;
+ for (u of usel) {
+ p = u.parentNode; // should be label
+ if (!p) continue;
+ if (teamname == "TEAM") { // Reset all checks
+ u.checked = false; // when "TEAM" is selected
+ } else {
+ p = p.parentNode.parentNode;// should be tr
+ team = nthChildOf(p, 5, "td")
+ if (team && team.textContent
+ && team.textContent.match(selected)) {
+ u.checked = true;
+ }
+ }
+ }
+ }, null);
+ }
+ }
+ function dispInfoMomentary(msg, elem) {
+ // Momentarily display MSG in tooltip-baloon relative to ELEM element.
+ let help = document.createElement("p");
+ elem.style.position = 'relative';
+ elem.style.overflow = 'visible';
+ help.setAttribute("class", "info-tooltip");
+ help.innerHTML = msg;
+ elem.appendChild(help);
+ setTimeout(() => {
+ help.classList.add("dissolving");
+ setTimeout(() => help.remove(), 3000);
+ }, 1000);
+ }
+ function initGrphome() {
+ console.log("initGrphome");
+ // (1)Setup Frozen State Changing Button
+ var ja = navigator.language.match(/ja/i);
+
+ function toggleFrozen(e, rowid) {
+ let tgt = mypath+"?blog_setfrozen+"+rowid;
+ let td = e.target.parentNode;
+ let tr = td.parentNode;
+ fetch(tgt, {
+ method: "POST",
+ headers: {'Content-Type': 'text/html; charset=utf-8'},
+ credentials: "include"
+ }).then(function(resp) {
+ return resp.text();
+ }).then(function(tbody) {
+ try {
+ var json = JSON.parse(tbody);
+ } catch (e) {
+ return;
+ }
+ let state = json.state, newstate, info;
+ if (json.alert) {
+ alert(json.alert)
+ }
+ if (state.match(/frozen/i)) {
+ newstate = "凍結";
+ info = ja ? newstate+"に設定しました" : 'Set Frozen';
+ } else {
+ newstate = null;
+ info = ja ? '稼動に設定しました' : 'Set Running';
+ }
+ tr.setAttribute("class", newstate);
+ dispInfoMomentary(info, td);
+ });
+ }
+ let btn = document.querySelectorAll("button.toggle-frozen");
+ for (let b of btn) {
+ let rowid = null;
+ let td=b.parentNode, tr = td.parentNode, fr, ru;
+ ru = ja ? "動" : "Running";
+ fr = ja ? "凍" : "Frozen";
+ b.setAttribute('frozen-marker', fr);
+ b.setAttribute('running-marker', ru);
+ for (let a of tr.querySelectorAll("a[href]")) {
+ if (a.getAttribute("href").match(/\?replyblog\+([0-9]+)/)) {
+ rowid = parseInt(RegExp.$1);
+ break;
+ }
+ }
+ if (rowid && rowid>0) {
+ b.addEventListener("click", function(e) {
+ if (!btn) return;
+ toggleFrozen(e, rowid);
+ }, false);
+ b.setAttribute("title", "稼動/凍結をその場で切り替えます\n\
+Toggle Running/Frozen ("+rowid+")");
+ }
+ }
+ // (2)Setup Column Sort
+ function sortRowsByCol(tbl, nth) {
+ let rows = [];
+ let after2 = tbl.querySelectorAll("tr:nth-child(n+2)");
+ let thNth = tbl.querySelector(`tr th:nth-child(${nth})`);
+ let title = thNth.getAttribute("title"), direction;
+ let allnumeric = true;
+ if (title.match(/REVERSE /)) {
+ title = title.replace(/REVERSE /, "");
+ direction = -1;
+ thNth.classList.remove("rev");
+ } else {
+ title = title.replace(/sort /, "REVERSE sort ");
+ direction = 1;
+ thNth.classList.add("rev");
+ }
+ for (let tr of after2) {
+ let td = tr.querySelector(`td:nth-child(${nth})`);
+ let text = td.textContent;
+ // XXX: [[workaround]] Frozen or not Frozen
+ if (td.getAttribute("class") == "稼動状態") {
+ text = (tr.getAttribute("class")||"");
+ }
+ if (text.match(/[^0-9]/)) allnumeric = false;
+ rows.push({tr: tr, sortby: text});
+ }
+ if (allnumeric)
+ rows.sort((a,b)=>{
+ let [x, y] = [parseInt(a.sortby), parseInt(b.sortby)];
+ if (x < y) return -direction;
+ if (x > y) return direction;
+ });
+ else
+ rows.sort((a,b)=>{
+ if (a.sortby < b.sortby) return -direction;
+ if (a.sortby > b.sortby) return direction;
+ return 0;
+ return 0;
+ });
+ for (let i of rows) tbl.appendChild(i.tr);
+ thNth.setAttribute("title", title);
+ }
+ let row1 = document.querySelector("table.dumpblogs tr:first-child");
+ if (row1) {
+ let heads = row1.querySelectorAll("th");
+ let tbl = document.querySelector("table.dumpblogs");
+ for (let i=0; i {
+ e.preventDefault();
+ ta.focus();
+ helpMarkdownPreview(ta);
+ });
+ ta.parentNode.appendChild(btn);
+ }
+ function initMath() {
+ mathjax = window.MathJax||document.getElementById("mathjax");
+ if (!mathjax) return;
+ addPreviewButton();
+ }
+ /*
+ * Mermaid operations
+ */
+ var mermaidSelector = ".s4_mermaid";
+ function callMermaid() {
+ (async function() {
+ mermaid.initialize({startOnLoad: false});
+ await mermaid.run({
+ querySelector: mermaidSelector, // Defined in s4-funcs.sh
+ });
+ })();
+ }
+
+ var openSvgAsPdf = null;
+ function initMermaid() {
+ let mm = document.querySelectorAll(mermaidSelector);
+ if (mm.length == 0) return;
+ for (let m of mm) {
+ // Add mermaid source text to tooltip content
+ if (!m.title) m.title = m.textContent;
+ m.src = m.textContent; // innerText is null in nested divs
+ // Add COPY-SOURCE buttons
+ let div = document.createElement("div")
+ div.classList.add("relativebox");
+ let d = document.createElement("button")
+ d.classList.add("printpdf");
+ d.textContent = "PrintPDF";
+ d.addEventListener("click", (e) => {
+ e.preventDefault();
+ if (openSvgAsPdf) {
+ openSvgAsPdf(m.innerHTML);
+ } else {
+ loadJS("js/svgpdf.js", ()=>{
+ openSvgAsPdf = window.openSvgAsPdf;
+ delete window.openSvgAsPdf; // Remove from global scope
+ openSvgAsPdf(m.innerHTML)
+ });
+ }
+ });
+ div.appendChild(d);
+ let b = document.createElement("button")
+ b.classList.add("copy");
+ b.textContent = "Copy Mermaid";
+ b.addEventListener("click", (e) => {
+ e.preventDefault();
+ navigator.clipboard.writeText(m.src);
+ dispInfoMomentary("Mermaid source Copied to clipboard", div);
+ })
+ div.appendChild(b);
+ m.insertAdjacentElement("beforebegin", div);
+ }
+ if (!mmScript) {
+ loadJS("https://unpkg.com/mermaid/dist/mermaid.min.js", callMermaid);
+ } else {
+ callMermaid();
+ }
+ addPreviewButton();
+ }
+ function rewriteReplyHover(unit) {
+ function getTextById(id) {
+ let repltd = document.getElementById(id);
+ if (repltd) {
+ let txt = repltd.innerText,
+ authtd = repltd.parentNode.getElementsByTagName("td")[0],
+ author = authtd.querySelector("a.author").innerText,
+ digest = txt.split("\n").splice(0, hoverTextLines).join("\n");
+ return escapeChars("[[ "+author+" ]]\n"+digest);
+ } else
+ return "";
+ }
+ unit = unit||document;
+ for (let td of unit.querySelectorAll("td.repl")) {
+ let firstC = td.firstChild;
+ // Direct replacing innerHTML breaks embedded DOM event handlers.
+ // So, we split td.repl into elements and replace the first
+ // textNode(nodeType==3) with hover-text embeded content.
+ if (firstC.nodeType==3 && firstC.nodeValue.startsWith(">#")) {
+ let newline = firstC.nodeValue.indexOf("\n");
+ let firstline;
+ if (newline > 0) {
+ firstline = firstC.nodeValue.substring(0, 1+newline);
+ firstC.nodeValue = firstC.nodeValue.substring(1+newline);
+ } else {
+ // Cannot be reached here, but leave this for robustness
+ firstline = firstC.nodeValue;
+ firstC.nodeValue = "";
+ }
+ td.insertAdjacentHTML(
+ 'afterbegin',
+ escapeChars(firstline).replace(
+ /#([0-9]+)/g,
+ (match, start, whole) => {
+ let id = RegExp.$1
+ return '' + match + '';
+ }));
+ }
+ }
+ }
+ function initReplyHover(unit) {
+ // https://stackoverflow.com/questions/60154233/event-when-typesetting-is-done-mathjax-3
+ if (mathjax && MathJax.startup)
+ MathJax.startup.promise.then(()=>rewriteReplyHover());
+ else
+ rewriteReplyHover();
+ }
+ var getHandoutCSV;
+ function initGetHandoutCSV() {
+ getHandoutCSV = document.getElementById("gethandoutcsv");
+ if (!getHandoutCSV) return;
+ document.getElementById("bommsg").innerText =
+ `Excelで開く場合は上記CSVリンクをCtrlを押しながら。
+You need to click CSV link above with Ctrl-key when you handle CSV with Excel`;
+ getHandoutCSV.addEventListener("click", (e) => {
+ e.preventDefault(); // Stop visiting link
+ let bom = e.ctrlKey;
+ let csv = document.getElementById("totalcsv");
+ if (!csv || !csv.textContent) return;
+ let fn = "report-count", plus=myurl.lastIndexOf("+");
+ if (plus) fn += ("-"+myurl.substring(1+plus));
+ fn = fn.replace(/#.*/, "");
+ downloadFile(fn+".csv", csv.textContent, bom);
+ });
+ }
+ function init() {
+ isOlderJS = !("insertAdjacentElement" in document.body);
+ initGrpAction();
+ initBlogs();
+ initFileInput();
+ initTextarea();
+ initGrphome();
+ initMath();
+ initMermaid();
+ initReplyHover();
+ initGetHandoutCSV();
+ }
+ document.addEventListener('DOMContentLoaded', init, null);
+})();