failed-type-setting-project/script.js

266 lines
9.5 KiB
JavaScript
Raw Normal View History

2021-05-25 20:30:40 +08:00
document.getElementById("info").innerHTML += "paper width (px)" + document.getElementById("paper").offsetWidth + "<br/>";
function css(element, property) {
return window.getComputedStyle(element, null).getPropertyValue(property);
}
var paper = document.getElementById('paper');
var paperPage1 = document.getElementById('paper-page1');
var font_family = css(paper, 'font-family');
var font_size = css(paper, 'font-size');
paper.addEventListener('input', getWordsWidth);
paper.addEventListener('keydown', function (e) {
if (e.key == " ") { //enter
e.preventDefault(); //Prevent default browser behavior
var sel;
var range;
sel = window.getSelection();
range = sel.getRangeAt(0);
range.deleteContents();
var textNode = document.createTextNode('\u00A0'); // no linebreaking-space
range.insertNode(textNode);
range.setStartAfter(textNode);
sel.addRange(range);
getWordsWidth();
// paper.innerHTML+= paper.innerHTML;
//var currentPage = document.getElementById(getCaretCurrentPageId());
//var currentRange = getCursorLengthRange(currentPage);
//var HTMLBeforeCaret = rangeToHTMLFragement(currentRange);
}
});
// 如果游標在 contentdiveditable id "paper-page1" 裡面,
// 該函數返回 "paper-page1"
function getCaretCurrentPageId() {
var anchorNode = window.getSelection().anchorNode;
var currentNode = anchorNode;
while (currentNode.id === undefined || !(currentNode.id.match(/^paper-page\d+/))) {
currentNode = currentNode.parentNode;
}
return currentNode.id;
}
// 得到子節點(文字物件)
// ["dolore", [ "m ips", ["um si"], "t am"], "et"]
function getChildNodes(ele) {
var res_array;
res_array = [];
if (ele.nodeType == Node.TEXT_NODE) {
return ele;
}
else {
for (var i = 0; i < ele.childNodes.length; i++) {
res_array.push(getChildNodes((ele.childNodes[i])));
}
return res_array;
}
}
// 平坦化陣列
// [a, [b, c, d], [[e]]] => [a, b, c, d, e]
function flatten(arr) {
if (!Array.isArray(arr)) {
return arr;
}
else {
var result = [];
for (var i = 0; i < arr.length; i++) {
if (Array.isArray(arr[i])) {
result = result.concat(flatten(arr[i]));
}
else {
result.push(arr[i]);
}
}
return result;
}
}
/* 從第幾個字到第幾個字選 range. */
function selecRengeFromCharToChar(i, j, ele) {
var range = document.createRange();
var sel = document.getSelection();
var flattened_ar = flatten(getChildNodes(ele));
range.selectNodeContents(ele);
var ran_start = i;
var ran_end = j;
var ran_start_is_set = false;
for (var i = 0; i < flattened_ar.length; i++) {
var fragement_text_length = flattened_ar[i].textContent.length;
// 如果 ran_start > 碎片長度
if (ran_start > fragement_text_length) {
ran_start -= fragement_text_length;
ran_end -= fragement_text_length;
// 如果 ran_start <= 碎片長度
}
else if (ran_start <= fragement_text_length && ran_start_is_set == false) {
range.setStart(flattened_ar[i], ran_start);
ran_start_is_set = true;
// 如果 ran_end > 碎片長度
if (ran_end > fragement_text_length) {
ran_end -= fragement_text_length;
// 如果 ran_end <= 碎片長度setEnd 中止迴圈
}
else {
range.setEnd(flattened_ar[i], ran_end);
break;
}
// 如果 ran_end > 碎片長度
}
else if (ran_end > fragement_text_length && ran_start_is_set == true) {
ran_end -= fragement_text_length;
}
// 如果 ran_end <= 碎片長度setEnd 中止迴圈
else {
range.setEnd(flattened_ar[i], ran_end);
break;
}
}
var sel = window.getSelection();
sel.removeAllRanges();
sel.addRange(range);
return range;
}
/*
設置游標位置於 ele 要素的第 col 個字不含標籤例子
HTML <div>dolore<i>m ips<b>um si</b>t am</i>et&nbsp;1234<div>
setCaret(document.getElementById('paper-page1'),10)
V CARET
<div>dolore<i>m ip|s<b>um si</b>t am</i>et&nbsp;1234<div>
*/
function setCaret(ele, col) {
var range = document.createRange();
var sel = document.getSelection();
var flattened_ar = flatten(getChildNodes(ele)); // flattened array
range.selectNodeContents(ele);
var ran_start = col;
for (var i = 0; i < flattened_ar.length; i++) {
var fragement_text_length = flattened_ar[i].textContent.length;
if (ran_start > fragement_text_length) {
ran_start -= fragement_text_length;
}
else {
range.setEnd(flattened_ar[i], ran_start);
range.collapse();
break;
}
}
var sel = window.getSelection();
sel.removeAllRanges();
sel.addRange(range);
}
// 將座標轉成座標所在位置的 range
function getCursorLengthRange(ele) {
var win = ele.ownerDocument.defaultView;
var range = win.getSelection().getRangeAt(0);
var cloneRange = range.cloneRange();
cloneRange.selectNodeContents(ele);
cloneRange.setEnd(range.endContainer, range.endOffset);
return cloneRange;
}
// 將座標 range 轉成字串的長度
function rangeToStringLen(range) {
return range.toString().length;
}
// 將座標位置 range 轉成 html 斷片
function rangeToHTMLFragement(range) {
var nodes = range.cloneContents().childNodes;
var result = "";
for (var i = 0; i < nodes.length; i++) {
var parentNode = nodes[i].parentNode;
var div = document.createElement("div");
div.appendChild(parentNode);
if (typeof (nodes[i].outerHTML) === "undefined") {
result += nodes[i].textContent;
}
else {
result += nodes[i].outerHTML;
}
console.log("Parent Node" + div.outerHTML);
}
return result;
}
// 得到一個 word 或是 character 的寬度
function getTextWidth(text, fontfamily, fontsize) {
console.log(text);
var decodedText = decodeEntities(text);
var canvas = document.createElement("canvas");
var context = canvas.getContext("2d");
context.font = fontsize + " " + fontfamily;
var width = context.measureText(decodedText).width;
return width;
}
// 得到字寬
function getWordsWidth() {
document.getElementById('line-info').innerHTML = "";
var array = paper.childNodes;
var res = [];
for (var i = 0; i < array.length; i++) {
if (array[i].nodeType != Node.TEXT_NODE) {
res.push(array[i]);
}
}
var innerArray = res.map(function (x) { return x.innerHTML; });
var innerHTMLTotal = innerArray.reduce(function (x, y) { return (x + y); });
var innerHTMLRemoveTags = innerHTMLTotal.replace(/[<][\/]?[^<]+[\/]?[>]/gi, ""); // 移除標籤
var innerHTMLSplitted = innerHTMLRemoveTags.split(/( |\s|&nbsp;|[⺀-\u2efe\u3000-〾㇀-\u31ee㌀-㏾㐀-\u4dbe一-\u9ffe豈-\ufafe-]|[\ud840-\ud868\ud86a-\ud86c][\udc00-\udfff]|\ud869[\udc00-\udede\udf00-\udfff]|\ud86d[\udc00-\udf3e\udf40-\udfff]|\ud86e[\udc00-\udc1e]|\ud87e[\udc00-\ude1e])/).filter(function (item) { return item != ""; });
console.log(innerHTMLSplitted);
//var innerHTMLSplittedLength = innerHTMLSplitted.map((x)=>x.length)
//var innerHTMLSelectedRange = [];
/*var sum = 0
for (var i=0; i<innerHTMLSplittedLength.length;i++){
var head = sum;
var tail = sum + innerHTMLSplittedLength[i];
innerHTMLSelectedRange.push([head, tail]);
sum+= innerHTMLSplittedLength[i];
}*/
/*var innerHTMLSplittedRange = innerHTMLSelectedRange.map((x) => rangeToHTMLFragement(selecRengeFromCharToChar(x[0],x[1],paper)))
console.log("Range 結果"+innerHTMLSplittedRange);*/
var textWidthList = innerHTMLSplitted.map(function (x) { return getTextWidth(x, font_family, font_size); });
var lineInfoLength = [];
for (var i = 0; i < innerHTMLSplitted.length; i++) {
var object = { "content": innerHTMLSplitted[i],
"length": textWidthList[i] };
document.getElementById("line-info").innerHTML += "(" + innerHTMLSplitted[i] + ",";
document.getElementById("line-info").innerHTML += textWidthList[i] + ")";
lineInfoLength.push(object);
}
// document.getElementById("info").innerHTML += lineInfoLength;
}
// 將要在地幾個字插入符號,改為修正為在有標籤的 HTML 的片段中,第幾個不算標籤的字插入符號
/*
> getrealcol(5, "example")
> 5
> getrealcol(5, "e<em>xam</em>ple")
> 14
*/
function getrealcol(n, str) {
var arr = str.split(RegExp("(<[^<>]+>)")).map(function (x) { return ({ cont: x, len: x.length }); });
var j = 0;
var k = 0;
for (var i = 0; i < arr.length; i++) {
if (arr[i].cont.match(/^[<]/)) {
continue;
}
else {
if (n > arr[i].len) {
n = n - arr[i].len;
}
else {
j = i;
k = n;
break;
}
}
;
}
var res_col = 0;
for (var i = 0; i < j; i++) {
res_col += arr[i].len;
}
res_col += k;
return res_col;
}
// 解碼 &1234; 這種東西用
function decodeEntities(encodedString) {
var textArea = document.createElement('textarea');
textArea.innerHTML = encodedString;
return textArea.value;
}