addRange(): The given range isn't in document Quill warning - javascript

I'm using react-quill library, the editor is working fine, I added undo redo buttons to the editor and still working fine, but when I passed props {onChange, defaultValue} , I get this warning:
addRange(): The given range isn't in document.
whenever I type in the editor the editor disappear from the page and the console gives the above warning.
Live Preview of the issue:
https://codesandbox.io/s/weathered-framework-m5hk0u?file=/src/NewPost.jsx
Please Check TextEditor.jsx
I think the error is from here
const undoHandler = () => {
reactQuillRef.current.editor.history.undo("undo");
};
const redoHandler = () => {
reactQuillRef.current.editor.history.redo("redo");
};
What I think what makes the error is current.editor, and the question is how to fix it? how to set content to the editor? Some help would be appreciated.

Related

How to integrate Quill-comment with React-quill?

I currently have this Code SandBox where I am trying to get React-Quill and Quill-Comment to work together so that I can let users comment on content that has been written.
Quill comment is not a react package and I am a react noob so I don't know if what I am trying to do it even possible. It appears to partially work because the toolbar add comment button registers the click event.
let commentCallback;
function commentAddClick(callback) {
setOpen(true); //show the modal
commentCallback = callback; //Appears to do nothing?
console.log("callback :>> ", callback); //Nothing is ever in the callback
console.log("commentAddClick");
}
However, the callback value doesn't appear to have or do anything. When I click the add comment button in the modal:
const commentSave = () => {
const comment = "This is a comment, forced for testing";
commentCallback(comment);
console.log("comment :>> ", comment);
//let comment = $('#commentInput').val();
commentCallback(comment);
addCommentToList(comment, currentTimestamp);
};
it throws an error that tells me
commentCallback is not a function
I am attempting to following the Vanilla JS example see line 68 here. I assume this problem is related to this warning message that spams on every keypress.
quill:toolbar ignoring attaching to nonexistent format comments-add
<button type="button" class="ql-comments-add"></button>
How do I resolve the warning message, and get the callback to work? Or, secondarily, is there another good commenting library that will work with Quill?
A working example in Vanilla JS can be found here:
https://github.com/nhaouari/quill-comment/tree/master/example/quill-comment-test
I'd like to replicate this in React.
The library you are referring to says that callback function will be null when nothing is selected in the editor. So, you need to select some text in the editor for the callback function to work.

Cypress Iframe Handling - Failure to interact with Button

I am trying to E2E test an auth flow with Cypress that includes a third party method called BankID. BankId is integrated through three nested iframes that I can successfully access. However, when I type into the input field via cy.type('12345678912'), BankId does not register this as trusted events and never unlocks the submit button with the arrow.
According to this issue here, Cypress does not intend to support native browser events and suggests to use the package cypress-real-events. When using this via cy.realType('12345678912'), it actually succeeds in unlocking the submit button. However i can never successfully click the submit button, neither with .click() or even the package method .realClick().
The error is: "Failed to execute 'getComputedStyle' on 'Window': parameter 1 is not of type 'Element'."
I uploaded a sample repository with an minimal testing version here.
Any feedback or hints would be greatly appreciated :)
Here is the relevant code:
/// <reference types="cypress" />
import { skipOn } from '#cypress/skip-test'
describe('Recipe: blogs__iframes', () => {
skipOn('firefox', () => {
it('do it more generically', () => {
const getIframeBody = (identifier) => {
return cy
.get(identifier)
.its('0.contentDocument.body')
.should('not.be.empty')
.then(cy.wrap)
}
// Visiting the page index.html and getting iframe A
cy.visit('index.html').contains('XHR in iframe')
getIframeBody('iframe[data-cy="bankid"]').as('iframeA')
cy.get('#iframeA').within(() => {
getIframeBody('iframe[src="https://tools.bankid.no/bankid-test/auth"]').as('iframeB')
cy.get('#iframeB').within(() => {
getIframeBody('iframe[src^="https://csfe.bankid.no/CentralServerFEJS"]').as('iframeC')
// Now we are in the right place and it finds the correct input element.
// However, normal cypress command .type() fails and we have to use library cypress-real-events,
// which provides an event firing system that works literally like in puppeteer
cy.get('#iframeC').find('input[type="tel"]').should('be.visible').realType('12345678912')
// But for the button below, this library now doesn't help anymore:
// "Failed to execute 'getComputedStyle' on 'Window': parameter 1 is not of type 'Element'."
cy.get('#iframeC').find('button[type="submit"]').should('be.visible').first().realClick()
})
})
})
})
})
I also posted this problem on https://github.com/dmtrKovalenko/cypress-real-events/issues/226 and got an answer there:
Using .realClick({ scrollBehavior: false }); solved the issue.
The problem is if the webapp is not scrolling as expected, therefore leading to Cypress not finding the element. In my case, i made the iframe wider to avoid needing to scroll and the issue was still there, but the workaround solved it anyway.

Uncaught TypeError: Cannot read property 'addEventListener' of null (multiple forms)

Hello fellow developers,
I have a simple question. I'm working on my javascript skills, which are obviously not the best :). I'm trying to code a search box with the giphy API, by tutorial. My code was working to 100% like the code displayed in the tutorial until video 5, but now (video 6) it's not working anymore.
I'm getting the error "Uncaught TypeError: Cannot read property 'addEventListener' of null". I googled a lot and tried the fixes which I found here, but they are not working on my code :/ The funny part of this is, that my code is working on codepen.io! So the only difference between codepen and my local website, are multiple search forms and bootstrap. So I'm guessing the problem are multiple search forms, because of this lines:
const searchGif = document.getElementById("search-gif");
const searchInput = document.getElementById("gif-search-string");
searchGif.addEventListener('submit', function(event){
event.preventDefault();
const query = searchInput.value;
search(query);
})
But I thought because I'm grabbing the right form by ID before I execute the rest of my javascript code, it is ok? So I hope that you can help me to resolve my problem. Like I said, I'm not very good in JS and just trying to get better and better <3.
PS: loading my script by script tag at the end of the html body
PS2: Here is my complete HTML Code -> index.php - timeline-gif.php
It's how you "start" your code. Loaded !== rendered (not 100% sure that these are the correct terms).
Try to wrap it in a self executing function:
(function() {
// Put your code here - dom should be available
})();

DOMException on calling navigator.clipboard.readText()

Following lines of code used to work and stopped working after chrome upgrade to Version 74.0.3729.169 (Official Build) (64-bit). Now I get DOMException even though permission is set correctly. Appreciate if you can explain what is the bug and workaround. Exception details:
message:Document is not focused
name:NotAllowedError
code:0
navigator.permissions.query({ name: 'clipboard-read' }).then(result => {
// If permission to read the clipboard is granted or if the user will
// be prompted to allow it, we proceed.
if (result.state === 'granted' || result.state === 'prompt') {
navigator.clipboard.readText()
.then(text => {
//my code to handle paste
})
.catch(err => {
console.error('Failed to read clipboard contents: ', err);
});
}
}
This seems to happen when executing code from the devtools console or snippets.
Workaround:
You can execute the code below and focus on the window within 3 seconds, by clicking somewhere, or just by pressing <tab>.
e.g. from snippets
Ctrl-Enter
<Tab>
e.g. from console
Enter
<Tab>
setTimeout(async()=>console.log(
await window.navigator.clipboard.readText()), 3000)
The issue I was having was that I had an alert to say that the text had been copied, and that was removing focus from the document. Ironically, this caused the text to not be copied. The workaround was quite simple:
clipboard.writeText(clippy_button.href).then(function(x) {
alert("Link copied to clipboard: " + clippy_button.href);
});
Just show the alert when the Promise is resolved. This might not fix everybody's issue but if you came here based on searching for the error this might be the correct fix for your code.
As Kaiido said, your DOM need to be focused. I had the same problem during my development when i put a breakpoint in the code... The console developper took the focused and the error appear. With the same code and same browser, all work fine if F12 is closed
Problem
It's a security risk, clearly. :)
Solution
I assume you face this when you are trying to call it from the dev tools. Well, to make life easier, I am taking Jannis's answer, to a less adrenaline-oriented way. :)
I am adding a one-time focus listener to window to do the things magically after hitting "tab" from the Devtools.
function readClipboardFromDevTools() {
return new Promise((resolve, reject) => {
const _asyncCopyFn = (async () => {
try {
const value = await navigator.clipboard.readText();
console.log(`${value} is read!`);
resolve(value);
} catch (e) {
reject(e);
}
window.removeEventListener("focus", _asyncCopyFn);
});
window.addEventListener("focus", _asyncCopyFn);
console.log("Hit <Tab> to give focus back to document (or we will face a DOMException);");
});
}
// To call:
readClipboardFromDevTools().then((r) => console.log("Returned value: ", r));
Note: The return value is a Promise as it's an asynchronous call.
if you want to debug a and play around to view result. also can hide this <p></p>.
async function readClipboard () {
if (!navigator.clipboard) {
// Clipboard API not available
return
}
try {
const text = await navigator.clipboard.readText();
document.querySelector('.clipboard-content').innerText = text;
} catch (err) {
console.error('Failed to copy!', err)
}
}
function updateClipboard() {
// Here You Can Debug without DomException
debugger
const clipboard = document.querySelector('.clipboard-content').innerText;
document.querySelector('.clipboard-content').innerText = 'Updated => ' + clipboard;
}
<button onclick="readClipboard()">Paste</button>
<p class="clipboard-content"></p>
<button onclick="updateClipboard()">Edit</button>
As the exception message says, you need to have the Document actively focused in order to use this API.
Suppose there is a p element. you want to copy its innerText.
So, lets not use navigation.clipboard (because 0f the error your are facing)
So below given is a example which copies the innerText of the p element when that button is clicked. your do not to rely upon "clicking" the button manually by using the code below. you can trigger the "click" by executing code like pElement.click() from devtools console.
Your devtools console problem, that #jannis-ioannou mentioned in his post above, will not occur!
function myFunction() {
var copyText = document.getElementById("copy-my-contents");
var range = document.createRange();
var selection = window.getSelection();
range.selectNodeContents(copyText);
selection.removeAllRanges();
selection.addRange(range);
document.execCommand("copy");
}
<p id="copy-my-contents">copy-me</p>
<button onclick="myFunction()">Copy text</button>
I was facing this in a Cypress test, this fixed it for me:
first focus the copy icon/button which is about to be clicked, then
use cy.realClick from cypress-real-events instead of cy.click
I just discovered that I don't need to write any code to debug this. When you pause on a breakpoint in Chrome DevTools, it adds a small yellow box to the page you're debugging which says, "Paused in debugger" and has play and step over buttons. I've never used it before, preferring the more extensive controls in DevTools.
I just discovered that if you use the step over button in this yellow box, the DOM stays focused and no error is thrown.
Cypress - Use the right window/navigator and focus on the document.
I tried to programatically populate the clipboard in my Cypress test so I could paste the contents into a text-area input element.
When I was struggling with this issue I found out that there were two things causing the problem.
The first issue was that I used the wrong window. Inside the test function scope window returns the Window object in test scope, while cy.window() returns the Window object for the Application Under Test (AUT).
Second issue was that document was not in focus, which can be easily resolved by calling cy.window().focus();.
Since both result in the same DOMException:
NotAllowedError: Document is not focused.
It was not always clear that there were 2 issues going on. So when debugging this:
Make sure you use the right window/navigator of the page you are testing.
Make sure that the document is focused on.
See following Cypress tests demonstrating the above:
describe('Clipboard tests', () => {
before(() => {
cy.visit('/');
// Focus on the document
cy.window().focus();
});
it('window object in test scope is not the window of the AUT', () => {
cy.window().then((win) => {
expect(window === win).to.equal(false);
expect(window.navigator === win.navigator).to.equal(false);
})
});
it('See here the different results from the different Window objects', () => {
expect(window.navigator.clipboard.writeText('test').catch(
(exception) => {
expect(exception.name).to.equal('NotAllowedError')
expect(exception.message).to.equal('Document is not focused.')
},
));
cy.window().then((win) => {
return win.navigator.clipboard.writeText('test').then(() => {
return win.navigator.clipboard.readText().then(
result => expect(result).to.equal('test'),
);
});
});
})
});
We saw a handful of these in our production app, and after some digging it turned out that the root cause in our case was the user was copying a lot of data, and switched tabs during the process (thus causing the relevant DOM to lose focus, and triggering the error). We were only able to replicate this by using CPU throttling in chrome, and even then it doesn't happen every time!
There was nothing to be "fixed" in this case - instead we're just catching the error and notifying the user via a toast that the copy failed and that they should try again. Posting in case it's of use to anyone else seeing this!
If you're using Selenium and getting this, you need to bring the test window to the front:
webDriver.switchTo().window(webDriver.getWindowHandle());
I have to do this repeatedly so I have it in a loop with a Thread.sleep() until the the paste works.
Full details: https://stackoverflow.com/a/65248258/145976

Can not read property 'mergeAttributes' of null error when I try to insert new records using extjs grid editor

First of all, I am using 6.2 version of extjs framework.
I'm facing a problem to save new records using the ext.js grid with the "Ext.grid.plugin.RowEditing" plugin.
When I try to save a record, since the line does not have a combobox in the editor, it works fine.
However, when I add a combobox in the the line editor, the following error occurs:
Can not read property 'mergeAttributes' of null
By checking the extjs framework code, I noticed that the error occurs when the editor is exiting and the line is being populated with the modified content.
This occurs in following section of the Table.js file:
cellSelector = me.getCellSelector(column);
oldCell = oldRow.selectNode(cellSelector);
newCell = newRow.selectNode(cellSelector);
// Copy new cell attributes across. Use IE-specific method if possible.
if (oldCell.mergeAttributes) {
oldCell.mergeAttributes(newCell, true);
} else {
newAttrs = newCell.attributes;
attLen = newAttrs.length;
for (attrIndex = 0; attrIndex < attLen; attrIndex++) {
attName = newAttrs[attrIndex].name;
if (attName !== 'id') {
oldCell.setAttribute(attName, newAttrs[attrIndex].value);
}
}
}
Basically, the variable "oldCell" is not being populated by "oldRow.selectNode (cellSelector)".
In the first column I put an invisible column containing the Id of the record. This cell is being filled, however, any other cell, having the combobox or not, is returning "oldCell" as null.
Just to enforce, when I remove all comboboxes from editor it works.
This is also true only with new records.
Luckily the bug is easy to fix.
I have a "render" in the column where the combobox is placed.
An unhandled error was occurring in this render. So, I corrected it and the bug disappeared.
#André Cristino: I believe it's renderer in the column rather than render.
Basically, both are different.
Render term is used while creating a component.
A renderer is a kind of template used to change the data in a grid cell.
Though I don't have any error in the renderer, I am still facing the mergeAttributes issue.

Categories

Resources