Commit a04a308e by ramdayalmunda

managed library to work on both, node and browser

parent 4bea5711
let isModule = (typeof module != 'undefined') ? true : false
const { jsPDF } = require("jspdf");
const { createCanvas } = require('canvas')
var ADocEditor = function (customConfig) {
var counter = 7
var screen = { width: 1366, height: 720 }
var defaultConfig = {
element: "",
pageSetup: {
width: 210,
height: 110,
},
format: {
background: "#fff",
margin: 20,
border: "",
fontSize: 10,
tabWidth: 20,
},
style: {
fontSize: 30,
fontFamily: 'Arial',
bold: false,
italic: false,
fontColor: "#001"
},
}
var config = JSON.parse(JSON.stringify(defaultConfig));
var canvasList = []
const dataTypes = [
"paragraph", // simple text filled line by line
"list", // sequence of line that preserves indentation
]
var dataSet = [
{
id: ++counter,
type: 0,
formatedText: [],
plainContent: "",
tabCount: 0,
style: { ...config.style }
},
]
// // paragraphs // this line is added only for testing please remove this on completion
dataSet = JSON.parse('[{"id":1,"type":0,"formatedText":[],"plainContent":"Rendering text in HTML canvas involves using the CanvasRenderingContext2D interface to display text content within a canvas element. This process allows for dynamic text display, enabling the creation of custom text effects, labels, captions, or textual elements within the canvas.","style":{"fontSize":30,"fontFamily":"Arial","bold":false,"italic":false,"fontColor":"#001"}},{"id":2,"type":0,"plainContent":"To render text on a canvas, developers typically use the fillText() method provided by the Canvas API. This method allows the specification of text content, font styles, position, and color. Additionally, the measureText() method helps in determining the width of text, facilitating accurate positioning and layout arrangements.","style":{"fontSize":30,"fontFamily":"Arial","bold":false,"italic":false,"fontColor":"#001"}},{"id":3,"type":0,"plainContent":"Text in canvas can be customized by setting various font properties like font family, font size, style (bold, italic), alignment, and color. However, canvas text rendering lacks the text reflow and responsive layout capabilities inherent in HTML and CSS.","style":{"fontSize":30,"fontFamily":"Arial","bold":false,"italic":false,"fontColor":"#001"}},{"id":4,"type":0,"plainContent":"Despite its intricacies, canvas text rendering offers unparalleled creative freedom, enabling the development of immersive graphical experiences, custom typography, and visually stunning representations that enhance user engagement and interactivity within web-based applications and games.","style":{"fontSize":30,"fontFamily":"Arial","bold":false,"italic":false,"fontColor":"#001"}},{"id":5,"type":0,"plainContent":"Developers often use canvas text rendering to create graphical representations of text-based information, such as game interfaces, data visualizations, charts, and diagrams. Despite its flexibility in text manipulation and artistic possibilities, rendering text in canvas may require additional manual adjustments for formatting, spacing, and alignment compared to traditional HTML text rendering.","style":{"fontSize":30,"fontFamily":"Arial","bold":false,"italic":false,"fontColor":"#001"}}]')
// // lists // this line is added only for testing please remove this on completion
dataSet = JSON.parse('[{"id":1,"type":0,"plainContent":"Here is a list of household items you need to buy if you are relocating and don\'t have anything with you","style":{"fontSize":30,"fontFamily":"Arial","bold":false,"italic":false,"fontColor":"#003"},"formatedText":[]},{"id":2,"type":1,"tabCount":0,"plainContent":"Recipie book for vegetarian noodles","style":{"fontSize":30,"fontFamily":"Arial","bold":false,"italic":false,"fontColor":"#003"},"formatedText":[]},{"id":3,"type":1,"tabCount":0,"plainContent":"Noodles","style":{"fontSize":30,"fontFamily":"Arial","bold":false,"italic":false,"fontColor":"#003"},"formatedText":[]},{"id":5,"type":1,"tabCount":0,"plainContent":"Garlic","style":{"fontSize":30,"fontFamily":"Arial","bold":false,"italic":false,"fontColor":"#003"},"formatedText":[]},{"id":6,"type":1,"tabCount":0,"plainContent":"Some School stationaries for Arvind","style":{"fontSize":30,"fontFamily":"Arial","bold":false,"italic":false,"fontColor":"#003"},"formatedText":[]},{"id":7,"type":1,"tabCount":1,"plainContent":"Full pack of pen","style":{"fontSize":30,"fontFamily":"Arial","bold":false,"italic":false,"fontColor":"#003"},"formatedText":[]},{"id":8,"type":1,"tabCount":1,"plainContent":"Drawing kit","style":{"fontSize":30,"fontFamily":"Arial","bold":false,"italic":false,"fontColor":"#003"},"formatedText":[]},{"id":9,"type":1,"tabCount":1,"plainContent":"2 register size notebook","style":{"fontSize":30,"fontFamily":"Arial","bold":false,"italic":false,"fontColor":"#003"},"formatedText":[]},{"id":10,"type":1,"tabCount":0,"plainContent":"Window shields","style":{"fontSize":30,"fontFamily":"Arial","bold":false,"italic":false,"fontColor":"#003"},"formatedText":[]},{"id":11,"type":1,"tabCount":0,"plainContent":"Mosquito repelant","style":{"fontSize":30,"fontFamily":"Arial","bold":false,"italic":false,"fontColor":"#003"},"formatedText":[]}]')
var lines = []
var caretData = {
activeData: dataSet[0],
index: 0,
interval: null,
intervalDuration: 800,
blink: false,
canvasIndex: 0,
caretSize: config.style.fontSize,
x: config.format.margin,
y: config.format.margin + (3 * config.style.fontSize / 4),
previousCaret: null,
}
var renderInProgress = false;
function inititalize(customConfig) {
config = { ...defaultConfig, ...customConfig }
config.pageSetup.canvasMultiplier = Math.round(screen.width / config.pageSetup.width)
config.pageSetup.canvasWidth = config.pageSetup.canvasMultiplier * config.pageSetup.width
config.pageSetup.canvasHeight = config.pageSetup.canvasMultiplier * config.pageSetup.height
reRenderPages(dataSet)
}
function reRenderPages(dataList, option) {
if (renderInProgress) return
renderInProgress = true
let canvasIndex = 0
if (!canvasList.length) canvasList[0] = { el: createNewCanvas(), dataIndex: 0 }
// to clear the canvases
for (let i = 0; i < canvasList.length; i++) {
let ctx = canvasList[i].el.getContext('2d', { willReadFrequently: true })
ctx.save()
ctx.clearRect(0, 0, canvasList[i].el.width, canvasList[i].el.height); // clears the canvas
ctx.fillStyle = config.format.background
ctx.fillRect(0, 0, canvasList[i].el.width, canvasList[i].el.height)
ctx.restore()
}
lines = []
for (let i = 0; i < dataList.length; i++) {
calculateTextSizeAndPosition(canvasIndex, i)
}
renderTheLines()
if (!caretData.blink && caretData.activeData) renderCaret()
function calculateTextSizeAndPosition(canvasIndex, dataSetIndex) {
let dataBlock = dataList[dataSetIndex]
let canvas = canvasList[canvasIndex].el
let ctx = canvas.getContext('2d', { willReadFrequently: true })
ctx.save()
// to calculate the lines
let dataLineArr = []
function getLineObj() {
return {
x: 0, // this is the starting point x; it will change based on the tabNumber
y: 0, // this is the starting y coordinate; it will change based on the max font size
plainContent: "",
fontSize: 30,
maxFontSize: 30,
dataSetIndex: dataSetIndex,
charStartIndex: 0, // index from where to check
charEndIndex: 0, // index till where to check// not including this index.
}
}
if (!dataBlock.formatedText) dataBlock.formatedText = []
let lineObj = new getLineObj()
dataLineArr.push(lineObj)
lineObj.type = dataBlock.type
lineObj.blockStart = true
let wordEndIndex = 0; // this stores the index of the word which can fit in the line;
let tempLineWidth = 0;
let maxLineWidth = config.pageSetup.canvasWidth - (config.format.margin * 2 * config.pageSetup.canvasMultiplier)
if (dataBlock.tabCount || dataBlock.type == 1) {
let finalTabCount = dataBlock.tabCount
if (dataBlock.type == 1) {
finalTabCount++
}
let tabDistance = finalTabCount * config.format.tabWidth * config.pageSetup.canvasMultiplier
if (tabDistance > maxLineWidth * 5 / 6) { tabDistance = 0 }
maxLineWidth = maxLineWidth - tabDistance
}
lineObj.maxLineWidth = maxLineWidth
lineObj.tabCount = dataBlock.tabCount
// // for checking the listIndex
if (dataBlock.type == 1) {
for (let i = dataSetIndex - 1; i >= 0; i--) {
if (dataList[i].type != 1) {
dataBlock.listIndex = 0
break;
} else if (dataList[i].tabCount == dataBlock.tabCount) {
dataBlock.listIndex = dataList[i].listIndex + 1
break
} else if (dataList[i].tabCount < dataBlock.tabCount) {
dataBlock.listIndex = 0
break;
}
}
}
lineObj.listIndex = dataBlock.listIndex
let i = 0
for (i = 0; i < dataBlock.plainContent.length; i++) {
let style = dataBlock?.formatedText?.[i]
if (!style) style = JSON.parse(JSON.stringify(config.style))
if (/\s/.test(dataBlock.plainContent[i])) {
wordEndIndex = i
lineObj.charEndIndex = wordEndIndex;
}
let charWidth = getCharacterWidth(canvasIndex, dataBlock.plainContent[i], style)
dataBlock.formatedText[i] = {
...config.style,
width: charWidth
}
lineObj.maxFontSize = style.fontSize
// lineObj.fontSize = style.fontSize
tempLineWidth += charWidth
if (tempLineWidth <= maxLineWidth) {
// can be added to the line //
} else {
// cannot add this// new line should be added//
i = wordEndIndex;
lineObj.plainContent = dataBlock.plainContent.slice(lineObj.charStartIndex, lineObj.charEndIndex + 1)
lineObj = new getLineObj()
lineObj.listIndex = dataBlock.listIndex
lineObj.maxLineWidth = maxLineWidth
lineObj.tabCount = dataBlock.tabCount
lineObj.charStartIndex = i
lineObj.charEndIndex = i
dataLineArr.push(lineObj)
tempLineWidth = 0
}
}
lineObj.plainContent = dataBlock.plainContent.slice(lineObj.charStartIndex, lineObj.charEndIndex + 1)
// there is chance that the last line is not at the width// so we need to handle the last line separately
if (lineObj.charEndIndex <= dataBlock.plainContent.length) {
lineObj.charEndIndex = dataBlock.plainContent.length - 1
}
lineObj.plainContent = dataBlock.plainContent.slice(lineObj.charStartIndex, lineObj.charEndIndex)
lines.push(...dataLineArr)
ctx.restore()
return true
}
function renderTheLines() {
let canvasIndex = 0
let ctx = canvasList[canvasIndex].el.getContext('2d', { willReadFrequently: true })
let x = 0
let y = (config.format.margin * config.pageSetup.canvasMultiplier)
let maxVericalWidth = (config.pageSetup.canvasHeight - config.format.margin * config.pageSetup.canvasMultiplier * 2)
for (let l = 0; l < lines.length; l++) {
x = (config.format.margin * config.pageSetup.canvasMultiplier);
y += lines[l].maxFontSize
if (lines[l].blockStart && l != 0) y += lines[l].maxFontSize
if ((maxVericalWidth + lines[l].maxFontSize) < (y - lines[l].maxFontSize)) {
canvasIndex++
if (!canvasList[canvasIndex]) {
canvasList[canvasIndex] = { id: ++counter, el: createNewCanvas(), dataIndex: lines[l].dataSetIndex, lineIndex: l }
}
ctx = canvasList[canvasIndex].el.getContext('2d', { willReadFrequently: true })
y = lines[l].maxFontSize + (config.format.margin * config.pageSetup.canvasMultiplier)
}
let setData = dataSet[lines[l].dataSetIndex]
lines[l].y = y
if (lines[l].listIndex >= 0) {
let totalTabDistance = config.format.tabWidth * config.pageSetup.canvasMultiplier * (lines[l].tabCount + 1)
x += totalTabDistance;
let numberX = x - config.format.tabWidth * config.pageSetup.canvasMultiplier / 2
if (lines[l].blockStart) {
let style = {
...config.style,
...setData.style
}
ctx.save()
ctx.fillStyle = `${style.fontColor}`
ctx.font = `${style.bold ? 'bold ' : ''}${style.italic ? 'italic ' : ''} ${style.fontSize}px ${style.fontFamily}`
ctx.fillText(`${lines[l].listIndex + 1}.`, numberX, y)
ctx.restore()
}
}
lines[l].x = x
lines[l].canvasIndex = canvasIndex
for (let c = lines[l].charStartIndex; c <= lines[l].charEndIndex; c++) {
let char = setData?.plainContent[c]
if (char) {
let style = setData.formatedText[c]
ctx.save()
ctx.font = `${style?.bold ? 'bold ' : ''}${style?.italic ? 'italic ' : ''} ${style.fontSize}px ${style.fontFamily}`
ctx.fillStyle = `${style?.fontColor}`
ctx.fillText(char, x, y)
setData.formatedText[c].x = x
setData.formatedText[c].y = y
ctx.restore()
if (setData.formatedText[c]?.width) {
x += setData.formatedText[c]?.width
}
}
}
}
}
// to render caret
function renderCaret() {
let ctx = canvasList[caretData.canvasIndex].el.getContext('2d', { willReadFrequently: true })
ctx.save()
let activeDataIndex = dataSet.findIndex(item => item.id == caretData.activeData.id)
let activeLine = lines.find((item, i) => {
if (item.dataSetIndex == activeDataIndex) {
if (item.charEndIndex == -1) return true
if (item.charEndIndex >= caretData.index) return true
if (!(lines[i + 1]?.dataSetIndex == activeDataIndex)) return true
else false
} else return false
})
// handle left right on multiple pages
if (activeLine) {
caretData.canvasIndex = activeLine.canvasIndex
ctx.restore()
ctx = canvasList[activeLine.canvasIndex].el.getContext('2d', { willReadFrequently: true })
ctx.save()
}
let characterData = dataSet[activeDataIndex].formatedText[caretData.index]
let rectX = characterData?.x,
rectY = activeLine.y - activeLine.maxFontSize,
rectWidth = 2,
rectHeight = 5 * activeLine.maxFontSize / 4;
if (!characterData && dataSet[activeDataIndex].formatedText?.[caretData.index - 1]) {
rectX = dataSet[activeDataIndex].formatedText?.[caretData.index - 1]?.x + dataSet[activeDataIndex].formatedText?.[caretData.index - 1]?.width
}
if (activeLine.charEndIndex == caretData.index) {
rectX = dataSet[activeDataIndex].formatedText?.[caretData.index - 1]?.x + dataSet[activeDataIndex].formatedText?.[caretData.index - 1]?.width
}
if (!(rectX > 0 || rectX == 0)) { rectX = activeLine.x }
const imageData = ctx.getImageData(rectX, rectY, rectWidth, rectHeight);
const data = imageData.data;
// Invert the color of the rectangular region
for (let i = 0; i < data.length; i += 4) {
data[i] = 255 - data[i]; // Red
data[i + 1] = 255 - data[i + 1]; // Green
data[i + 2] = 255 - data[i + 2]; // Blue
// Alpha channel remains unchanged (data[i + 3])
ctx.putImageData(imageData, rectX, rectY);
}
ctx.restore()
}
function getCharacterWidth(canvasIndex, char, style) {
let canvas = canvasList[canvasIndex].el
let ctx = canvas.getContext('2d', { willReadFrequently: true })
ctx.save()
ctx.font = `${style?.bold ? 'bold ' : ''}${style?.italic ? 'italic ' : ''} ${style.fontSize}px ${style.fontFamily}`
ctx.fillStyle = `${style?.fontColor}`
let width = ctx.measureText(char).width
ctx.restore()
return width
}
function createNewCanvas() {
let canvas = createCanvas(config.pageSetup.canvasWidth, config.pageSetup.canvasHeight)
let ctx = canvas.getContext('2d', { willReadFrequently: true })
ctx.fillStyle = config.format.background
ctx.fillRect(0, 0, canvas.width, canvas.height)
return canvas
}
renderInProgress = false
}
function generatePDF(fileName) {
if (isModule) {
console.log('to generate PDF on Server side', config.pageSetup)
const doc = new jsPDF('l', 'px', [660, 1260]);
let canvasIndex = 0;
let x = 0
let y = (config.format.margin * config.pageSetup.canvasMultiplier)
let maxVericalWidth = (config.pageSetup.canvasHeight - config.format.margin * config.pageSetup.canvasMultiplier * 2)
for (let l = 0; l < lines.length; l++) {
x = (config.format.margin * config.pageSetup.canvasMultiplier);
y += lines[l].maxFontSize
if (lines[l].blockStart && l != 0) y += lines[l].maxFontSize
if ((maxVericalWidth + lines[l].maxFontSize) < (y - lines[l].maxFontSize)) {
canvasIndex++
doc.addPage()
console.log('new page added')
y = lines[l].maxFontSize + (config.format.margin * config.pageSetup.canvasMultiplier)
}
let setData = dataSet[lines[l].dataSetIndex]
lines[l].y = y
if (lines[l].listIndex >= 0) {
let totalTabDistance = config.format.tabWidth * config.pageSetup.canvasMultiplier * (lines[l].tabCount + 1)
x += totalTabDistance;
let numberX = x - config.format.tabWidth * config.pageSetup.canvasMultiplier / 2
if (lines[l].blockStart) {
let style = {
...config.style,
...setData.style
}
}
}
lines[l].x = x
lines[l].canvasIndex = canvasIndex
for (let c = lines[l].charStartIndex; c <= lines[l].charEndIndex; c++) {
let char = setData?.plainContent[c]
if (char) {
let style = setData.formatedText[c]
doc.setFont('times')
doc.setFontSize(style.fontSize)
doc.text( char, x, y )
// ctx.font = `${style?.bold ? 'bold ' : ''}${style?.italic ? 'italic ' : ''} ${style.fontSize}px ${style.fontFamily}`
// ctx.fillStyle = `${style?.fontColor}`
// ctx.fillText(char, x, y)
setData.formatedText[c].x = x
setData.formatedText[c].y = y
if (setData.formatedText[c]?.width) {
x += setData.formatedText[c]?.width
}
}
}
}
doc.save(fileName);
} else {
console.log('to generate PDF on browser')
}
}
inititalize(customConfig)
function destory() {
clearInterval(caretData.interval)
}
var returnObj = {
destory,
loadContent: function (data) {
dataSet = JSON.parse(JSON.stringify(data))
reRenderPages(dataSet)
caretData.activeData = null
caretData.activeData = dataSet[0]
caretData.index = 0
},
getContent: function () {
return JSON.parse(JSON.stringify(dataSet))
},
generatePDF,
}
return returnObj
}
if (isModule) module.exports = ADocEditor
\ No newline at end of file
let isModule = (typeof module != 'undefined') ? true : false
var ADocEditor = function (customConfig) {
var screenWidth = (typeof screen != 'undefined') ? screen.width : 1280
var counter = 7
var container = null
var mainComponent = null
......@@ -66,89 +67,92 @@ var ADocEditor = function (customConfig) {
function inititalize(customConfig) {
config = { ...defaultConfig, ...customConfig }
config.pageSetup.canvasMultiplier = Math.round(screen.width / config.pageSetup.width)
config.pageSetup.fontMultiplier = config.pageSetup.canvasMultiplier/3
config.pageSetup.canvasMultiplier = Math.round(screenWidth / config.pageSetup.width)
config.pageSetup.fontMultiplier = config.pageSetup.canvasMultiplier / 3
config.pageSetup.canvasWidth = config.pageSetup.canvasMultiplier * config.pageSetup.width
config.pageSetup.canvasHeight = config.pageSetup.canvasMultiplier * config.pageSetup.height
if (!config.element) throw "'container' not provided in the config"
if (typeof config.element == 'string') container = document.querySelector(config.element)
if (config.element instanceof HTMLElement) container = config.element
if (!container) throw "undefined"
let mainComponentId = `main-${new Date().getTime()}`
let headerComponentId = `header-${new Date().getTime()}`
let footerComponentId = `footer-${new Date().getTime()}`
let scrollingAreaId = `scrolling-area-${new Date().getTime()}`
let leftSidebarId = `left-sidebar-${new Date().getTime()}`
let rightSidebarId = `right-sidebar-${new Date().getTime()}`
let htmlSetup = /*html*/`
<div class="a-doc-editor" id="${mainComponentId}">
<div class="header" id="${headerComponentId}">
<div class="option-bar">
<span class="option">File</span>
<span class="option">Edit</span>
<span class="option">Insert</span>
<span class="option">Help</span>
<span class="option" a-doc-editor-action="generate-pdf">PDF</span>
</div>
<div class="option-bar">
<span class="option">Search</span>
<span class="option">Undo</span>
<span class="option">Redo</span>
<span class="option">Heading</span>
<span class="option">Font Family</span>
<span class="option">Font Size</span>
<span class="option">Bold</span>
<span class="option">Italic</span>
<span class="option">Undeline</span>
<span class="option">Font Color</span>
<span class="option">Highlight Color</span>
</div>
</div>
<div class="body">
<div class="scrolling-area" id="${scrollingAreaId}">
</div>
<div class="left-sidebar" id="${leftSidebarId}">
<div class="toggle-sidebar">
<span></span>
<span>Summary</span>
<span>&lrarr;</span>
if (!isModule) {
if (!config.element) throw "'container' not provided in the config"
if (typeof config.element == 'string') container = document.querySelector(config.element)
if (config.element instanceof HTMLElement) container = config.element
if (!container) throw "undefined"
let mainComponentId = `main-${new Date().getTime()}`
let headerComponentId = `header-${new Date().getTime()}`
let footerComponentId = `footer-${new Date().getTime()}`
let scrollingAreaId = `scrolling-area-${new Date().getTime()}`
let leftSidebarId = `left-sidebar-${new Date().getTime()}`
let rightSidebarId = `right-sidebar-${new Date().getTime()}`
let htmlSetup = /*html*/`
<div class="a-doc-editor" id="${mainComponentId}">
<div class="header" id="${headerComponentId}">
<div class="option-bar">
<span class="option">File</span>
<span class="option">Edit</span>
<span class="option">Insert</span>
<span class="option">Help</span>
<span class="option" a-doc-editor-action="generate-pdf">PDF</span>
</div>
<div class="option-bar">
<span class="option">Search</span>
<span class="option">Undo</span>
<span class="option">Redo</span>
<span class="option">Heading</span>
<span class="option">Font Family</span>
<span class="option">Font Size</span>
<span class="option">Bold</span>
<span class="option">Italic</span>
<span class="option">Undeline</span>
<span class="option">Font Color</span>
<span class="option">Highlight Color</span>
</div>
<div class="sidebar-body"></div>
</div>
<div class="right-sidebar" id="${rightSidebarId}">
<div class="toggle-sidebar">
<span>&lrarr;</span>
<span>Comments</span>
<span></span>
<div class="body">
<div class="scrolling-area" id="${scrollingAreaId}">
</div>
<div class="left-sidebar" id="${leftSidebarId}">
<div class="toggle-sidebar">
<span></span>
<span>Summary</span>
<span>&lrarr;</span>
</div>
<div class="sidebar-body"></div>
</div>
<div class="right-sidebar" id="${rightSidebarId}">
<div class="toggle-sidebar">
<span>&lrarr;</span>
<span>Comments</span>
<span></span>
</div>
<div class="sidebar-body"></div>
</div>
<div class="sidebar-body"></div>
</div>
<div class="footer" id="${footerComponentId}">
<div>Footer Data</div>
</div>
</div>
<div class="footer" id="${footerComponentId}">
<div>Footer Data</div>
</div>
</div>
`
container.innerHTML = htmlSetup
mainComponent = document.getElementById(mainComponentId)
headerComponent = document.getElementById(headerComponentId)
scrollingComponent = document.getElementById(scrollingAreaId)
footerComponent = document.getElementById(footerComponentId)
leftSidebar = document.getElementById(leftSidebarId)
rightSidebar = document.getElementById(rightSidebarId)
leftSidebar.classList.add('hide')
rightSidebar.classList.add('hide')
mainComponent.getElementsByClassName('toggle-sidebar')[0].addEventListener('click', (e) => {
leftSidebar.classList.toggle('hide')
})
mainComponent.getElementsByClassName('toggle-sidebar')[1].addEventListener('click', (e) => {
rightSidebar.classList.toggle('hide')
})
let generatePDFBtn = document.querySelector('[a-doc-editor-action]')
generatePDFBtn.addEventListener( 'click', generatePDF)
`
container.innerHTML = htmlSetup
mainComponent = document.getElementById(mainComponentId)
headerComponent = document.getElementById(headerComponentId)
scrollingComponent = document.getElementById(scrollingAreaId)
footerComponent = document.getElementById(footerComponentId)
leftSidebar = document.getElementById(leftSidebarId)
rightSidebar = document.getElementById(rightSidebarId)
leftSidebar.classList.add('hide')
rightSidebar.classList.add('hide')
mainComponent.getElementsByClassName('toggle-sidebar')[0].addEventListener('click', (e) => {
leftSidebar.classList.toggle('hide')
})
mainComponent.getElementsByClassName('toggle-sidebar')[1].addEventListener('click', (e) => {
rightSidebar.classList.toggle('hide')
})
let generatePDFBtn = document.querySelector('[a-doc-editor-action]')
generatePDFBtn.addEventListener('click', generatePDF)
}
reRenderPages(dataSet)
}
......@@ -158,7 +162,7 @@ var ADocEditor = function (customConfig) {
renderInProgress = true
let canvasIndex = 0
if (!canvasList.length) canvasList[0] = { el: createCanvas(), dataIndex: 0 }
if (!canvasList.length) canvasList[0] = { el: createNewCanvas(), dataIndex: 0 }
// to clear the canvases
......@@ -289,8 +293,6 @@ var ADocEditor = function (customConfig) {
}
function renderTheLines() {
console.clear()
console.log('to render the lines')
let canvasIndex = 0
let ctx = canvasList[canvasIndex].el.getContext('2d', { willReadFrequently: true })
let x = 0
......@@ -300,12 +302,12 @@ var ADocEditor = function (customConfig) {
x = (config.format.margin * config.pageSetup.canvasMultiplier);
y += (lines[l].maxFontSize*config.pageSetup.fontMultiplier)
y += (lines[l].maxFontSize * config.pageSetup.fontMultiplier)
if (lines[l].blockStart && l != 0) y += lines[l].maxFontSize
if ((maxVericalWidth + lines[l].maxFontSize) < (y - lines[l].maxFontSize)) {
canvasIndex++
if (!canvasList[canvasIndex]) {
canvasList[canvasIndex] = { id: ++counter, el: createCanvas(), dataIndex: lines[l].dataSetIndex, lineIndex: l }
canvasList[canvasIndex] = { id: ++counter, el: createNewCanvas(), dataIndex: lines[l].dataSetIndex, lineIndex: l }
}
ctx = canvasList[canvasIndex].el.getContext('2d', { willReadFrequently: true })
y = lines[l].maxFontSize + (config.format.margin * config.pageSetup.canvasMultiplier)
......@@ -325,7 +327,7 @@ var ADocEditor = function (customConfig) {
}
ctx.save()
ctx.fillStyle = `${style.fontColor}`
ctx.font = `${style.bold ? 'bold ' : ''}${style.italic ? 'italic ' : ''} ${style.fontSize*config.pageSetup.fontMultiplier}px ${style.fontFamily}`
ctx.font = `${style.bold ? 'bold ' : ''}${style.italic ? 'italic ' : ''} ${style.fontSize * config.pageSetup.fontMultiplier}px ${style.fontFamily}`
ctx.fillText(`${lines[l].listIndex + 1}.`, numberX, y)
ctx.restore()
}
......@@ -339,7 +341,7 @@ var ADocEditor = function (customConfig) {
if (char) {
let style = setData.formatedText[c]
ctx.save()
ctx.font = `${style?.bold ? 'bold ' : ''}${style?.italic ? 'italic ' : ''} ${style.fontSize*config.pageSetup.fontMultiplier}px ${style.fontFamily}`
ctx.font = `${style?.bold ? 'bold ' : ''}${style?.italic ? 'italic ' : ''} ${style.fontSize * config.pageSetup.fontMultiplier}px ${style.fontFamily}`
ctx.fillStyle = `${style?.fontColor}`
ctx.fillText(char, x, y)
setData.formatedText[c].x = x
......@@ -372,7 +374,7 @@ var ADocEditor = function (customConfig) {
// handle left right on multiple pages
if (activeLine) {
canvasList[activeLine.canvasIndex].el.focus()
if (!isModule) canvasList[activeLine.canvasIndex].el.focus()
caretData.canvasIndex = activeLine.canvasIndex
ctx.restore()
ctx = canvasList[activeLine.canvasIndex].el.getContext('2d', { willReadFrequently: true })
......@@ -383,9 +385,9 @@ var ADocEditor = function (customConfig) {
let characterData = dataSet[activeDataIndex].formatedText[caretData.index]
let rectX = characterData?.x,
rectY = activeLine.y - (activeLine.maxFontSize*config.pageSetup.fontMultiplier),
rectY = activeLine.y - (activeLine.maxFontSize * config.pageSetup.fontMultiplier),
rectWidth = 2,
rectHeight = 5 * (activeLine.maxFontSize*config.pageSetup.fontMultiplier) / 4;
rectHeight = 5 * (activeLine.maxFontSize * config.pageSetup.fontMultiplier) / 4;
if (!characterData && dataSet[activeDataIndex].formatedText?.[caretData.index - 1]) {
rectX = dataSet[activeDataIndex].formatedText?.[caretData.index - 1]?.x + dataSet[activeDataIndex].formatedText?.[caretData.index - 1]?.width
}
......@@ -412,27 +414,33 @@ var ADocEditor = function (customConfig) {
let canvas = canvasList[canvasIndex].el
let ctx = canvas.getContext('2d', { willReadFrequently: true })
ctx.save()
ctx.font = `${style?.bold ? 'bold ' : ''}${style?.italic ? 'italic ' : ''} ${style.fontSize*config.pageSetup.fontMultiplier}px ${style.fontFamily}`
ctx.font = `${style?.bold ? 'bold ' : ''}${style?.italic ? 'italic ' : ''} ${style.fontSize * config.pageSetup.fontMultiplier}px ${style.fontFamily}`
ctx.fillStyle = `${style?.fontColor}`
let width = ctx.measureText(char).width
ctx.restore()
return width
}
function createCanvas() {
let canvas = document.createElement('canvas')
let ctx = canvas.getContext('2d', { willReadFrequently: true })
canvas.setAttribute('class', 'page')
canvas.width = config.pageSetup.canvasWidth
canvas.height = config.pageSetup.canvasHeight
ctx.fillStyle = config.format.background
ctx.fillRect(0, 0, canvas.width, canvas.height)
canvas.addEventListener('keydown', keydownHandler)
canvas.addEventListener('mousedown', mousedownHandler)
// canvas.addEventListener("focus", onFocusHandler)
// canvas.addEventListener("blur", onBlurHandler)
canvas.setAttribute("tabIndex", -1)
scrollingComponent.append(canvas)
function createNewCanvas() {
let canvas;
if (isModule){
const { createCanvas } = require('canvas')
canvas = createCanvas(config.pageSetup.canvasWidth, config.pageSetup.canvasHeight)
}else{
canvas = document.createElement('canvas')
let ctx = canvas.getContext('2d', { willReadFrequently: true })
canvas.setAttribute('class', 'page')
canvas.width = config.pageSetup.canvasWidth
canvas.height = config.pageSetup.canvasHeight
ctx.fillStyle = config.format.background
ctx.fillRect(0, 0, canvas.width, canvas.height)
canvas.addEventListener('keydown', keydownHandler)
canvas.addEventListener('mousedown', mousedownHandler)
// canvas.addEventListener("focus", onFocusHandler)
// canvas.addEventListener("blur", onBlurHandler)
canvas.setAttribute("tabIndex", -1)
scrollingComponent.append(canvas)
}
return canvas
}
......@@ -562,39 +570,39 @@ var ADocEditor = function (customConfig) {
}
function setCaretPosition(e) {
let canvasIndex = canvasList.findIndex( item => item.el == e.target )
let canvasIndex = canvasList.findIndex(item => item.el == e.target)
let rect = e.target.getBoundingClientRect()
let position = {
x: (e.offsetX / rect.width)*config.pageSetup.canvasWidth,
y: (e.offsetY / rect.height)*config.pageSetup.canvasHeight,
x: (e.offsetX / rect.width) * config.pageSetup.canvasWidth,
y: (e.offsetY / rect.height) * config.pageSetup.canvasHeight,
}
let closestLine = lines.find( (item, i) => {
let thisLine = (item.y+ item.maxFontSize/4)>position.y && canvasIndex==item.canvasIndex
let closestLine = lines.find((item, i) => {
let thisLine = (item.y + item.maxFontSize / 4) > position.y && canvasIndex == item.canvasIndex
if (thisLine) return true
else if ( !(lines[i+1]) || ( lines[i+1]?.canvasIndex>canvasIndex ) ) return true
else if (!(lines[i + 1]) || (lines[i + 1]?.canvasIndex > canvasIndex)) return true
return false
} )
if (closestLine){
})
if (closestLine) {
caretData.activeData = dataSet[closestLine.dataSetIndex]
let charIndex = closestLine.charStartIndex
let found = false
for(let i=charIndex; (i<=closestLine.charEndIndex && caretData.activeData.formatedText[i].y==closestLine.y); i++){
for (let i = charIndex; (i <= closestLine.charEndIndex && caretData.activeData.formatedText[i].y == closestLine.y); i++) {
let formatedText = caretData.activeData.formatedText[i]
if (position.x<(formatedText.x+formatedText.width)){
if (position.x < (formatedText.x + formatedText.width)) {
charIndex = i
found= true
found = true
break;
}
charIndex = i+1
charIndex = i + 1
}
if (/\s+/.test(caretData.activeData.plainContent[charIndex]) && caretData.activeData.plainContent[charIndex+1] && charIndex==closestLine.charStartIndex){
if (/\s+/.test(caretData.activeData.plainContent[charIndex]) && caretData.activeData.plainContent[charIndex + 1] && charIndex == closestLine.charStartIndex) {
charIndex++
}
caretData.index = charIndex
}
reRenderPages( dataSet )
reRenderPages(dataSet)
}
......@@ -613,11 +621,11 @@ var ADocEditor = function (customConfig) {
}
}
function generatePDF(e){
if (isModule){
console.log('to generate PDF on Server side')
}else{
console.log('to generate PDF on browser')
function generatePDF(file) {
if (isModule) {
console.log('to generate PDF on Server side:', file)
} else {
console.log('to generate PDF on browser:', file)
}
}
......@@ -640,8 +648,8 @@ var ADocEditor = function (customConfig) {
getContent: function () {
return JSON.parse(JSON.stringify(dataSet))
},
generatePDF,
}
if (isModule) returnObj.generatePDF = generatePDF
return returnObj
}
......
let ADocEditor = require("./a-doc-editor-node.js")
let ADocEditor = require("./dist/assets/a-doc-editor.js")
var counter = 0
module.exports = async function(req, res){
try{
console.clear()
console.log('generating PDF', ++counter)
let editor = new ADocEditor()
console.log('generating PDF', ++counter, editor)
editor.generatePDF('temp.pdf')
res.status(200).json( { success: true, message: "Successfull" } )
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment