How to replace input field selected text with Chrome extension context menu? - javascript

I am looking for a simple solution to change input field value with context menu trigger.
Let's say changing to bar will be enough, I'll try to add some processing later.
This is how it should work
manifest.json:
{
"manifest_version": 2,
"background" : { "scripts": ["background.js"] },
"permissions": [ "contextMenus", "http://*/*", "https://*/*" ],
"name": "test plugin",
"version": "0.1"
}
background.js:
function getClickHandler() {
//magic here
};
chrome.contextMenus.create({
"title" : "change to 'bar'",
"type" : "normal",
"contexts" : ["editable"],
"onclick" : getClickHandler()
});

The basic idea would be
Listen to contextmenu event in content scripts and record e.target (This is needed because we don't know the actual DOM node for chrome context menu api, see Issue 39507) We could directly use document.activeElement, since input elements get focused upon click
In background page, send a message to content scripts when getClickHandler is triggered
In content scripts, replace target.value with "bar"
Sample code:
manifest.json
{
"manifest_version": 2,
"background" : { "scripts": ["background.js"] },
"permissions": [ "contextMenus", "http://*/*", "https://*/*" ],
"name": "test plugin",
"version": "0.1",
"content_scripts": [
{
"matches": [
"*://*/*"
],
"js": [
"content.js"
],
"all_frames": true
}
]
}
content.js
chrome.runtime.onMessage.addListener(function (request) {
replaceSelectedText(document.activeElement, request.text);
});
function replaceSelectedText(elem, text) {
var start = elem.selectionStart;
var end = elem.selectionEnd;
elem.value = elem.value.slice(0, start) + text + elem.value.substr(end);
elem.selectionStart = start + text.length;
elem.selectionEnd = elem.selectionStart;
}
background.js
function getClickHandler(info, tab) {
chrome.tabs.sendMessage(tab.id, {text: "bar"});
};
chrome.contextMenus.create({
"title" : "change to 'bar'",
"type" : "normal",
"contexts" : ["editable"],
"onclick" : getClickHandler
});
Updated
As #Xan has mentioned in the comments, if you just want to update <input> field, then using input.value = xxx is ok; however if you would like to manipulate arbitrary editable element, see Is there a flexible way to modify the contents of an editable element? for more ideas.

Related

Catching YouTube video going fullscreen in extension

As starter in Chrome extensions i'm trying to triger my function when somebody puts his youtube video into fullscreen. I've came up with code below, but it still don't triggers the alert message.
Manifest.json
{
"name": "Ext",
"version": "0.1",
"manifest_version": 2,
"description": "Catching fullscreen.",
"icons": {"16": "icon_16.png"
},
"background": {
"scripts": ["background.js"]
},
"browser_action":{
"default_title": "Ext",
"default_icon": "icon_16.png"
},
"permissions": [
"background",
"tabs",
"http://*/*",
"https://*/*"
]
}
background.js
document.addEventListener('DOMContentLoaded', function() {
var link = document.getElementByClassName('ytp-fullscreen-button');
link.addEventListener('click', function() {
alert("Fullscreen");
});
});
Beside answering to question how to add custom listener to video going fullscreen event i would be very thankful for some tips how to improve myself in this type of apps.
Read the extensions architecture overview: background page of an extension is not related to the web page so the background page script doesn't have direct access to webpage document or events.
Use a content script and fullscreenchange event (currently, it's under a vendor prefix):
addVendorEventListener(document, 'fullscreenchange', onFullscreenChange);
function onFullscreenChange(event) {
console.log(event);
}
function addVendorEventListener(element, eventName, callback) {
var vendorName = 'on' + eventName in element ? eventName
: 'onwebkit' + eventName in element ? 'webkit' + eventName
: 'onmoz' + eventName in element ? 'moz' + eventName
: null;
if (vendorName)
element.addEventListener(vendorName, callback);
}
manifest.json:
"content_scripts": [{
"matches": ["https://www.youtube.com/*"],
"js": ["content.js"]
}],

Chrome extension:Monitor change in element

I am building a Chrome extension with which I'd like to insert some text between the "link" and the "description" on each Google search result and also write the title of each link to the console. See the screenshot and the code below
screenshot
Manifest.json
{
"name": "INJECTA",
"version": "0.0.1",
"manifest_version": 2,
"description": "Abcdefgh",
"content_scripts": [
{
"matches": [
"<all_urls>"
],
"js": ["jquery-3.1.1.min.js","content.js"],
"run_at": "document_end"
}
]
}
content.js
$(document).ready(function() {
$("div.srg").find("h3 > a").each(function (index) {
console.log("Title: " + this.text);
$(this).append("<br><span style='color: orange'>My new line text</span>");
});
});
It works but when I make another search query on the same google page, then it doesn’t work. How can I fix it?

Running an extension in background on page load/refresh

I'm new to writing extensions (and javascript). I'd like an extension to run on a timer whenever a certain URL is opened/refreshed. Code is below. This is all I have so far from what I've found online. I'm not sure if this will run for just one tab at a time.
manifest.json
{
"manifest_version": 2,
"name": "Test Plugin",
"description": "This extension is a test.",
"version": "1.0",
"content_scripts": [
{
"matches": ["https://www.google.com/*"],
"js": ["main.js"]
}
],
"permissions": [
"activeTab"
]
}
main.js
chrome.tabs.onUpdated.addListener( function (tabId, changeInfo, tab) {
if (changeInfo.status == 'complete' && tab.active) {
setInterval(mainF, 5000)
}
})
function mainF() {
var getTitle = document.getElementById('title');
var titleValue = getTitle.Value();
var fso = new ActiveXObject("Scripting.FileSystemObject");
var fh = fso.OpenTextFile("test.txt", 8, false, 0);
fh.WriteLine(titleValue);
fh.Close()
}
Move your logic to the Event Page.
Content Script doesn't have access to chrome.tabs API.
And according to best practices when using event pages,
Use event filters to restrict your event notifications to the cases you care about. For example, if you listen to the tabs.onUpdated event, try using the webNavigation.onCompleted event with filters instead (the tabs API does not support filters). That way, your event page will only be loaded for events that interest you.
Code snippets would look like
manifest.json
{
"manifest_version": 2,
"name": "Test Plugin",
"description": "This extension is a test.",
"version": "1.0",
"background": {
"scripts": ["main.js"],
"persistent": false
},
"permissions": [
"webNavigation"
]
}
main.js
chrome.webNavigation.onCompleted.addListener(function(details){
console.log("Certain url with hostSuffix google.com has been loaded");
}, {url: [{hostSuffix: 'google.com'}]});

Chrome extension - onclick icon event

As you can see, I have a problem with onclick event in chrome extension and I need your help.
$(function jony() {
jQuery.each( jQuery('img'), function() {
jQuery(this).attr('src', 'urlimage');
});
});
chrome.browserAction.onClicked.addListener(function(tab) {
jony();
});
Manifest:
{
"manifest_version": 2,
"name": "Jonyzátor",
"description": "Change images on page to JoNy!",
"version": "1.0",
"browser_action": {
"default_icon": "icon.png",
"default_title": "Klikni na mě!"
},
"permissions": [
"activeTab",
"https://ajax.googleapis.com/"
],
"content_scripts": [ {
"js": [ "jquery.js", "jonyza.js"],
"matches": [ "http://*/*", "https://*/*"]
}]
}
The scope in which jony is defined is limited to $(); outside it's simply undefined.
function jony() {
jQuery.each( jQuery('img'), function() {
jQuery(this).attr('src', 'urlimage');
}
$(jony); // Will execute on page load
// and you can still use it here
I'm not sure it was the logic you intended - do you want it to run both at page load AND when you click?
You can't use browserAction API in content scripts. The proper place for it would be a background (or event) script, and then you can message your content script to do something.

Very simple Chrome Extension to display alert

I am trying to create a quick Chrome extension (complete beginner) and just want to display an alert whenever the icon is clicked, so I tried the following:
manifest.json
{
"name": "Something",
"version": "1.0",
"manifest_version": 2,
"description": "Woohoo",
"browser_action": {
"default_icon": "icon.png"
},
"content_scripts" : [{
"matches": ["<all_urls>"],
"js" : ["bgscript.js"]
}]
}
bgscript.js
chrome.browserAction.onClicked.addListener(function(tab) {
alert('icon clicked')
});
However when I click on my icon, nothing happens! Looking at the above - can anyone spot why this wouldn't work?
In order to be notified for browser-action's onClicked event, you need a background-page (or better yet event-page), not a content-script.
Change your manifest like this:
// Replace that:
"content_scripts" : [{...}]
// with this:
"background": {
"persistent": false,
"scripts": ["bgscript.js"]
}
If you want the browser-action to invoke something on a content-script, you need to communicate throught the background-page using Message Passing (e.g. Simple one-time requests).
E.g.:
manifest.json
{
"name": "Something",
"version": "1.0",
"manifest_version": 2,
"description": "Woohoo",
"browser_action": {
"default_icon": "icon.png"
},
"background": {
"persistent": false,
"scripts": ["background.js"]
},
"content_scripts" : [{
"matches": ["<all_urls>"],
"js" : ["content.js"]
}]
}
background.js
chrome.browserAction.onClicked.addListener(function (tab) {
/* Send a message to the active tab's content script */
chrome.tabs.sendMessage(tab.id, { action: 'saySomething' });
});
content.js
chrome.runtime.onMessage.addListener(function (msg) {
/* We received a message, let's do as instructed */
if (msg.action === 'saySomething') {
alert('something');
}
});

Categories