1

Context:

  1. Writing a google chrome extension using JavaScript
  2. Using context menus library
  3. User should be able to right click into a textbox, select chrome extension, select "insert text", and then that text will get inserted into the selected text box.
  4. I am using pure javascript, please no jquery or AJAX.
  5. I am unable to edit the HTML page as it could be any generic web page with an HTML text box or editable field.

Code I have so far:

//the menu item
    var menuItem_insert = chrome.contextMenus.create({"title": "Insert Timestamp", "contexts":[context], "onclick:": insertTimestamp}); 

//the onclick
    function insertTimestamp(info, tab) {
      //if info.editable is true then
      alert(info.editable); //for debugging

    //CODE GOES HERE: need to insert timestamp here
    }

Question: How do I insert text into a selected textbox for which I may not have the "ID" for?

carrots
  • 785
  • 1
  • 8
  • 19

3 Answers3

1

Through document.activeElement you can refer to the current active element:

document.activeElement.value = 'My value';

should put the "My value" string inside the input text you have selected at the moment of the invocation.

Unfortunately in your case you want that to happen after you click a button, so your active element will become your button at the moment of the click. So you can find as workaround to define the element onblur of your text input, so that clicking to the button you will refer to that input text. So this is the HTML

<div>
  <input type="text" onblur="trackElement(this)" />
  <button onclick="test()">
  Test
  </button>
</div>

And this is the JS:

var myTxt = null;

function test() {
    if (myTxt != null) {
    myTxt.value = 'my value';
  }
}

function trackElement(el) {
    console.log(el);
    myTxt = el;
}

https://jsfiddle.net/2459g8z5/4/

quirimmo
  • 9,800
  • 3
  • 30
  • 45
  • Hey @quirimmo Thanks for the explanation, this makes sense, the only issue I see with this is that you are assuming I am able to modify the html code for the page on which I want to perform this action on... I unfortunately can't modify that page to add onclick attributes or anything really. – carrots May 14 '17 at 16:44
  • Sorry I thought you were able to change the HTML. Can you please paste your HTML code you are getting? I will write you a selector for retrieving the element you want – quirimmo May 14 '17 at 16:46
  • I just checked... looks like I may have the ID for the text box element. I am testing the`document.getElementById("id_here").value= "my_timestamp` but it's not replacing the text... – carrots May 15 '17 at 03:35
  • This code is correct so it should work. Can you please paste me all the example? – quirimmo May 15 '17 at 08:26
1

according this reply
You can inject content script with mousedown event listener and store element that was clicked:

manifest.json

..
"permissions": ["contextMenus"],
"background": {
  "scripts": ["./bg.js"]
},
"content_scripts": [{
  "js": ["./content.js"],
  "matches": ["<all_urls>", "http://*/*" , "https://*/*", "file:///"],
  "run_at": "document_end"
}],
"manifest_version": 2
..

background.js

function mycallback(info, tab) {
  if (info.editable) {
    chrome.tabs.sendMessage(tab.id, {
      "text": "TEXT GOES HERE"
    });
  }
}
chrome.contextMenus.create({
  title: "Insert Timestamp",
  contexts: ["editable"],
  onclick: mycallback
});

content.js

var clickedEl = null;
document.addEventListener("mousedown", function (event) {
  //right click
  if (event.button == 2) {
    clickedEl = event.target;
  }
}, true);
chrome.runtime.onMessage.addListener(function (request) {
  clickedEl.value = request.text;
});
Community
  • 1
  • 1
alessandrio
  • 4,282
  • 2
  • 29
  • 40
1

avril alejandro answer is good, this is a different approach to solve the problem

Logic is, when user clicks your context menu item, menu will disappear and focus is back right where you need it, on origin element from which right click started (also from any point in that element if user clicked somewhere in the middle of existing text)
All you need to do is simulate copy/paste action.

so, in background script:

  • in your onClicked listener create textarea
  • fill it with value you want to insert (date string in this example)
  • focus it and select it
  • use document.execCommand('Copy') to put taxarea value into clipboard
  • if click started from iframe, make sure you target only that frame, to avoid multiple script insertion and errors
  • inject script into sender tab (you have all the info from onClicked listener)
  • injected script will do only one thing, pasting what was is in the clipboard document.execCommand('paste')

background.js

chrome.contextMenus.onClicked.addListener(function(info, tab) {
    var tArea = document.createElement('textarea'), _frame = null, date = new Date();
    document.body.appendChild(tArea);
    tArea.value = date.toLocaleString();
    tArea.focus();
    tArea.select();
    document.execCommand('copy');

    if(info.frameId) _frame = info.frameId;

    chrome.tabs.executeScript(tab.id, {frameId: _frame, matchAboutBlank: true, code: 
        "document.execCommand('paste');"
    }, function() {
        if (chrome.runtime.lastError) console.log(chrome.runtime.lastError);
        document.body.removeChild(tArea);
    });     
});

in your manifest add "clipboardWrite", "clipboardRead", "activeTab" permissions

I'm using this logic in my Opera notes extension.
I never saw anyone using this trick, and it's very simple, plus it will remove all the hassle with targeting the right element, selections, ranges, rich text editors ...etc

Community
  • 1
  • 1
Wolf War
  • 1,503
  • 1
  • 15
  • 28