Commit 90f53e1e by ramdayalmunda

add fonts completed

parent c813ff8b
......@@ -18,6 +18,7 @@ var ADocEditor = function (customConfig) {
var footerComponent = null
var leftSidebar = null
var rightSidebar = null
var fontFamilyDropdown = null
var fontList = []
var defaultConfig = {
element: "",
......@@ -43,6 +44,7 @@ var ADocEditor = function (customConfig) {
}
var config = JSON.parse(JSON.stringify(defaultConfig));
var canvasList = []
var lastFocusCanvas = null;
const dataTypes = [
"paragraph", // simple text filled line by line
"list", // sequence of line that preserves indentation
......@@ -58,180 +60,7 @@ var ADocEditor = function (customConfig) {
},
]
// // this is the combination of paragraph and list //
dataSet = [
{
id: ++counter, type: 0, style: { ...config.style }, formatedText: [],
plainContent: "Sarah: Alex, we need some groceries from the store. Could you please go and get them?",
},
{
id: ++counter, type: 0, style: { ...config.style }, formatedText: [],
plainContent: "Alex: (Without looking up from his laptop) Mom, I'm right in the middle of something important. Can't it wait?",
},
{
id: ++counter, type: 0, style: { ...config.style }, formatedText: [],
plainContent: "Sarah: (Smiling) I understand, dear. But I've got a lot to do here, and it'd be a great help if you could pick up the groceries.",
},
{
id: ++counter, type: 0, style: { ...config.style }, formatedText: [],
plainContent: "Alex: (Sighing) Can't we go later? I've got this project deadline...",
},
{
id: ++counter, type: 0, style: { ...config.style }, formatedText: [],
plainContent: "Sarah: (Interrupting gently) Alex, we're running low on essentials. It won't take much time. Plus, some fresh air might do you good after being glued to your laptop for hours.",
},
{
id: ++counter, type: 0, style: { ...config.style }, formatedText: [],
plainContent: "Alex: (Reluctantly) But it's your day off, Mom. You should relax.",
},
{
id: ++counter, type: 0, style: { ...config.style }, formatedText: [],
plainContent: "Sarah: (Chuckling) Relaxing is fetching groceries? No worries, it's alright. I can go.",
},
{
id: ++counter, type: 0, style: { ...config.style }, formatedText: [],
plainContent: "Alex: (Feeling guilty) No, no, I'll go. Just let me finish this task, okay?",
},
{
id: ++counter, type: 0, style: { ...config.style }, formatedText: [],
plainContent: "Sarah: (Smiling warmly) Thanks, dear. I really appreciate it.",
},
{
id: ++counter, type: 0, style: { ...config.style }, formatedText: [],
plainContent: "They share a smile, and Alex closes his laptop, heading out to the store.",
},
{
id: ++counter, type: 0, style: { ...config.style }, formatedText: [],
plainContent: "Sarah: (Calling after him) Don't forget the list!",
},
{
id: ++counter, type: 0, style: { ...config.style }, formatedText: [],
plainContent: "Alex waves in acknowledgment and leaves, while Sarah returns to her cooking, content that the groceries will soon be sorted. Alex looks at the list, there were a lot of items on the list.",
},
{
id: ++counter, type: 1, style: { ...config.style }, formatedText: [],
plainContent: "Vegetables", tabCount: 0,
},
{
id: ++counter, type: 1, style: { ...config.style }, formatedText: [],
plainContent: "Carrots", tabCount: 1,
},
{
id: ++counter, type: 1, style: { ...config.style }, formatedText: [],
plainContent: "Broccli", tabCount: 1,
},
{
id: ++counter, type: 1, style: { ...config.style }, formatedText: [],
plainContent: "Bell Peppers", tabCount: 1,
},
{
id: ++counter, type: 1, style: { ...config.style }, formatedText: [],
plainContent: "Fruits", tabCount: 0,
},
{
id: ++counter, type: 1, style: { ...config.style }, formatedText: [],
plainContent: "Apples", tabCount: 1,
},
{
id: ++counter, type: 1, style: { ...config.style }, formatedText: [],
plainContent: "Oranges", tabCount: 1,
},
{
id: ++counter, type: 1, style: { ...config.style }, formatedText: [],
plainContent: "Dairy", tabCount: 0,
},
{
id: ++counter, type: 1, style: { ...config.style }, formatedText: [],
plainContent: "Milk", tabCount: 1,
},
{
id: ++counter, type: 1, style: { ...config.style }, formatedText: [],
plainContent: "Cheese", tabCount: 1,
},
{
id: ++counter, type: 1, style: { ...config.style }, formatedText: [],
plainContent: "Yogurt", tabCount: 1,
},
{
id: ++counter, type: 1, style: { ...config.style }, formatedText: [],
plainContent: "Household", tabCount: 0,
},
{
id: ++counter, type: 1, style: { ...config.style }, formatedText: [],
plainContent: "Cottonelle Toilet Paper (Pack of 6). Make sure to bring the items where each pack has 100 meter rolls.", tabCount: 1,
},
{
id: ++counter, type: 1, style: { ...config.style }, formatedText: [],
plainContent: "Mrs. Meyer's Lemon Verbena Dish Soap", tabCount: 1,
},
{
id: ++counter, type: 1, style: { ...config.style }, formatedText: [],
plainContent: "Tide Free & Gentle Laundry Detergent", tabCount: 1,
},
{
id: ++counter, type: 1, style: { ...config.style }, formatedText: [],
plainContent: "Bakery", tabCount: 0,
},
{
id: ++counter, type: 1, style: { ...config.style }, formatedText: [],
plainContent: "Bread", tabCount: 1,
},
{
id: ++counter, type: 1, style: { ...config.style }, formatedText: [],
plainContent: "Bagels", tabCount: 1,
},
{
id: ++counter, type: 0, style: { ...config.style }, formatedText: [],
plainContent: "Once Alex stepped out of his house, he felt the crisp autumn air greet him. Armed with his phone displaying Sarah's detailed grocery list, he set off on his mission to the nearby supermarket.",
},
{
id: ++counter, type: 0, style: { ...config.style }, formatedText: [],
plainContent: "The store was bustling with shoppers, but Alex navigated through the aisles with purpose. He began in the produce section, carefully selecting the freshest carrots, crisp broccoli, and vibrant red bell peppers. He lingered a moment longer in the fruit section, examining each apple, banana, and orange to ensure they met the criteria on Sarah's list.",
},
{
id: ++counter, type: 0, style: { ...config.style }, formatedText: [],
plainContent: "With the vegetables and fruits secured, he made his way to the dairy aisle. He picked up the specified 2% organic milk, sharp cheddar cheese, and Greek vanilla yogurt, double-checking the brands to match Sarah's preferences.",
},
{
id: ++counter, type: 0, style: { ...config.style }, formatedText: [],
plainContent: "Next on the list were bakery items. He chose a loaf of whole-grain bread and a pack of everything bagels, making sure they were fresh before moving on to the pantry essentials. Penne pasta, Basmati rice, fire-roasted diced tomatoes, and honey nut crunch cereal found their way into his cart.",
},
{
id: ++counter, type: 0, style: { ...config.style }, formatedText: [],
plainContent: "As he moved to the meat and protein section, he carefully selected free-range chicken breasts, a pound of lean ground beef, and a dozen farm-fresh eggs, ensuring they met the quality standards Sarah had in mind.",
},
{
id: ++counter, type: 0, style: { ...config.style }, formatedText: [],
plainContent: "After collecting household items like cottonelle toilet paper, Mrs. Meyer's lemon verbena dish soap, and Tide Free & Gentle laundry detergent, Alex made his way to the checkout counter. The cashier scanned each item, and Alex packed them meticulously into bags, arranging delicate produce separately to prevent any damage.",
},
{
id: ++counter, type: 0, style: { ...config.style }, formatedText: [],
plainContent: "Balancing the bags on his arms, Alex made his way back home. The sky had turned a warm orange hue as the sun began to set. He navigated through the busy streets, feeling a sense of accomplishment for successfully checking off every item on Sarah's exhaustive list.",
},
{
id: ++counter, type: 0, style: { ...config.style }, formatedText: [],
plainContent: "As he approached his house, he could already smell the aroma of the dinner Sarah was preparing. Alex walked in, slightly out of breath but proud of his successful grocery run.",
},
{
id: ++counter, type: 0, style: { ...config.style }, formatedText: [],
plainContent: `"Hey, Mom, I'm back!" he called out.`,
},
{
id: ++counter, type: 0, style: { ...config.style }, formatedText: [],
plainContent: `Sarah, busy at the stove, turned around, beaming. "Oh, Alex, you're a lifesaver! Did you manage to get everything?"`,
},
{
id: ++counter, type: 0, style: { ...config.style }, formatedText: [],
plainContent: `"Absolutely," Alex replied, setting the bags down on the counter. "And I even got the specific brands and types you asked for!"`,
},
{
id: ++counter, type: 0, style: { ...config.style }, formatedText: [],
plainContent: `Sarah gave him a grateful smile. "Thank you so much, Alex. You're a star! Now, dinner will be ready in no time."`,
},
{
id: ++counter, type: 0, style: { ...config.style }, formatedText: [],
plainContent: `As they unpacked the groceries together, Sarah couldn't help but appreciate her thoughtful son's effort and attention to detail, making the task much more manageable and enjoyable for her.`,
},
]
// dataSet=[{id:++counter,type:0,style:{...config.style},formatedText:[],plainContent:"Sarah: Alex, we need some groceries from the store. Could you please go and get them?"},{id:++counter,type:0,style:{...config.style},formatedText:[],plainContent:"Alex: (Without looking up from his laptop) Mom, I'm right in the middle of something important. Can't it wait?"},{id:++counter,type:0,style:{...config.style},formatedText:[],plainContent:"Sarah: (Smiling) I understand, dear. But I've got a lot to do here, and it'd be a great help if you could pick up the groceries."},{id:++counter,type:0,style:{...config.style},formatedText:[],plainContent:"Alex: (Sighing) Can't we go later? I've got this project deadline..."},{id:++counter,type:0,style:{...config.style},formatedText:[],plainContent:"Sarah: (Interrupting gently) Alex, we're running low on essentials. It won't take much time. Plus, some fresh air might do you good after being glued to your laptop for hours."},{id:++counter,type:0,style:{...config.style},formatedText:[],plainContent:"Alex: (Reluctantly) But it's your day off, Mom. You should relax."},{id:++counter,type:0,style:{...config.style},formatedText:[],plainContent:"Sarah: (Chuckling) Relaxing is fetching groceries? No worries, it's alright. I can go."},{id:++counter,type:0,style:{...config.style},formatedText:[],plainContent:"Alex: (Feeling guilty) No, no, I'll go. Just let me finish this task, okay?"},{id:++counter,type:0,style:{...config.style},formatedText:[],plainContent:"Sarah: (Smiling warmly) Thanks, dear. I really appreciate it."},{id:++counter,type:0,style:{...config.style},formatedText:[],plainContent:"They share a smile, and Alex closes his laptop, heading out to the store."},{id:++counter,type:0,style:{...config.style},formatedText:[],plainContent:"Sarah: (Calling after him) Don't forget the list!"},{id:++counter,type:0,style:{...config.style},formatedText:[],plainContent:"Alex waves in acknowledgment and leaves, while Sarah returns to her cooking, content that the groceries will soon be sorted. Alex looks at the list, there were a lot of items on the list."},{id:++counter,type:1,style:{...config.style},formatedText:[],plainContent:"Vegetables",tabCount:0},{id:++counter,type:1,style:{...config.style},formatedText:[],plainContent:"Carrots",tabCount:1},{id:++counter,type:1,style:{...config.style},formatedText:[],plainContent:"Broccli",tabCount:1},{id:++counter,type:1,style:{...config.style},formatedText:[],plainContent:"Bell Peppers",tabCount:1},{id:++counter,type:1,style:{...config.style},formatedText:[],plainContent:"Fruits",tabCount:0},{id:++counter,type:1,style:{...config.style},formatedText:[],plainContent:"Apples",tabCount:1},{id:++counter,type:1,style:{...config.style},formatedText:[],plainContent:"Oranges",tabCount:1},{id:++counter,type:1,style:{...config.style},formatedText:[],plainContent:"Dairy",tabCount:0},{id:++counter,type:1,style:{...config.style},formatedText:[],plainContent:"Milk",tabCount:1},{id:++counter,type:1,style:{...config.style},formatedText:[],plainContent:"Cheese",tabCount:1},{id:++counter,type:1,style:{...config.style},formatedText:[],plainContent:"Yogurt",tabCount:1},{id:++counter,type:1,style:{...config.style},formatedText:[],plainContent:"Household",tabCount:0},{id:++counter,type:1,style:{...config.style},formatedText:[],plainContent:"Cottonelle Toilet Paper (Pack of 6). Make sure to bring the items where each pack has 100 meter rolls.",tabCount:1},{id:++counter,type:1,style:{...config.style},formatedText:[],plainContent:"Mrs. Meyer's Lemon Verbena Dish Soap",tabCount:1},{id:++counter,type:1,style:{...config.style},formatedText:[],plainContent:"Tide Free & Gentle Laundry Detergent",tabCount:1},{id:++counter,type:1,style:{...config.style},formatedText:[],plainContent:"Bakery",tabCount:0},{id:++counter,type:1,style:{...config.style},formatedText:[],plainContent:"Bread",tabCount:1},{id:++counter,type:1,style:{...config.style},formatedText:[],plainContent:"Bagels",tabCount:1},{id:++counter,type:0,style:{...config.style},formatedText:[],plainContent:"Once Alex stepped out of his house, he felt the crisp autumn air greet him. Armed with his phone displaying Sarah's detailed grocery list, he set off on his mission to the nearby supermarket."},{id:++counter,type:0,style:{...config.style},formatedText:[],plainContent:"The store was bustling with shoppers, but Alex navigated through the aisles with purpose. He began in the produce section, carefully selecting the freshest carrots, crisp broccoli, and vibrant red bell peppers. He lingered a moment longer in the fruit section, examining each apple, banana, and orange to ensure they met the criteria on Sarah's list."},{id:++counter,type:0,style:{...config.style},formatedText:[],plainContent:"With the vegetables and fruits secured, he made his way to the dairy aisle. He picked up the specified 2% organic milk, sharp cheddar cheese, and Greek vanilla yogurt, double-checking the brands to match Sarah's preferences."},{id:++counter,type:0,style:{...config.style},formatedText:[],plainContent:"Next on the list were bakery items. He chose a loaf of whole-grain bread and a pack of everything bagels, making sure they were fresh before moving on to the pantry essentials. Penne pasta, Basmati rice, fire-roasted diced tomatoes, and honey nut crunch cereal found their way into his cart."},{id:++counter,type:0,style:{...config.style},formatedText:[],plainContent:"As he moved to the meat and protein section, he carefully selected free-range chicken breasts, a pound of lean ground beef, and a dozen farm-fresh eggs, ensuring they met the quality standards Sarah had in mind."},{id:++counter,type:0,style:{...config.style},formatedText:[],plainContent:"After collecting household items like cottonelle toilet paper, Mrs. Meyer's lemon verbena dish soap, and Tide Free & Gentle laundry detergent, Alex made his way to the checkout counter. The cashier scanned each item, and Alex packed them meticulously into bags, arranging delicate produce separately to prevent any damage."},{id:++counter,type:0,style:{...config.style},formatedText:[],plainContent:"Balancing the bags on his arms, Alex made his way back home. The sky had turned a warm orange hue as the sun began to set. He navigated through the busy streets, feeling a sense of accomplishment for successfully checking off every item on Sarah's exhaustive list."},{id:++counter,type:0,style:{...config.style},formatedText:[],plainContent:"As he approached his house, he could already smell the aroma of the dinner Sarah was preparing. Alex walked in, slightly out of breath but proud of his successful grocery run."},{id:++counter,type:0,style:{...config.style},formatedText:[],plainContent:'"Hey, Mom, I\'m back!" he called out.'},{id:++counter,type:0,style:{...config.style},formatedText:[],plainContent:'Sarah, busy at the stove, turned around, beaming. "Oh, Alex, you\'re a lifesaver! Did you manage to get everything?"'},{id:++counter,type:0,style:{...config.style},formatedText:[],plainContent:'"Absolutely," Alex replied, setting the bags down on the counter. "And I even got the specific brands and types you asked for!"'},{id:++counter,type:0,style:{...config.style},formatedText:[],plainContent:'Sarah gave him a grateful smile. "Thank you so much, Alex. You\'re a star! Now, dinner will be ready in no time."'},{id:++counter,type:0,style:{...config.style},formatedText:[],plainContent:"As they unpacked the groceries together, Sarah couldn't help but appreciate her thoughtful son's effort and attention to detail, making the task much more manageable and enjoyable for her."},];
var lines = []
var caretData = {
......@@ -267,6 +96,7 @@ var ADocEditor = function (customConfig) {
let scrollingAreaId = `scrolling-area-${new Date().getTime()}`
let leftSidebarId = `left-sidebar-${new Date().getTime()}`
let rightSidebarId = `right-sidebar-${new Date().getTime()}`
let fontFamilyDropdownId = `font-family-${new Date().getTime()}`
let htmlSetup = /*html*/`
<div class="a-doc-editor" id="${mainComponentId}">
<div class="header" id="${headerComponentId}">
......@@ -282,7 +112,9 @@ var ADocEditor = function (customConfig) {
<span class="option">Undo</span>
<span class="option">Redo</span>
<span class="option">Heading</span>
<span class="option">Font Family</span>
<span class="option">
<select id="${fontFamilyDropdownId}"></select>
</span>
<span class="option">Font Size</span>
<span class="option">Bold</span>
<span class="option">Italic</span>
......@@ -336,7 +168,9 @@ var ADocEditor = function (customConfig) {
mainComponent.getElementsByClassName('toggle-sidebar')[1].addEventListener('click', (e) => {
rightSidebar.classList.toggle('hide')
})
fontFamilyDropdown = document.getElementById(fontFamilyDropdownId)
fontFamilyDropdown.addEventListener( 'change', changeFontFamily )
reRenderFontDropdown()
let generatePDFBtn = document.querySelector('[a-doc-editor-action]')
generatePDFBtn.addEventListener('click', generatePDF)
}
......@@ -346,6 +180,7 @@ var ADocEditor = function (customConfig) {
}
function reRenderPages(dataList, option) {
if (renderInProgress) return
renderInProgress = true
......@@ -444,6 +279,7 @@ var ADocEditor = function (customConfig) {
let charWidth = getCharacterWidth(canvasIndex, dataBlock.plainContent[i], style)
dataBlock.formatedText[i] = {
...config.style,
...dataBlock.formatedText[i],
width: charWidth
}
......@@ -564,7 +400,7 @@ var ADocEditor = function (customConfig) {
// handle left right on multiple pages
if (activeLine) {
if (!isModule) canvasList[activeLine.canvasIndex].el.focus()
if (!isModule && option?.scrollIntoView) canvasList[activeLine.canvasIndex].el.focus()
caretData.canvasIndex = activeLine.canvasIndex
ctx.restore()
ctx = canvasList[activeLine.canvasIndex].el.getContext('2d', { willReadFrequently: true })
......@@ -597,6 +433,12 @@ var ADocEditor = function (customConfig) {
// Alpha channel remains unchanged (data[i + 3])
ctx.putImageData(imageData, rectX, rectY);
}
if (characterData){
caretData.style = { ...characterData }
}else{
caretData.style = { ...caretData.activeData.style }
}
// fontFamilyDropdown.value = caretData.style.fontFamily
ctx.restore()
}
......@@ -626,8 +468,8 @@ var ADocEditor = function (customConfig) {
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.addEventListener("focus", onFocusHandler)
canvas.addEventListener("blur", onBlurHandler)
canvas.setAttribute("tabIndex", -1)
scrollingComponent.append(canvas)
}
......@@ -640,9 +482,10 @@ var ADocEditor = function (customConfig) {
reRenderPages(dataSet)
}
function onBlurHandler(e) {
lastFocusCanvas = e.target
focusedCanvas = null
caretData.blink = false
reRenderPages(dataSet)
reRenderPages(dataSet, { scrollIntoView: false })
clearInterval(caretData.interval)
}
......@@ -652,8 +495,14 @@ var ADocEditor = function (customConfig) {
caretData.blink = false
if (e.shiftKey && (e.ctrlKey || e.metaKey)) { } // ctr+shift combination
else if (e.ctrlKey || e.metaKey) {
if (e.shiftKey && (e.ctrlKey || e.metaKey)) {
return
}
else if (e.keyCode==16){ // only shift key
return
}
// ctr+shift combination
else if (e.ctrlKey || e.metaKey) { // only ctrl or meta key
if (e.keyCode == 8) { // ctrl+backspace: delete the entrite word
let separatedSentence = caretData.activeData.plainContent.slice(0, caretData.index)
let indexOfpreviousBlankChar = separatedSentence.search(/[^a-zA-Z0-9](?=[a-zA-Z0-9]*$)/)
......@@ -691,8 +540,13 @@ var ADocEditor = function (customConfig) {
}
}
}
else if (e.key.length == 1 || e.keyCode == 32) {
else if (e.key.length == 1 || e.keyCode == 32) { // these are printable characters key
e.preventDefault()
caretData.style.fontFamily = fontFamilyDropdown.value
caretData.activeData.formatedText[caretData.index] = { ...caretData.style }
caretData.activeData.plainContent = caretData.activeData.plainContent.slice(0, caretData.index) + e.key + caretData.activeData.plainContent.slice(caretData.index)
++caretData.index
}
......@@ -907,54 +761,63 @@ var ADocEditor = function (customConfig) {
document.body.removeChild(downloadLink)
}
function addFonts(paths, name) {
function addFonts(paths, name){
if (typeof paths == 'string') paths = [ paths ]
let fontObj = {
paths: [],
name: name,
}
if (!isModule) {
if (fontList.find(item => item.name.toLowerCase() == name.toLowerCase())) {
throw "Font: Already Exists"
let linkString = ''
for(let i=0; i<paths.length; i++){
let format = paths[i].split('.');
format = format[format.length-1]
linkString += `url(${paths[i]}) format("${format=='ttf'?'truetype':format}")${(i>=paths.length-1)?'':',\n'}`
}
const customFont = new FontFace('YourCustomFont', `${linkString}`);
customFont.load()
.then( (loadedFont)=>{
document.fonts.add(loadedFont);
loadedFont.loaded.then( ()=>{
fontList.push(fontObj)
reRenderFontDropdown()
} )
} )
}
let newStyle = `${styleTag.textContent}
@font-face {
font-family: '${name}';
src:
`
if (typeof paths == 'object') {
for (let i = 0; i < paths.length; i++) {
let linkTag = document.createElement('link')
linkTag.onload = () => { reRenderPages(dataSet) }
linkTag.href = paths[i]
linkTag.rel = "stylesheet"
document.head.append(linkTag)
let splitted = paths[i].split('.')
let format = splitted[splitted.length - 1]
format = format == 'ttf' ? 'truetype' : format
newStyle += `url('${paths[i]}') format('${format}')${(i == paths.length - 1) ? ';' : ','}
`
}
} else {
let linkTag = document.createElement('link')
linkTag.onload = () => { reRenderPages(dataSet) }
linkTag.href = paths
let splitted = paths.split('.')
document.head.append(linkTag)
let format = splitted[splitted.length - 1]
format = format == 'ttf' ? 'truetype' : format
newStyle += `url('${paths}') format('${format}');`
// // these are methods related to the toolbar items
function changeFontFamily(e){
caretData.style.fontFamily = e.target.value
caretData.styleModified = false
if (lastFocusCanvas){
lastFocusCanvas.focus({ preventScroll: true })
}
newStyle += `
if (!caretData.activeData.plainContent.length){
caretData.activeData.style.fontFamily = e.target.value
}
`
styleTag.textContent = newStyle
container.append(styleTag)
}
fontList.push({
path: path,
name: name,
})
function reRenderFontDropdown(){
if (fontFamilyDropdown){
fontFamilyDropdown.innerHTML = ""
fontList.forEach( (font,i)=>{
let optionTag = document.createElement('option')
optionTag.setAttribute('value', font.name)
optionTag.innerHTML = font.name
fontFamilyDropdown.append(optionTag)
} )
}
}
inititalize(customConfig)
function destory() {
......
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