Gergely Borgulya Gergely Borgulya - 4 months ago 17
HTML Question

addeventlistener not catching event in chrome extension for gmail

I'm working on a simple Chrome extension that puts a contenteditable div in the GMail composer, into the email body that listens to keyboard events and does some helpful type assistance. The basic idea is that after you send the email there is only the div remaining in the email without the type assistance. However I'm not able to make the inserted div catch the keyboard events when one types into it. It works if inserted to other sites than GMail.

The div element is inserted to the mail body like this:

// create div element:
var element = document.createElement ("div");
element.setAttribute ('contenteditable', true);
element.innerText = "sample text";
element.addEventListener ("input", function (event) {
console.log ('Input event caught'); // this never fires
}, true);
// insert it at the cursor:
var sel = window.getSelection();
var range = sel.getRangeAt (0);
range.deleteContents ();
range.insertNode (element);


This code part is in a file called gmail-inline.js . I also put "all_frames": true in the manifest:

{
"name": "extension",
"manifest_version": 2,
"description": "description",
"version": "0.1",
"background": { "page": "background.html" },
"browser_action": {
"default_icon": {
"19": "images/icon19.png",
"38": "images/icon38.png"
},
"default_title": "test"
},
"content_scripts": [
{
"matches": ["*://*/*"],
"all_frames": true,
"js": [
"gmail-inline.js"
],
}
],
"permissions": [
"tabs"
]
}


The div nicely appears in the email body when the script is run. According to the Event Listeners in Chrome's developer tools, the event is attached to the element, it simply doesn't fire somehow. I thought it could be some other event handlers preventing the event to get to this script, so I set event listening to be done in the capturing phase, but still nothing.

I did some research and found similar questions and answers that don't answer this case. And it seems to be unusual to attach an event handler to the element directly and not to the document. It seemed to be a good idea, as otherwise one has to deal with GMail's deep iframe structure, and assign the listeners dynamically to the spawning iframes. So what do I do wrong?

Answer

It's happen because contenteditable element inside another contenteditable element not consider like it get a focus, just is parent focused . and focus mean listen for keyboard event. so for fix that you should make your div as contenteditable=false and create another div inside with contenteditable=true.
so:

var element = document.createElement ("div");
element.setAttribute ('contenteditable', false);
var helper = document.createElement ("div");
helper.setAttribute ('contenteditable', true);
helper.style.width = '100%'; 
...
element.appendChild(helper);
helper.innerText = "sample text";
helper.addEventListener ("input", function (event) {
    console.log ('Input event caught'); // this now fires
}, true);