generated at
r_takaishi

ここは、日記でもまとまった記事でもないものをあれこれ書いていく場所です

script.js
scrapbox.TimeStamp.addFormat("YYYY-MM-DD[\n\n][#Journal] #YYYY-MM-DD #YYYY #YYYY-MM #MM-DD");



script.js
// From https://scrapbox.io/customize/クリックでON%2FOFFできるチェックボックス setTimeout(() => { // チェックボックスとして使用する文字セットのリスト const checkboxSetList = [ ['⬜', '✅'] ]; const allBoxes = checkboxSetList.reduce((accu, current) => accu.concat(current), []); const startsWithBoxReg = new RegExp('^\\s*(' + allBoxes.join('|') + ')'); const targetProject = scrapbox.Project.name; class KeydownEvent { constructor() { this.textArea = document.getElementById('text-input'); this.event = document.createEvent('UIEvent'); this.event.initEvent('keydown', true, true); } dispatch(keyCode, withShift = false, withCtrl = false, withAlt = false, withCommand = false) { this.event.keyCode = keyCode; this.event.shiftKey = withShift; this.event.ctrlKey = withCtrl; this.event.altKey = withAlt; this.event.metaKey = withCommand; this.textArea.dispatchEvent(this.event); } } // ボックスクリックでオンオフする $('#app-container').off(`click.toggleCheckBox_${targetProject}`, '.lines'); $('#app-container').on(`click.toggleCheckBox_${targetProject}`, '.lines', async event => { if (scrapbox.Project.name !== targetProject) { $('#app-container').off(`click.toggleCheckBox_${targetProject}`, '.lines'); return; } const target = event.target; if (!isFirstElementChild(target)||!isCharSpan(target, allBoxes)) return; await new Promise(resolve => setTimeout(resolve, 30)); let lineString; try { lineString = getCursorLineString(); } catch (err) { console.log(err); return; } if (!startsWithBoxReg.test(lineString)) return; const targetX = target.getBoundingClientRect().left; const cursorX = document.getElementsByClassName('cursor')[0].getBoundingClientRect().left; const keydownEvent = new KeydownEvent(); if (cursorX <= targetX) { keydownEvent.dispatch(39); // → } keydownEvent.dispatch(8); // Backspace const newBox = (() => { const trimmedLineString = lineString.trim(); for (const checkboxSet of checkboxSetList) { for (let i = 0; i < checkboxSet.length; i++) { if (trimmedLineString.startsWith(checkboxSet[i])) { return checkboxSet[i + 1 < checkboxSet.length ? i + 1 : 0]; } } } return target.textContent; })(); writeText(newBox); // この下のコメントアウトを解除すると、checked時に取消線を入れて時刻を追記します // Mac、Porterでのみ動作します /* if (/Mobile/.test(navigator.userAgent)) return; const targetBoxSet = checkboxSetList[0]; if (!targetBoxSet.includes(newBox) || newBox === targetBoxSet[0]) return; await new Promise(resolve => setTimeout(resolve, 30)); keydownEvent.dispatch(39, true, false, false, true); // shift + command + → writeText('-'); keydownEvent.dispatch(39, false, false, false, true); // command + → const now = moment().format('HH:mm'); writeText(` ${now}`); */ }); // ボックス行で改行すると次行にボックス自動挿入 $('#text-input').off(`keydown.autoInsertCheckBox_${targetProject}`); $('#text-input').on(`keydown.autoInsertCheckBox_${targetProject}`, async event => { if (scrapbox.Project.name !== targetProject) { $('#text-input').off(`keydown.autoInsertCheckBox_${targetProject}`); return; } switch (event.key) { case 'Enter': { let currentLineString; try { currentLineString = getCursorLineString(); } catch (err) { console.log(err); return; } if (!startsWithBoxReg.test(currentLineString)) return; await new Promise(resolve => setTimeout(resolve, 30)); let nextLineString; try { nextLineString = getCursorLineString(); } catch (err) { console.log(err); return; } if (!startsWithBoxReg.test(nextLineString)) { const trimmedLineString = currentLineString.trim(); const targetBoxSet = checkboxSetList.find(boxSet => { return boxSet.some(box => trimmedLineString.startsWith(box)); }); writeText(targetBoxSet[0]); } return; } default: { return; } } }); function isFirstElementChild(element) { return element.parentNode.firstElementChild === element; } function getCursorLineString() { return document.querySelector('.lines div.line.cursor-line').textContent; } function isCharSpan(element, targetCharList) { return element.tagName === 'SPAN' && targetCharList.includes(element.textContent) && element.classList.value.split(' ').some(value => /^c\-\d+$/.test(value)); } function writeText(text) { const textArea = document.getElementById('text-input'); textArea.value = text; textArea.dispatchEvent(new InputEvent('input', {bubbles: true, cancelable: true})); } }, 1500);

styles.css
a#Templates.tool-btn:hover { text-decoration: none } a#Templates.tool-btn::before { position: absolute; left: calc(46px/3 - 1px); content: '\f067'; font: 21px/46px 'FontAwesome' } a#Templates.tool-btn img { opacity: 0 }

script.js
addTemplateItemsToPageMenu() function addTemplateItemsToPageMenu() { // テンプレートメニューの定義ここから ---------- 下の解説を見てね!! ---------- const __templates = [ { title: '📄 週報テンプレート', template: '/api/code/rtakaishi/テンプレート/週報テンプレートS.js' } ] // テンプレートメニューの定義ここまで ---------- const __templMenuTitle = 'Templates' scrapbox.PageMenu.addMenu({ title: __templMenuTitle, image: '/assets/img/logo.png', onClick: () => { } }) __templates.forEach((i) => { scrapbox.PageMenu(__templMenuTitle).addItem({ title: i.title, onClick: () => { __loadTemplate(i.template) }}) }) var __loadTemplate = function (templateUrl) { if (scrapbox.Page.lines && scrapbox.Page.lines.length == 1) { // タイトル行をクリックしたことにする const line = document.getElementById('L' + scrapbox.Page.lines[0].id) const lastChar = $(line).find('span[class^="c-"]').last().get(0) __mimicClick(line.id, line.offsetWidth, lastChar.offsetTop + 10) // テンプレートを読み込む $('#text-input').load(templateUrl, function (response, status, xhr) { if (status == "success") { try { // 読み込んだテンプレートをテキストエリアにセットしまして const textarea = document.getElementById('text-input') textarea.value = /\.js$/.test(templateUrl) ? eval(response) : response // テキストエリアのinputイベントを出しまして const event = document.createEvent('Event') event.initEvent('input', true, true) textarea.dispatchEvent(event) // 選択状態を解除したいのでもう1回クリックしとく __mimicClick(line.id, line.offsetWidth, lastChar.offsetTop + 10) } catch (ex) { console.log("だめでした>< \n" + ex) } } else { console.log("だめでした>< \n" + status) } }) } } const __mimicClick = (targetId, left, top) => { const genEvent = type => { const event = document.createEvent("MouseEvents") event.initMouseEvent(type, true, true, window, 1, 0, 0, left, top, false, false, false, false, 0, null) return event } const elm = document.getElementById(targetId) elm.dispatchEvent(genEvent("mousedown")) elm.dispatchEvent(genEvent("mouseup")) elm.dispatchEvent(genEvent("click")) } }