diff --git a/service.js b/service.js index a3fa1f3..0e3026d 100644 --- a/service.js +++ b/service.js @@ -41,7 +41,7 @@ class BesService { this.enabledCategories = [] this.disabledCategories = [] this.results = [] // Results of grammar-checking, one per each block/paragraph of text - this.highlightedRects = [] + this.highlightElements = [] this.createCorrectionPanel() // Disable browser built-in spell-checker to prevent collision with our grammar markup. @@ -58,7 +58,7 @@ class BesService { this.hostElement.setAttribute('data-gramm', 'false') this.hostElement.setAttribute('data-gramm_editor', 'false') this.hostElement.setAttribute('data-enable-grammarly', 'false') - this.textFont = window.getComputedStyle(this.textElement).fontFamily + this.textFont = window.getComputedStyle(this.hostElement).fontFamily this.onScroll = this.onScroll.bind(this) this.hostElement.addEventListener('scroll', this.onScroll) @@ -334,8 +334,8 @@ class BesService { const dpr = window.devicePixelRatio this.ctx.lineWidth = 2 * dpr // Use 2 for clearer visibility this.ctx.strokeStyle = ruleId.startsWith('MORFOLOGIK_RULE') - ? '#ff7300' - : '#007bff' + ? 'rgba(255, 115, 0, 0.5)' + : 'rgba(0, 123, 255, 0.5)' for (let rect of range.getClientRects()) { const x = (rect.left - scrollPanelRect.left) * dpr const y = (rect.top - scrollPanelRect.top) * dpr @@ -455,7 +455,9 @@ class BesService { * @param {PointerEvent} source Click event source */ popupCorrectionPanel(el, match, source) { + this.dismissPopup() const popup = document.querySelector('bes-popup-el') + // TODO: popup.setContent(elements, matches, this, this.isContentEditable()) popup.changeMessage(match.match.message) popup.appendReplacements(el, match, this, this.isContentEditable()) this.highlightMistake(match) @@ -469,27 +471,32 @@ class BesService { */ highlightMistake(match) { // TODO: Če sta 2 napaki v istem rectu, se prikaže samo zgornja/zadnja (oz. tista, ki jo uporabnik klikne). To pa pomeni, da se lahko podčrtana barva razlikuje od "highlight" barve. - const highlightColor = match.match.rule.id.startsWith('MORFOLOGIK_RULE') - ? '#ff7300' - : '#007bff' - - match.highlights.forEach(highlight => { - const rect = highlight - const highlightElement = document.createElement('div') - highlightElement.classList.add('highlight-rect') - highlightElement.style.position = 'absolute' - highlightElement.style.left = `${rect.x}px` - highlightElement.style.top = `${rect.y}px` - highlightElement.style.width = `${rect.width}px` - highlightElement.style.height = `${rect.height}px` - highlightElement.style.backgroundColor = highlightColor - highlightElement.style.opacity = '0.5' - highlightElement.style.cursor = 'text' - document.body.appendChild(highlightElement) - this.highlightedRects.push(highlightElement) + match.highlights.forEach(rect => { + const el = document.createElement('div') + el.classList.add('bes-highlight-rect') + el.classList.add( + match.match.rule.id.startsWith('MORFOLOGIK_RULE') + ? 'bes-highlight-spelling-rect' + : 'bes-highlight-grammar-rect' + ) + el.style.left = `${rect.x}px` + el.style.top = `${rect.y}px` + el.style.width = `${rect.width}px` + el.style.height = `${rect.height}px` + document.body.appendChild(el) + this.highlightElements.push(el) }) } + /** + * Clears highlight and hides popup + */ + dismissPopup() { + BesPopup.hide() + this.highlightElements.forEach(el => el.remove()) + this.highlightElements = [] + } + /** * Checks if host element content is editable. * @@ -764,34 +771,10 @@ class BesTreeService extends BesService { * @param {Element} el DOM element for removal */ clearProofing(el) { - this.clearMarkup(el) this.results = this.results.filter( result => !BesTreeService.isSameParagraph(result.element, el) ) - } - - /** - * Clears given block element grammar mistake markup. - * - * @param {Element} el DOM element we want to clean markup for - */ - clearMarkup(el) { - const dpr = window.devicePixelRatio - this.results - .filter(result => BesTreeService.isSameParagraph(result.element, el)) - .forEach(result => { - let sourceRect = result.element.getBoundingClientRect() - let targetRect = this.canvasPanel.getBoundingClientRect() - let newX = sourceRect.left - targetRect.left - let newY = sourceRect.top - targetRect.top - this.ctx.clearRect( - newX * dpr, - newY * dpr, - sourceRect.width * dpr, - sourceRect.height * dpr - ) - delete result.matches - }) + this.repositionAllMarkup() } /** @@ -930,16 +913,15 @@ class BesTreeService extends BesService { for (let result of this.results) { for (let m of result.matches) { - for (let h of m.highlights) { - if (BesService.isPointInRect(source.clientX, source.clientY, h)) { + for (let rect of m.highlights) { + if (BesService.isPointInRect(source.clientX, source.clientY, rect)) { this.popupCorrectionPanel(el, m, source) return } } } } - BesPopup.hide() - this.highlightedRects.forEach(h => h.remove()) + this.dismissPopup() } } @@ -1024,8 +1006,7 @@ class BesDOMService extends BesTreeService { onInput() { // Now that the text is done changing, we can correctly calculate markup position. this.repositionAllMarkup() - BesPopup.hide() - this.highlightedRects.forEach(h => h.remove()) + this.dismissPopup() // Defer grammar-checking to reduce stress on grammar-checking server. this.scheduleProofing(1000) } @@ -1536,30 +1517,10 @@ class BesPlainTextService extends BesService { * @param {Range} range Paragraph range */ clearProofing(range) { - this.clearMarkup(range) this.results = this.results.filter( result => !BesPlainTextService.isSameParagraph(result.range, range) ) - } - - /** - * Clears given paragraph grammar mistake markup. - * - * @param {Range} range Paragraph range - */ - clearMarkup(range) { - this.results - .filter(result => - BesPlainTextService.isSameParagraph(result.range, range) - ) - .forEach(result => - result.matches.forEach(match => { - if (match.highlights) { - match.highlights.forEach(h => h.remove()) - delete match.highlights - } - }) - ) + this.repositionAllMarkup() } /** @@ -1605,16 +1566,15 @@ class BesPlainTextService extends BesService { for (let result of this.results) { for (let m of result.matches) { - for (let h of m.highlights) { - if (BesService.isPointInRect(source.clientX, source.clientY, h)) { + for (let rect of m.highlights) { + if (BesService.isPointInRect(source.clientX, source.clientY, rect)) { this.popupCorrectionPanel(result.range, m, source) return } } } } - BesPopup.hide() - this.highlightedRects.forEach(h => h.remove()) + this.dismissPopup() } /** @@ -1729,8 +1689,7 @@ class BesDOMPlainTextService extends BesPlainTextService { // Now that the text is done changing, we can correctly calculate markup position. this.repositionAllMarkup() - BesPopup.hide() - this.highlightedRects.forEach(h => h.remove()) + this.dismissPopup() // Defer grammar-checking to reduce stress on grammar-checking server. this.scheduleProofing(1000) } @@ -1862,28 +1821,21 @@ class BesTAService extends BesPlainTextService { const styles = window.getComputedStyle(hostElement) textElement.style.zIndex = hostElement.style.zIndex - 1 - textElement.style.fontSize = styles.fontSize - textElement.style.fontFamily = styles.fontFamily + textElement.style.font = styles.font textElement.style.lineHeight = styles.lineHeight textElement.style.whiteSpace = styles.whiteSpace textElement.style.whiteSpaceCollapse = styles.whiteSpaceCollapse textElement.style.hyphens = styles.hyphens + textElement.style.boxSizing = styles.boxSizing + textElement.style.scrollBehavior = styles.scrollBehavior + textElement.style.overflow = 'hidden' textElement.style.border = styles.border textElement.style.borderRadius = styles.borderRadius - textElement.style.paddingLeft = styles.paddingLeft - textElement.style.paddingTop = styles.paddingTop - textElement.style.paddingRight = styles.paddingRight - textElement.style.paddingBottom = styles.paddingBottom - textElement.style.height = styles.height - textElement.style.minHeight = styles.minHeight - textElement.style.maxHeight = styles.maxHeight - textElement.style.overflow = styles.overflow - textElement.style.overflowWrap = styles.overflowWrap - textElement.style.top = `${rect.top + scrollTop}px` + textElement.style.padding = styles.padding textElement.style.left = `${rect.left + scrollLeft}px` + textElement.style.top = `${rect.top + scrollTop}px` textElement.style.width = styles.width - textElement.style.minWidth = styles.minWidth - textElement.style.maxWidth = styles.maxWidth + textElement.style.height = styles.height } /** @@ -2137,7 +2089,7 @@ class BesPopup extends HTMLElement {
Besana
- +
@@ -2210,7 +2162,7 @@ class BesPopup extends HTMLElement { replacementBtn.addEventListener('click', () => { if (allowReplacements) { service.replaceText(el, match, replacement.value) - BesPopup.hide() + service.dismissPopup() } }) replacementDiv.appendChild(replacementBtn) @@ -2274,167 +2226,24 @@ class BesPopup extends HTMLElement { } /** - * Dismisses all the popups. + * Hides all the popups. */ static hide() { document.querySelectorAll('bes-popup-el').forEach(popup => { popup.classList.remove('show') }) - document.querySelectorAll('.bes-mistake-highlight-selected').forEach(el => { - el.classList.remove('bes-mistake-highlight-selected') - }) + } + + /** + * Dismisses all the popups. + */ + static dismiss() { + besServices.forEach(service => service.dismissPopup()) } } customElements.define('bes-popup-el', BesPopup) -// /************************************************************************* -// * -// * Status pop-up -// * -// *************************************************************************/ -// class BesStatusPopup extends HTMLElement { -// constructor() { -// super() -// this.attachShadow({ mode: 'open' }) -// } - -// /** -// * Called each time the element is added to the document -// */ -// connectedCallback() { -// this.shadowRoot.innerHTML = ` -// -//
-//
-//
Besana
-// -//
-//
-// -// Če želite izključiti preverjanje pravopisa, kliknite na gumb. -// -// -//
-//
-// ` -// } - -// /** -// * Shows popup window. -// * -// * @param {Number} x X location hint -// * @param {Number} y Y location hint -// * @param {BesService} service Grammar checking service -// */ -// show(x, y, service) { -// this.style.position = 'fixed' -// this.style.display = 'block' - -// // Element needs some initial placement for the browser to provide this.offsetWidth and this.offsetHeight measurements. -// // The fade-in effect on the popup window should prevent flicker. -// this.style.left = `0px` -// this.style.top = `0px` -// this.classList.add('show') - -// if (x + this.offsetWidth <= window.innerWidth) { -// this.style.left = `${x}px` -// } else if (this.offsetWidth <= x) { -// this.style.left = `${x - this.offsetWidth}px` -// } else { -// this.style.left = `${x - this.offsetWidth / 2}px` -// } - -// if (y + 20 + this.offsetHeight <= window.innerHeight) { -// this.style.top = `${y + 20}px` -// } else if (this.offsetHeight <= y) { -// this.style.top = `${y - this.offsetHeight}px` -// } else { -// this.style.top = `${y - this.offsetHeight / 2}px` -// } - -// if (service) { -// const disableButton = this.shadowRoot.querySelector('.bes-service-btn') -// disableButton.onclick = () => { -// service.unregister() -// BesStatusPopup.hide() -// } -// } -// this.classList.add('show') -// } - -// /** -// * Dismisses all the popups. -// */ -// static hide() { -// const popup = document.querySelector('bes-popup-status.show') -// popup?.classList?.remove('show') -// } -// } - -// customElements.define('bes-popup-status', BesStatusPopup) - // Auto-register all elements with bes-service class. window.addEventListener('load', () => { document diff --git a/styles.css b/styles.css index 8159993..9cd8425 100644 --- a/styles.css +++ b/styles.css @@ -8,32 +8,26 @@ cursor: text; } -/* TODO: Cleanup */ -.bes-grammar-mistake { - border-bottom: 2px solid #007bff; +.bes-highlight-rect { position: absolute; - z-index: 3; + opacity: 0.3; cursor: text; } +.bes-highlight-spelling-rect { + background: rgb(255, 115, 0); +} + +.bes-highlight-grammar-rect { + background: rgb(0, 123, 255); +} + .bes-canvas { position: relative; z-index: 3; cursor: text; } -/* TODO: Cleanup */ -.bes-spelling-mistake.bes-mistake-highlight-selected { - background: #cc7024; - opacity: 0.5; -} - -/* TODO: Cleanup */ -.bes-grammar-mistake.bes-mistake-highlight-selected { - background: #3691f3; - opacity: 0.5; -} - /* Styles required to ensure full functionality and optimal user experience. */ .bes-correction-panel-parent { position: relative;