diff --git a/web/admin/print/tablet_edit/editorNewOne.html b/web/admin/print/tablet_edit/editorNewOne.html index c034495..8c1c499 100644 --- a/web/admin/print/tablet_edit/editorNewOne.html +++ b/web/admin/print/tablet_edit/editorNewOne.html @@ -445,34 +445,34 @@ }); let pageStyle = ``; + * { -webkit-print-color-adjust: exact !important; print-color-adjust: exact !important; color-adjust: exact !important; } + .vertical-text { writing-mode: vertical-rl !important; -webkit-writing-mode: vertical-rl !important; text-orientation: mixed !important; } + body { overflow: visible !important; } + @media print { + :host { width:auto !important; height:auto !important; } + @page { size:${printSize.width}mm ${printSize.height}mm !important; margin:0; } + html, body, form, .full-home, .printArea, .canvas-area { height: auto !important; width: auto !important; overflow: visible !important; margin: 0 !important; padding: 0 !important; display: block !important; } + .no-print, #customMenu { display: none !important; } + .canvas-area { display:flex !important; flex-direction: row !important; justify-content:center !important; align-items:center !important; } + .tablet-paper { position: relative !important; display: block !important; break-inline:avoid; page-break-inline:avoid; break-after: page !important; page-break-after: always !important; margin: 0 !important; border: none !important; background-repeat: no-repeat; background-size: 100% 100%; } + .tablet-element { position: absolute !important; white-space: normal; color: black !important; } + } + .roster-container { width: 100%; height: 100%; writing-mode: vertical-rl; display: flex; flex-direction: row; align-items: center; justify-content: center; gap: 20px; } + .roster-row { display: flex; flex-direction: row-reverse; justify-content: center; gap: 8px; margin-left: 10px; } + .name-group { display: flex; flex-direction: column; justify-content: center; align-items: center; } + .roster-name { text-orientation: upright; white-space: normal; line-height: 1.2; font-family: DFKai-sb; width: fit-content; } + .ancestor-wrapper { writing-mode: horizontal-tb; display: flex; flex-direction: column; align-items: center; justify-content: flex-start; width: fit-content; } + .main-name { line-height: 1.2; } + .sub-text { font-size: ${ancestorFontSize}px; line-height: 1.2; margin-top: 4px; white-space: normal; writing-mode:vertical-rl; } + .canvas-area { width: ${pageSize.width}mm; height: ${pageSize.height}mm; break-after: page; page-break-after: always; display:flex !important; justify-content:center; } + .tablet-paper { background-color: white; display: inline-block; width: ${size.width}mm !important; height: ${size.height}mm !important; position: relative; margin-bottom: 0; background-image: url(${img.path}); background-size: 100% 100%; break-inline:avoid; page-break-inline:avoid; } + .tablet-element { cursor: move; padding: 4px; color: black !important; border: 1px solid transparent; transition: writing-mode 0.3s, transform 0.2s; } + .tablet-element:hover { border-color: rgba(13, 110, 253, 0.3); } + .tablet-paper:last-child { page-break-after: auto; } + .tablet-element span { z-index: 999; } + .selectedItem .canselectItem { font-size: 18px; } + .selectedItem, .rounded-pill .canselectItem, .rounded-pill { font-size: 12px; } + `; $("#pageStyle").remove(); $("head").append(pageStyle); @@ -494,11 +494,11 @@ this.alive.forEach(x => { let f = this.familyMembers.find(z => z.fam_name == x); $(".selectedItem").append(`
  • 卍 - ${x} - ${(f && f.fam_title) ? f.fam_title : ""} - − - ↑ - ↓
  • `); + ${x} + ${(f && f.fam_title) ? f.fam_title : ""} + − + ↑ + ↓`); }); let items = this.familyMembers.filter(x => x.deceased == false).map(x => x.fam_name); @@ -507,19 +507,19 @@ finalItem.forEach(yy => { let f = this.familyMembers.find(z => z.fam_name == yy); $(".canselectItem").append(`
  • 卍 ${yy} - ${(f && f.fam_title) ? f.fam_title : ""} - +
  • `); + ${(f && f.fam_title) ? f.fam_title : ""} + +`); }); } else if (element.hasClass("address")) { $(".selectedItem").append(`
  • 卍 - ${this.address == undefined ? "" : this.address} - −`); + ${this.address == undefined ? "" : this.address} + −`); } else if (element.hasClass("lefttitle")) { this.leftProperTitle.forEach(x => { let f = this.familyMembers.find(z => z.fam_name == x); $(".selectedItem").append(`
  • 卍${x} - ${(f && f.fam_title) ? f.fam_title : ""} - −`); + ${(f && f.fam_title) ? f.fam_title : ""} + −`); }); let items = this.familyMembers.filter(x => (this.tabletType == "A" && x.deceased == false) || (this.tabletType == "B" && x.deceased == true)).map(x => x.fam_name); @@ -528,15 +528,15 @@ finalItem.forEach(yy => { let f = this.familyMembers.find(z => z.fam_name == yy); $(".canselectItem").append(`
  • 卍 ${yy} - ${(f && f.fam_title) ? f.fam_title : ""} - +
  • `); + ${(f && f.fam_title) ? f.fam_title : ""} + +`); }); } else if (element.hasClass("righttitle")) { this.rightProperTitle.forEach(x => { let f = this.familyMembers.find(z => z.fam_name == x); $(".selectedItem").append(`
  • 卍${x} - ${(f && f.fam_title) ? f.fam_title : ""} - −`); + ${(f && f.fam_title) ? f.fam_title : ""} + −`); }); let items = this.familyMembers.filter(x => (this.tabletType == "A" && x.deceased == false) || (this.tabletType == "B" && x.deceased == true)).map(x => x.fam_name); @@ -545,8 +545,8 @@ finalItem.forEach(yy => { let f = this.familyMembers.find(z => z.fam_name == yy); $(".canselectItem").append(`
  • 卍 ${yy} - ${(f && f.fam_title) ? f.fam_title : ""} - +
  • `); + ${(f && f.fam_title) ? f.fam_title : ""} + +`); }); } else { let hasControls = !element.hasClass("ancestor-wrapper"); @@ -554,8 +554,8 @@ let f = this.familyMembers.find(z => z.fam_name == y); let controlHtml = hasControls ? `↑↓` : ''; $(".selectedItem").append(`
  • 卍${y} - ${(f && f.fam_title) ? f.fam_title : ""} - −${controlHtml}
  • `); + ${(f && f.fam_title) ? f.fam_title : ""} + −${controlHtml}`); }); if (hasControls) { @@ -564,8 +564,8 @@ finalItem.forEach(yy => { let f = this.familyMembers.find(z => z.fam_name == yy); $(".canselectItem").append(`
  • 卍 ${yy} - ${(f && f.fam_title) ? f.fam_title : ""} - +
  • `); + ${(f && f.fam_title) ? f.fam_title : ""} + +`); }); } } @@ -813,7 +813,7 @@ renderNormal(mid, d) { return $(`
    ${mid}
    `).css({ "z-index": 9999, visibility: d.visibility, width: d.width, height: d.height }); }, - renderNameList(names, d, newFontSize, style, colWidth) { + /*renderNameList(names, d, newFontSize, style, colWidth) { let h = parseFloat(d.height), w = parseFloat(d.width), th = parseFloat(d.textHeight) || h; let v_gap = parseFloat(d.textSpan) || 0, h_gap = 5; let shrinkLimit = h < 300 ? 12 : (h < 500 ? 8 : 6); @@ -874,10 +874,266 @@ $namelist.append($(`${item.name}`).css({ display: "block", "min-height": item.isShort ? `${th}px` : `${h}px`, "max-height": `${h}px`, width: "auto", "line-height": "1.1", "text-align": alignStyle, "text-align-last": alignStyle, "margin-left": "5px", "text-justify": "inter-character", "word-break": "break-all" })); }); + return $namelist; + },*/ + renderNameList(names, d, newFontSize, style, colWidth) { + let h = Number(d.height); + let w = Number(d.width); + let th = Number(d.textHeight) || h; + let v_gap = Number(d.textSpan) || 0; + let h_gap = 5; + let shrinkLimit = 6; + + if (h < 500) { + shrinkLimit = 8; + } else if (h < 300) { + shrinkLimit = 12; + } + + let long_s = Number(d.fontSize); + let short_s = Number(d.fontSize); + + let renderNames = [...names]; + + if (h < 500 && renderNames.length == 1 && renderNames[0].includes("暨無始劫以來累世冤親債主")) { + renderNames = renderNames[0].split("暨"); + renderNames[0] = renderNames[0] + "暨"; + } + + let items = renderNames.map(name => { + let l = name.length; + let isShort = (l * 40) <= (th + (v_gap / 2)); + return { name: name, l: l, isShort: isShort, isMulti: false, size: 0 }; + }); + + let maxShortLen = Math.max(...items.filter(x => x.isShort).map(x => x.l), 1); + let allShort = items.every(x => x.isShort); + let fitsInHalf = items.every(x => (x.l * short_s * 1.333) <= (h / 2)); + + let isSpecial1 = allShort && fitsInHalf && items.length === 1; + let isSpecial2 = allShort && fitsInHalf && items.length === 2; + let isSpecial4 = allShort && fitsInHalf && (items.length === 4 || items.length === 6 || items.length === 8); + let isSpecial = isSpecial1 || isSpecial2 || isSpecial4; + + let sizes = []; + let shrink_turn = 'long'; + + while (true) { + let totalWidth = 0; + let current_col_h = 0; + let current_col_w = 0; + let cols_width = []; + let any_wrapped = false; + + for (let i = 0; i < items.length; i++) { + let item = items[i]; + let s = item.isShort ? short_s : long_s; + item.size = s; + let size_px = s * 1.333; + + if (item.isShort) { + let item_h = Math.max(th, maxShortLen * size_px); + + if (isSpecial) { + if (isSpecial1 || isSpecial2) item_h = h / 2; + if (isSpecial4) item_h = (h / 2) - (v_gap / 2); + } else { + let natural_h = maxShortLen * size_px; + if (item_h > natural_h * 1.5) { + item_h = natural_h * 1.5; + } + } + + if (current_col_h === 0) { + current_col_h = item_h; + current_col_w = size_px; + } else if ((current_col_h + v_gap + item_h) <= h) { + current_col_h += (v_gap + item_h); + if (size_px > current_col_w) current_col_w = size_px; + } else { + cols_width.push(current_col_w); + current_col_h = item_h; + current_col_w = size_px; + } + } else { + if (current_col_h > 0) { + cols_width.push(current_col_w); + current_col_h = 0; + current_col_w = 0; + } + + let item_w = size_px; + + if ((item.l * size_px) > (h - 10)) { + item.isMulti = true; + any_wrapped = true; + + let chars_per_col = Math.floor((h - 10) / size_px); + if (chars_per_col < 1) chars_per_col = 1; + let item_cols = Math.ceil(item.l / chars_per_col); + item_w = item_cols * (size_px * 1.1); + } else { + item.isMulti = false; + } + + cols_width.push(item_w); + } + } + + if (current_col_h > 0) cols_width.push(current_col_w); + + totalWidth = cols_width.reduce((a, b) => a + b, 0) + (cols_width.length > 1 ? (cols_width.length - 1) * h_gap : 0); + + if (totalWidth <= w && (!any_wrapped || long_s === shrinkLimit)) { + sizes = items.map(x => { + let final_s = x.size; + if (x.isShort) { + let max_s_for_th = Math.floor(th / (maxShortLen * 1.333)); + if (final_s > max_s_for_th) { + final_s = max_s_for_th; + } + } + return { name: x.name, size: final_s, isMulti: x.isMulti, isShort: x.isShort }; + }); + break; + } + + let hasLong = items.some(x => !x.isShort); + let hasShort = items.some(x => x.isShort); + + if (hasLong && hasShort) { + if (shrink_turn === 'long') { + if (long_s > shrinkLimit) { + long_s--; + shrink_turn = 'short'; + } else if (short_s > shrinkLimit) { + short_s--; + shrink_turn = 'long'; + } else { + break; + } + } else { + if (short_s > shrinkLimit) { + short_s--; + shrink_turn = 'long'; + } else if (long_s > shrinkLimit) { + long_s--; + shrink_turn = 'short'; + } else { + break; + } + } + } else if (hasLong) { + if (long_s > shrinkLimit) { + long_s--; + } else { + break; + } + } else { + if (short_s > shrinkLimit) { + short_s--; + } else { + break; + } + } + } + + if (sizes.length === 0) { + sizes = renderNames.map(name => { + return { name: name, size: shrinkLimit, isMulti: false, isShort: true }; + }); + } + + let flexDir = isSpecial2 ? "column" : "row"; + let flexJustify = isSpecial ? "center" : "flex-start"; + let flexAlign = "center"; + + if (isSpecial4) { + v_gap = Number(h) / 4; + } + + let $namelist = $(`
    `).css({ + "writing-mode": "vertical-rl", + display: "flex", + "flex-direction": flexDir, + "flex-wrap": "wrap", + "align-content": "center", + "align-items": flexAlign, + "justify-content": flexJustify, + margin: "auto", + width: `${w}px`, + height: `${h}px`, + border: "0px solid transparent", + padding: "1px", + "column-gap": `${v_gap}px`, + "font-family": d.fontFamily + }); + + sizes.forEach(item => { + let size_px = item.size * 1.333; + let natural_max_h = maxShortLen * size_px; + let boxH_num = item.isShort ? Math.max(th, natural_max_h) : h; + + if (isSpecial) { + if (isSpecial1 || isSpecial2) boxH_num = h / 2; + if (isSpecial4) boxH_num = (h / 2) - (v_gap) - 2; + } else if (item.isShort) { + if (boxH_num > natural_max_h * 1.5) { + boxH_num = natural_max_h * 1.5; + } + } + + let minH = `${boxH_num}px`; + let alignStyle = item.isMulti || (!item.isMulti && !item.isShort) ? "start" : "justify"; + + let spanDisplay = "block"; + let spanJustifyContent = "flex-start"; + + let spanMarginTop = "0px"; + if (isSpecial1 || isSpecial2) { + spanMarginTop = `-${h / 4}px`; + } + + if (isSpecial1 || isSpecial2 || isSpecial4) { + alignStyle = "justify"; + spanJustifyContent = "space-between"; + } + + let nameLen = item.name.length; + let contentH = nameLen * size_px; + let emptySpace = boxH_num - contentH; + let gapsCount = nameLen > 1 ? (nameLen - 1) : 1; + let avgGap = emptySpace / gapsCount; + + if (!isSpecial && alignStyle === "justify" && avgGap > (size_px * 1.5)) { + alignStyle = "justify"; + spanDisplay = "block"; + spanJustifyContent = "start"; + } + + let $span = $(`${item.name}`).css({ + "display": spanDisplay, + "justify-content": spanJustifyContent, + "align-items": "center", + "min-height": minH, + "max-height": `${h}px`, + "width": "auto", + "line-height": "1.1", + "text-align": alignStyle, + "text-align-last": alignStyle, + "margin-left": "5px", + "margin-top": spanMarginTop, + "text-justify": "inter-character", + "word-break": "break-all" + }); + + $namelist.append($span); + }); + return $namelist; }, - renderLiveList(names, el) { + /*renderLiveList(names, el) { let h = parseFloat(el.height), w = parseFloat(el.width), th = parseFloat(el.textHeight) || h; let v_gap = parseFloat(el.textSpan) || 0, h_gap = 5; let shrinkLimit = h < 300 ? 8 : (h < 500 ? 6 : 4); @@ -910,6 +1166,155 @@ renderLiveSpan(name, el, fontSize) { return $(`${name}`).css({ "display": "block", "min-height": `${parseFloat(el.textHeight) || parseFloat(el.height)}px`, "max-height": `${parseFloat(el.height)}px`, "width": "auto", "text-align": "justify", "text-align-last": "justify", "margin-left": "0px", "text-justify": "inter-character", "word-break": "break-all", "white-space": "pre-line" }); + },*/ + renderLiveList(names, el) { + let h = parseFloat(el.height); + let w = parseFloat(el.width); + let th = parseFloat(el.textHeight) || h; + + let v_gap = parseFloat(el.textSpan) || 0; + let h_gap = 5; + let shrinkLimit = 4; + + if (Number(el.height) < 300) { + shrinkLimit = 8; + } else if (Number(el.height) < 500) { + shrinkLimit = 6; + } + + let s = parseFloat(el.fontSize); + + if (names.length == 2) { + h = th + v_gap; + } + + let maxLen = Math.max(...names.map(x => x.length), 1); + + while (s >= shrinkLimit) { + let size_px = s * 1.333; + let current_col_h = 0; + let current_col_w = 0; + let cols_width = []; + let any_wrapped = false; + + for (let i = 0; i < names.length; i++) { + let l = names[i].length; + + let natural_max_h = maxLen * size_px; + let item_h = Math.max(th, natural_max_h); + + if (item_h > natural_max_h * 1.5) { + item_h = natural_max_h * 1.5; + } + + if (item_h > (h - 5)) { + any_wrapped = true; + + if (current_col_h > 0) { + cols_width.push(current_col_w); + current_col_h = 0; + current_col_w = 0; + } + + let chars_per_col = Math.floor((h - 5) / size_px); + if (chars_per_col < 1) chars_per_col = 1; + + let item_cols = Math.ceil(l / chars_per_col); + cols_width.push(item_cols * (size_px * 1.1)); + } else { + if (current_col_h === 0) { + current_col_h = item_h; + current_col_w = size_px; + } else if (current_col_h + v_gap + item_h <= h) { + current_col_h += v_gap + item_h; + if (size_px > current_col_w) current_col_w = size_px; + } else { + cols_width.push(current_col_w); + current_col_h = item_h; + current_col_w = size_px; + } + } + } + + if (current_col_h > 0) cols_width.push(current_col_w); + + let totalWidth = cols_width.reduce((a, b) => a + b, 0) + (cols_width.length > 1 ? (cols_width.length - 1) * h_gap : 0); + + if (totalWidth <= w && (!any_wrapped || s === shrinkLimit)) { + break; + } + + s -= 1; + } + + if (s < shrinkLimit) s = shrinkLimit; + + let $namelist = $(`
    `).css({ + "writing-mode": "vertical-rl", + "display": "flex", + "flex-flow": "wrap", + "align-content": "center", + "align-items": "center", + "margin": "auto", + "width": `${w}px`, + "height": `${h}px`, + "border": "0px solid transparent", + "padding": "0px", + "font-family": el.fontFamily, + "column-gap": `${v_gap}px` + }); + + names.forEach(name => { + $namelist.append(this.renderLiveSpan(name, el, s, maxLen)); + }); + + return $namelist; + }, + + renderLiveSpan(name, el, fontSize, maxLen = 1) { + let h = parseFloat(el.height); + let th = parseFloat(el.textHeight) || h; + let size_px = fontSize * 1.333; + let l = name.length; + + let natural_max_h = maxLen * size_px; + let boxH_num = Math.max(th, natural_max_h); + + if (boxH_num > natural_max_h * 1.5) { + boxH_num = natural_max_h * 1.5; + } + + let minH = `${boxH_num}px`; + let alignStyle = "justify"; + let spanDisplay = "block"; + let spanJustifyContent = "flex-start"; + + let contentH = l * size_px; + let emptySpace = boxH_num - contentH; + let gapsCount = l > 1 ? (l - 1) : 1; + let avgGap = emptySpace / gapsCount; + + if (alignStyle === "justify" && avgGap > (size_px * 1.5)) { + alignStyle = "justify"; + spanDisplay = "block"; + spanJustifyContent = "space-between"; + } + + return $(`${name}`).css({ + "display": spanDisplay, + "justify-content": spanJustifyContent, + "align-items": "center", + "min-height": minH, + "max-height": `${h}px`, + "width": "auto", + "text-align": alignStyle, + "text-align-last": alignStyle, + "margin-left": "0px", + "margin-top": "0px", + "text-justify": "inter-character", + "word-break": "break-all", + "white-space": "pre-line" + }); }, renderRoster(names, el) { @@ -924,9 +1329,9 @@ renderCombined(mid, d) { const parts = mid.join("\n").split('\n'); return `
    - ${parts[0] || ''} - ${parts[1] || ''} -
    `; + ${parts[0] || ''} + ${parts[1] || ''} + `; }, renderNameGroups(items, el) {