scrapbox-selection-2
全ッ然気づかなかった……takker.icon
気づいた背景:
2. takker.icon「これってScrapboxの仕様にかかわらず選択範囲の文字列を取得する方法があるのでは?」
3. document.getElementById('text-input').valueが怪しそうなので中身を確認
4. 予想通り入っていた!!!!
なお、選択範囲の開始・終了位置を計算するには、依然このscriptが必要になる
2021-01-10 03:56:34 この結果を元に新しいscriptを作った
/icons/hr.icon
2021-01-01
2020-12-30
08:38:51 選択範囲が一瞬で消えたときにerrorが出てしまう問題を解消した
テストコードtakker.icon
code:test1.js
import {selection} from '/api/code/takker/scrapbox-selection-2/script.js';
window.selection = selection;
const observer = new MutationObserver(mutations =>
mutations.forEach(mutation => console.log(selection.text)));
observer.observe(document.getElementsByClassName('cursor')?.0, {attributes: true}); dependencies
code:script.js
import {scrapboxDOM} from '/api/code/takker/scrapbox-dom-accessor/script.js';
import {getCharBorder} from '/api/code/takker/scrapbox-position/script.js';
import {CursorObserver} from '/api/code/takker/scrapbox-cursor-observer/script.js';
import {cursor} from '/api/code/takker/scrapbox-cursor-position-3/script.js';
import {char as c} from '/api/code/takker/scrapbox-char-info/script.js';
import {line as l} from '/api/code/takker/scrapbox-line-info-2/script.js';
// 左右の文字のDOMの間の番号を取得する
const borderIndex = ({left,right}) => right ? c(right).index : left ? c(left).index + 1 : undefined;
class Selection {
constructor() {
this._cursorObserver = undefined;
// 先に.selectionの監視を開始する
this._selectionObserver = new MutationObserver(mutations => {
.some(element =>element.classList.contains('selections'))) {
this._selectMode = true;
this._recordSelectionEdge(); // 選択範囲の開始位置を記録しておく
}
.some(element =>element.classList.contains('selections'))) {
this._selectMode = false;
}
});
this._selectionObserver.observe(scrapboxDOM.editor, { childList: true });
this._cursorObserver = new CursorObserver();
this._cursorObserver.start();
this._recordedEdge = {};
}
// 選択範囲が存在するかどうか
get exist() {
return this._selectMode;
}
// 選択範囲の開始位置と終了位置を返す
get range() {
// 現在のcursorの位置
//console.log({cursorEdge: this._cursorObserver, recordedEdge: this._recordedEdge});
// 順番を判定する
if (this._recordedEdge.lineNo > this._cursorObserver.lineNo) {
return {
start: this._cursorObserver,
end: this._recordedEdge,
};
}
if (this._recordedEdge.lineNo < this._cursorObserver.lineNo) {
return {
start: this._recordedEdge,
end: this._cursorObserver,
};
}
// 行が同じの場合は列で比較する
if (this._recordedEdge.index > this._cursorObserver.index) {
return {
start: this._cursorObserver,
end: this._recordedEdge,
};
}
if (this._recordedEdge.index < this._cursorObserver.index) {
return {
start: this._recordedEdge,
end: this._cursorObserver,
};
}
// 完全に位置が一致している場合
}
get text() {
const {start, end, message} = this.range;
if (message) {
console.log(message);
return [];
}
const texts = scrapbox.Page.lines.map(line => line.text);
start: {
},
end: {
},
});*/
// 選択範囲が一行に収まっているとき
if (start.lineNo === end.lineNo) {
return [textsstart.lineNo.substring(start.index, end.index)]; }
// 選択範囲が複数行にまたがるとき
return [
...texts.slice(start.lineNo + 1, 1 + end.lineNo - 1),
];
}
//cursorがない方の選択範囲の端を取得する
// この関数を呼び出すタイミングではまだ_cursorObserverが呼び出されていないので、独自にcursorの位置を取得する
_recordSelectionEdge() {
if (!this.exist) return undefined;
const selections = scrapboxDOM.selections?.getElementsByClassName('selection');
// 一瞬で選択範囲が消えるとselectionsがundefindeになる場合がある
if (!selections || selections?.length === 0) {
this._selectMode = false;
return undefined;
}
// 選択範囲の端の座標
const startRect = selections0.getBoundingClientRect(); const endRect = (selections2 ?? selections0).getBoundingClientRect(); // 選択範囲の端の文字を取得する
const start = getCharBorder({x: startRect.left, y: startRect.top});
const end = getCharBorder({x: endRect.right, y: endRect.bottom});
// 行数と列数を計算する
const startEdge = {
index: borderIndex(start),
lineNo: l(start.line).index,
};
const endEdge = {
index: borderIndex(end),
lineNo: l(end.line).index,
};
// cursorの位置を取得する
const temp = cursor();
const cursorEdge = {
index: temp.index,
lineNo: l(temp.line).index,
};
// 選択範囲が一行のときは、選択範囲の端の座標から計算した位置を使う
// 1行かつ選択範囲の取得開始直後なら記法が展開されていることが保証されている
if (startEdge.lineNo === endEdge.lineNo) {
if (cursorEdge.index === startEdge.index
&& cursorEdge.lineNo === startEdge.lineNo) {
this._recordedEdge = endEdge;
} else {
this._recordedEdge = startEdge;
}
return;
}
// 選択範囲が複数行に渡るときは、記録しておいたカーソルの位置を用いる
// 記法が隠れている可能性があるので、選択範囲の座標から位置を計算できない
this._recordedEdge = {
index: this._cursorObserver.index,
lineNo: this._cursorObserver.lineNo,
};
}
}
export const selection = new Selection();