click event at document level in chrome extensions - google-chrome-extension

I have a page where i need to auto fill a form.But that page contains jquery slider, jquery dropdown. The submit button contains validation of the form.
But i can't access the page's jquery object.
Also i tried to execute jquery and jquery ui through manifest file.but it wont change real jquery object of a page.
(Chrome exetention javascript is executing in seperate context)
Is it possible to trigger click at perticular position (eg: X : 20px, Y : 50px) of document in chrome extention.

Instead of triggering a click event, I believe it better suits your purpose to access the jQuery object directly.
As you correctly mentioned, content scripts are executed in a sandboxed environment.
Still, you can access the web-pages JS context through the shared DOM. All you need to do is add a script node including the necessary code, e.g.:
var script = document.createElement("script");
script.type = "text/javascript";
script.textContent =
"// Accessing the web-page's JS contex\n" +
"$(\"#myElem\").doSomething();";
document.body.appendChild(script);
script.parentNode.removeChild(script);
There is, also, this very detailed answer, describing the various JS injection methods (including bonus tips and tricks).

Related

Trigger a dialog box in background script

I have a chrome extension, where I periodically throw out an alert based on something.
The thing is that the default alert in Javascript is very ugly and I am trying to replace it with something more beautiful.
The problem is that currently the alert is triggered from the background script. Google doesn't allow us to include any external libraries in the background html.
Given this problem, how do I go about replacing the default alert with a more modern UI alert?
I was looking to replace the default alert with something like the SweetAlert.
My background.js currently looks like this:
// on some alarm trigger
function showpopup() {
console.log(" in show popuup");
console.log(Date());
alert("ugly alert");
}
I also explored the option of injecting another js file from my background file.
function showpopup() {
console.log(" in show popuup");
console.log(Date());
var s = document.createElement('script');
// added "script.js" to web_accessible_resources in manifest.json
s.src = chrome.extension.getURL('script.js');
s.onload = function() {
this.remove();
};
(document.head || document.documentElement).appendChild(s);
}
My script.js currently just calls an alert
alert("ugly alert now in script.js");
I am not able to figure out how to create my own dialog box in this javascript file script.js.
The problem is where your alert will be shown?
In an browser/OS dialog window? That's what alert() and friends do; as you see yourself, it's ugly and inflexible. In addition, it's technically challenging: it's an old mechanism that stops execution of JS code until closed, which can lead to API malfunctioning; Firefox WebExtensions specifically don't support calling this from the background page.
In the background page? By definition, it's invisible. You can add DOM nodes with an alert there, but you will not see it. Your problem isn't loading a library, your problem is where to display results.
(invisible, so no picture here!)
In the currently open tab? Hijacking an arbitrary page to show your own UI is hard, prone to break, would require draconian permissions with user warnings at install, won't always work. Wouldn't recommend.
In a fresh window? Possible (see chrome.windows API), but hardly "modern UI" at all (at least you can hide the URL bar).
In a browser action popup? Still not possible to trigger it to open in Chrome, so that's out.
The de-facto standard for informing the user about such things is the chrome.notifications API. It offers limited customization, but that's the "modern" approach considering that your extension has no UI surfaces already open at alert time.
You can insert your code into the tab content via
JS: chrome.tabs.executeScript()
CSS: chrome.tabs.insertCSS()
The second possibility would be to use a content script (content.js). But then you would have to use messaging to communicate between background.js and content.js.

Auto-collapse any item in PrimeFaces PanelMenu on page loading

I'm writing a Primefaces 5.1 portlet.
It consists in a unique page containing a panelMenu, and I need that it starts with any panel collapsed everytime a user change page (on page loading).
But, if I open a panel, then change page, it will start showing that panel still opened.
I wasn't able to find any option to achieve this goal (e.g. collapsed=true, ignoreCookie=true or something similar).
The only solution I found was the following Javascript code:
PrimeFaces.widgets.myPanelMenu.collapseRootSubmenu(PrimeFaces.widgets.myPanelMenu.headers);
The problem is that this code will collapse any opened panel (so on page loading user is able to see panel menu collapsing animation) but it seems it doesn't store this state in its cookie/localstorage... the result is that on any page loading user can see this animation.
I'm sure it doesn't save its state, because the only way to "solve" the problem is to manually re-open and re-collapse the panels... then, on following page change, these menus start closed (and there is no animation).
I also tried to use PrimeFaces.widgets.sideMenuPanel.saveState() after collapsing, but with no success.
Do you have any idea about?
Thank you...
I found a solution to the problem.
If you read my discussion with Kukeltje (comments on my question), you will find that latest Primefaces' versions will solve the problem.
Otherwise, if you want to avoid upgrade or modify sources, and you need a quick fix based on Javascript only please read the following part of the answer.
It directly works on the component's state using JavaScript.
First of all you need to have a variable reference to your component:
<p:panelMenu model="#{menuBackingBean.menuModel}" widgetVar="sidePanelMenu" />
Then you should add the following JS code on document ready:
var panelMenu = PrimeFaces.widgets.sidePanelMenu;
// 1. On page loading collapses possible opened panels
panelMenu.collapseRootSubmenu(panelMenu.headers);
// following line is commented because it never should be necessary is not necessary (unless unexpected situation I never verified)
//clearSidePanelMenuPreferences();
// 2. Call the "clear preferences" actions on click on two tpe of links: first level are the panel link (used to open/close the menu) and second level are the destination links
// We need to fork also on the first level links to be sure it works after user clicks there then exit from the page in another way
panelMenu.headers.children("a").click(function(){setTimeout(clearSidePanelMenuPreferences, 500)}); // setTimeout is necessary because this event should be fired after preferences are written
panelMenu.headers.siblings().find("a").click(function(){clearSidePanelMenuPreferences();});
The function called to clear preferences are the following:
function clearSidePanelMenuPreferences() {
var panelMenu = PrimeFaces.widgets.sidePanelMenu;
panelMenu.expandedNodes = []; // clear the opened panels lists
panelMenu.saveState(); // store this information
}
Hope it helps
Please check this block of code
PF('myPanelMenu').headers.each(
function(){
var header = jQuery(this);
PF('myPanelMenu').collapseRootSubmenu(header);
header.removeClass('ui-state-hover');
}
);
I prefer to do this in order to execute this method only once and keep the menu option selected.
$(document).ready(function() {
if(location.pathname == "/cotizador/" || location.pathname == "/cotizador/faces/login.xhtml"){
var panelMenu = PrimeFaces.widgets.sidePanelMenu;
// 1. On page loading collapses possible opened panels
panelMenu.collapseRootSubmenu(panelMenu.headers);
panelMenu.expandedNodes = []; // clear the opened panels lists
panelMenu.saveState();
}
});

Run a function from injected js

I have been going around in circles with this, so I would appreciate some help
This is what I want to achieve
User presses my extension ison
Popup appears with two buttons, 'run function a' and 'run function b'
When they press a button it runs the function in my own js file, that I have injected.
Function a for example, could be to count the number of elements of a certain type in the active tab
So, I can inject my js file on page load (this is in my contentscript.js)
var s = document.createElement('script');
s.src = chrome.extension.getURL('temp-file.js');
s.onload = function() {
this.parentNode.removeChild(this);
};
(document.head||document.documentElement).appendChild(s);
This works, and I can see the js being excuted
But what I can do is to have a function run that is in temp-file.js
For example in the popup I have
chrome.tabs.executeScript(null, {code:"shows();"});
I get this: Uncaught ReferenceError: shows is not defined
If I enter shows(); into the console, it works as expected
I presume that the issue is all about the context. I tried various things in the popup.js page to also inject the file but nothing seemed to work
Is anyone able to point me in the right direction please
Thanks
Grant
I presume that the issue is all about the context.
You're right about it.
The file "temp-file.js" has been injected into host page, so it is now part of host page context. Extension can mess with it - since it is in different context.
Run a function from injected js
Solution:
Not sure about what you are trying to achieve. pick what suits you:
Split injected file
Code/functions you want to execute on a page - use them as contentscript.
In this case split you "temp-file.js" - part extension has execute (becomes part of contentscript) and part host page has to execute(your code snippet).
use custom event
Use custom event - generate custom event in contenscript - listen for it injected script. custom event
Your question does not say what exactly you are trying to achieve.
This is what I understood. You want to execute a function on your contentscript.js from your popup.js.
If that is the case then you can call a method on contentscript from popup.js like mentioned here https://developer.chrome.com/extensions/messaging

Displaying Extension Library Dialog box when page loads?

Is there any way to display an extension pages dialog box when my page loads?
Add a <xp:scriptBlock /> with the following client-side code as its value:
XSP.addOnLoad(function(){XSP.openDialog("#{id:dlgMessage}");});
...just be sure to place the component outside any refresh targets, or it will launch the dialog again after every partial refresh event with a target that includes it.
Try adding a dojo.addOnLoad() (in a xp:scriptblock) that displays the dialog using CSJS: XSP.openDialog()
Bruce,
You could use jQuery to 'push' the button on page load.
Try putting this clientside js code in your onClientLoad event
$(document).ready(function(){
$('a.btn').trigger('click');
});
You will have to load jQuery to use this if you don't already have it loaded. You might also be able to do the same thing with dojo.
EDIT: You might have to modify the selector (the tag and class in the parens line 2) above if not using bootstrap. I would give it a unique class so as not to 'push' any other buttons at the same time.

Chrome extensions: is it possible to call a function in the options page from the background page?

How do I call a function in the options page from the background page?
For example, in the options page, you can call:
chrome.extension.getBackgroundPage().updateIcon("someDifferentIcon.png");
thereby communicating with the background page from the options page. How do you communicate with the options page from the background page?
One possible difficulty is that the options page is not always open (unlike the background), so that may explain why its not built-in (like above). My question is, is it possible to do?
A simple approach to implement your idea is using "chrome.extension.sendRequest" API. For example:
options.js:
chrome.extension.sendRequest({id:"updateIcon", filename:"foo.png"});
background.js:
chrome.extension.onRequest.addListener(funciton(request) {
if (request && (request.id == "updateIcon"))
updateIcon(chrome.extension.geURL(request.filename));
});
If the options page is already open, you can use chrome.extension.getViews({type:"tab"}) to get a hold of its window object and then call functions on it (you'll need to iterate over the returned views and pick the one with the URL that is the URL of your options page). If it's not open yet, you can use the tabs API to open a tab that points to it first, and then use chrome.extension.getViews.

Resources