編集バーを生やすUserScript
Scrapboxの編集画面に編集バーを生やすUserScriptのこと @ryot_g: これつけたらScrapboxがめちゃくちゃ使いやすくなった https://gyazo.com/5d52b3d50b717f250a7b174d3dbccc92
ryota.icon知らないうちにページができてる笑
ありがとうございます
下にコード置いておきます
問題点
ryota.icon編集バーの下に文字が隠れちゃう事がある
ので気になる方は右端とかに寄せてみてもいいかもしれません
もしソフトウェアキーボード表示時の、強制スクロール位置調整方法を知ってたら教えて欲しいです!!
ryota.iconページ一覧では編集バーを表示しないようにしているが、検索結果ページなどで表示されてしまう
たぶん直せるけどめんどくて直してません
だれか、、、お願いします
code:javascript
$('body').append('<div class="input_supporter" id="input_supporter"><button class="ins_btn" id="ins_link">[]</button><button class="ins_btn" id="ins_hash">#</button><button class="ins_btn" id="ins_asterisk">*</button><button class="ins_btn" id="ins_slash">/</button><button class="ins_btn" id="ins_greater">></button><button class="ins_btn" id="ins_code"></button><button class="ins_btn" id="ins_period">.</button><button class="ins_btn" id="ins_plus">+</button></div>');
if(location.pathname === "/project_name/") {
$('#input_supporter').addClass('ins_invisible');
}
// domの更新を検知
const target = document.getElementsByClassName("page-wrapper")0; const observer = new MutationObserver((recs) => {
if (!recs0.target.classList.contains("enter")) { if(location.pathname === "/project_name/") {
$('#input_supporter').addClass('ins_invisible');
} else {
$('#input_supporter').removeClass('ins_invisible');
}
}
});
observer.observe(target, {attributes: true, attributeFilter: "class"}); const ins_input = function(value) {
const cursor = document.getElementById('text-input');
cursor.focus();
document.execCommand('insertText', null, value);
};
$('#ins_link').on('touchend', () => ins_input("[]"));
$('#ins_hash').on('touchend', () => ins_input("#"));
$('#ins_asterisk').on('touchend', () => ins_input("*"));
$('#ins_slash').on('touchend', () => ins_input("/"));
$('#ins_greater').on('touchend', () => ins_input("> "));
$('#ins_code').on('touchend', () => ins_input(""));
$('#ins_period').on('touchend', () => ins_input("."));
$('#ins_plus').on('touchend', () => ins_input("+"));
code:style.css
.input_supporter {
position: fixed;
right: 0;
bottom: 0;
left: 0;
justify-content: space-between;
display: none;
width: 100%;
border-radius: 8px 8px 0 0;
box-shadow: rgb(15 15 15 / 5%) 0px 0px 0px 1px, rgb(15 15 15 / 10%) 0px 3px 6px, rgb(15 15 15 / 20%) 0px 9px 24px;
z-index: 300;
}
.ins_btn {
width: 12.5%;
width: calc(100% / 8);
padding: 12px 0;
background: none;
border: none;
}
.ins_btn:not(:first-child) {
}
.ins_invisible {
display: none !important;
}
@media (max-width: 767px) {
.input_supporter {
display: flex;
}
.status-bar {
bottom: 46px;
}
.page-status {
border-bottom: 1px solid var(--tool-light-color, #a9aaaf); border-radius: 3px 0 0 3px;
}
}
すごいyosider.icon
なるほど。単純に下に生やすだけでいいみたいですねtakker.icon
code readingしつつ書き直してみる
あー、.page-statusの位置を調節しないといけないのか
単純にDOMを挿入しただけだと重なってしまう
code:script.js
import { defaultSettings, setup } from "./mod.js";
setup(defaultSettings);
code:mod.js
const c=["[]","#","*","/",">","",".",">","+"].map(t=>({title:t,onClick:()=>t})),r=t=>{const d=u();d.append(...t.map(({title:p,className:i,onClick:a})=>l(p,a,i)));const o=document.createElement("div"),e=o.attachShadow({mode:"open"}),n=document.createElement("style");n.textContent=".input-supporter{position:fixed;right:0;bottom:0;left:0;justify-content:space-between;width:100%;border-radius:8px 8px 0 0;background:#FFF;border:solid 1px #37352f17;box-shadow:#0f0f0f0d 0 0 0 1px,#0f0f0f1a 0 3px 6px,#0f0f0f33 0 9px 24px;z-index:300}.ins-btn{width:12.5%;width:calc(100% / 8);padding:12px 0;background:none;border:none;color:#111}.ins-btn:not(:first-child){border-left:solid 1px #37352f17}@media (max-width: 767px){.input-supporter{display:flex}}",e.appendChild(n),e.appendChild(d),document.body.append(o);const s=()=>o.style.display=scrapbox.Layout==="page"?"":"none";s(),scrapbox.addListener("layout:changed",s)},u=()=>{const t=document.createElement("div");return t.classList.add("input-supporter"),t},l=(t,d,o)=>{const e=document.createElement("button");return e.classList.add("ins-btn"),o&&e.classList.add(o),e.textContent=t,e.addEventListener("click",()=>{const n=document.getElementById("text-input");if(!n)throw Error("#text-input is not ditected.");n.focus(),n.value=d();const s=new InputEvent("input",{bubbles:!0});n.dispatchEvent(s)}),e};export{c as defaultSettings};export{r as setup}; code:sh
code:mod.ts
/// <reference no-default-lib="true" />
/// <reference lib="esnext" />
/// <reference lib="dom" />
declare const scrapbox: Scrapbox;
export interface Button {
title: string;
onClick: () => string;
className?: string;
};
export const defaultSettings: Button[] = ["[]", "#", "*", "/", ">", "", ".", ">", "+"]
.map(
(text) => ({
title: text,
onClick: () => text,
})
);
export const setup = (settings: Button[]) => {
const supporter = makeSupporter();
supporter.append(...settings.map(
({ title, className, onClick }) => makeButton(title, onClick, className)
));
const app = document.createElement("div");
const shadowRoot = app.attachShadow({ mode: "open" });
const style = document.createElement("style");
style.textContent = ".input-supporter{position:fixed;right:0;bottom:0;left:0;justify-content:space-between;width:100%;border-radius:8px 8px 0 0;background:#FFF;border:solid 1px #37352f17;box-shadow:#0f0f0f0d 0 0 0 1px,#0f0f0f1a 0 3px 6px,#0f0f0f33 0 9px 24px;z-index:300}.ins-btn{width:12.5%;width:calc(100% / 8);padding:12px 0;background:none;border:none;color:#111}.ins-btn:not(:first-child){border-left:solid 1px #37352f17}@media (max-width: 767px){.input-supporter{display:flex}}"; shadowRoot.appendChild(style);
shadowRoot.appendChild(supporter);
document.body.append(app);
const changeVisible = () =>
app.style.display = scrapbox.Layout === "page" ? "" : "none";
changeVisible();
scrapbox.addListener("layout:changed", changeVisible);
};
const makeSupporter = () => {
const div = document.createElement("div");
div.classList.add("input-supporter");
return div;
};
const makeButton = (title: string, onClick: () => string, className?: string) => {
const button = document.createElement("button");
button.classList.add("ins-btn");
if (className) button.classList.add(className);
button.textContent = title;
button.addEventListener("click", () => {
const cursor = document.getElementById('text-input') as HTMLTextAreaElement | null;
if (!cursor) {
throw Error("#text-input is not ditected.");
}
cursor.focus();
cursor.value = onClick();
const event = new InputEvent("input", { bubbles: true });
cursor.dispatchEvent(event);
});
return button;
};
あっだめだ。クリックイベントとか対応してなかった
機能追加しないと
code:mod2.ts
/// <reference no-default-lib="true" />
/// <reference lib="esnext" />
/// <reference lib="dom" />
declare const scrapbox: Scrapbox;
export interface Button {
title: string;
onClick: () => string;
className?: string;
};
export const defaultSettings: Button[] = ["[]", "#", "*", "/", ">", "", ".", ">", "+"]
.map(
(text) => ({
title: text,
onClick: () => text,
})
);
export const setup = (settings: Button[]) => {
const supporter = makeSupporter();
supporter.append(...settings.map(
({ title, className, onClick }) => makeButton(title, onClick, className)
));
const app = document.createElement("div");
const shadowRoot = app.attachShadow({ mode: "open" });
const style = document.createElement("style");
style.textContent = ".input-supporter{position:fixed;right:0;bottom:0;left:0;justify-content:space-between;width:100%;border-radius:8px 8px 0 0;background:#FFF;border:solid 1px #37352f17;box-shadow:#0f0f0f0d 0 0 0 1px,#0f0f0f1a 0 3px 6px,#0f0f0f33 0 9px 24px;z-index:300}.ins-btn{width:12.5%;width:calc(100% / 8);padding:12px 0;background:none;border:none;color:#111}.ins-btn:not(:first-child){border-left:solid 1px #37352f17}@media (max-width: 767px){.input-supporter{display:flex}}"; shadowRoot.appendChild(style);
shadowRoot.appendChild(supporter);
document.body.append(app);
const changeVisible = () =>
app.style.display = scrapbox.Layout === "page" ? "" : "none";
changeVisible();
scrapbox.addListener("layout:changed", changeVisible);
};
const makeSupporter = () => {
const div = document.createElement("div");
div.classList.add("input-supporter");
return div;
};
const makeButton = (title: string, onClick: () => string, className?: string) => {
const button = document.createElement("button");
button.classList.add("ins-btn");
if (className) button.classList.add(className);
button.textContent = title;
button.addEventListener("click", () => {
insertText(onClick());
});
return button;
};