how can solve the ReferenceError: window is not defined in service-worker at pwa? - manifest

ReferenceError: window is not defined
progressive web apps using at "add to home screen" not working.
this is my services-workder.js
window.addEventListener('beforeinstallprompt', function(e) {
e.userChoice.then(function(choiceResult){
console.log(choiceResult.outcome);
if(choiceResult.outcome == 'dismissed'){
console.log('User cancelled home screen install');
}else{
console.log('User added to home screen');
}
});});

That code is meant to run in the context of your web app's window, not inside of your service worker's code.
So, move it to something like a <script> tag inside of your HTML.

Related

How to determine why an alert dialog was displayed by Chrome?

I am trying to fix a bug in a Chrome extension. When the extension is installed an alert dialog containing the message "undefined" will be displayed seemingly at random. This does not happen when the extension is not installed.
There is not one call to alert, confirm, or prompt in the extension source code. How do I find out why the alert dialog is being displayed?
I have attempted adding the following code to one of the background scripts and to one of the content scripts.
var originalWindowAlert = window.alert;
window.alert = function() {
console.trace();
return originalWindowAlert.apply(window, arguments);
}
I have confirmed that this technique works when used in a webpage, but it is not working for the extension.
I have also built Chromium from source code and I am able to reproduce it but so far I have not been able to figure out how to determine the origin of the alert dialog. I have set a breakpoint in the RenderFrameHostImpl::RunModalAlertDialog function but I see no way to determine what caused the breakpoint to be hit.
I am getting desperate.
I asked this question on the Chromium Extensions Google Group. I got the following very useful response from Scott Fortmann-Roe.
If you do the following in a content script:
var originalWindowAlert = window.alert;
window.alert = function() {
console.trace();
return originalWindowAlert.apply(window, arguments);
}
I don't believe it will actually intercept alerts triggered by the page as you are overriding the content script's window.alert method which is different from the page's method (content script JS is isolated from page JS).
To modify the page's alert method you'll probably need to inject a script tag into the page. E.g. something along these lines in the content script:
let script = document.createElement('script');
script.textContent = `
var originalWindowAlert = window.alert;
window.alert = function() {
console.trace()
return originalWindowAlert.apply(window, arguments);
} `;
document.body.appendChild(script);

Framework7: Dynamically load Component page from Tab

I just found Framework7 and it looks promising as a base for mobile apps.
From navigation tabs I can load a Component Page which has dynamic data. But this data is only set when the application is loaded.
Wanted:
Every time user clicks on tab, load data and render page.
Question:
How can I make a component page load every time?
I have made an example from framework7-template-tabs. Check console showing when pageInit is called.
Live:
http://f7-navigate-component-question.surge.sh/
Code:
https://github.com/gotling/framework7-tab-component-page-question
If you want some action to happen every time a particular tab is clicked/loaded, you can use the show event of the tab, documented here.
For example, to alert something every time tab2 is loaded, you could do this
$$("#tab2" ).on( "show", function( event, ui ) {
myApp.alert("Tab loaded!");
} );
I got the answer in the Framework 7 forum.
Listen to page show events:
$('#view-catalog').on('tab:show', ...
Refresh the page:
$('#view-catalog').on('tab:show', function () {
catalogView.router.navigate(catalogView.router.currentRoute.url, {
reloadCurrent: true,
ignoreCache: true
});
});
If using Framework7 2.0.6 or newer that could have been simplified with:
$('#view-catalog').on('tab:show', function () {
viewCatalog.router.refreshPage();
});

printing support on chrome packaged apps

I can't seem to find any example of window.print() support in chrome packaged apps - can someone please post an example?
I'm using this
function clickHandler(e) {
window.print();
}
document.addEventListener('DOMContentLoaded', function () {
document.querySelector('button').addEventListener('click', clickHandler);
});
from "Hello World!" sample platform app, but I can't seem to get it working.
is there a special permission settings I should use?
Thanks!
Yes, window.print() works in Chrome Apps. You can find a sample in the official samples repo.
It is as simple as calling window.print() in any DOM window of your app:
// prints the content of the current window:
window.print();
// prints the content of another AppWindow:
anotherAppWindow.contentWindow.print()
AppWindow is the Chrome Apps object that encapsulates and extends the actual DOM window with app capabilities. This object can be obtained by either:
saving the parameter from the callback of chrome.app.window.create
calling chrome.app.window.current() on any code running in the context of the desired window

Chrome content_script: How to wait for jQuery

I'm writing a small Chrome extension that would have a content_script.
It would run on a single domain, I'm trying to improve a site a bit.
I want to use jQuery in my content script, but the site also uses jQuery, so I cannot simply add jQuery to my extension's content_script array.
My content_script will
"run_at": "document_end"
but jQuery is not yet loaded. It's not loaded on document_idle either.
So I have to wait for it.
How do I do that?
I've tried doing this:
(function() {
var i = setInterval(function () {
console.log(typeof jQuery + " " + i);
if (typeof jQuery != "undefined") {
console.log("jQuery loaded");
clearInterval(i);
} else {
console.log("jQuery not loaded");
}
}, 200);
})();
But for some reason typeof jQuery is always undefined within that loop.
If I manually clearInterval, and check typeof jQuery I properly get "function".
(chrome inspector console)
Any ideas?
EDIT:
content_scripts are special:
Content scripts are JavaScript files that run in the context of web
pages. By using the standard Document Object Model (DOM), they can
read details of the web pages the browser visits, or make changes to
them.
I cannot simply add jQuery to my extension's content_script array.
You can and should. Extension variable space is sandboxed, so content scripts cannot access variables from parent's page and vice versa.

How do I access the popup page DOM from bg page in Chrome extension?

In Google Chrome's extension developer section, it says
The HTML pages inside an extension
have complete access to each other's
DOMs, and they can invoke functions on
each other. ... The popup's contents
are a web page defined by an HTML file
(popup.html). The popup doesn't need
to duplicate code that's in the
background page (background.html)
because the popup can invoke functions
on the background page
I've loaded and tested jQuery, and can access DOM elements in background.html with jQuery, but I cannot figure out how to get access to DOM elements in popup.html from background.html.
can you discuss why you would want to do that? A background page is a page that lives forever for the life time of your extension. While the popup page only lives when you click on the popup.
In my opinion, it should be refactored the other way around, your popup should request something from the background page. You just do this in the popup to access the background page:
chrome.extension.getBackgroundPage()
But if you insist, you can use simple communication with extension pages with sendRequest() and onRequest. Perhaps you can use chrome.extension.getViews
I understand why you want to do this as I have run into the problem myself.
The easiest thing I could think of was using Google's method of a callback - the sendRequest and onRequest methods work as well, but I find them to be clunky and less straightforward.
Popup.js
chrome.extension.getBackgroundPage().doMethod(function(params)
{
// Work with modified params
// Use local variables
});
Background.html
function doMethod(callback)
{
if(callback)
{
// Create/modify params if needed
var params;
// Invoke the callback
callback(params);
}
}
As other answers mention, you can call background.js functions from popup.js like so:
var _background = chrome.extension.getBackgroundPage();
_background.backgroundJsFunction();
But to access popup.js or popup.html from background.js, you're supposed to use the messages architecture like so:
// in background.js
chrome.runtime.sendMessage( { property: value } );
// in popup.js
chrome.runtime.onMessage.addListener(handleBackgroundMessages);
function handleBackgroundMessages(message)
{
if (message.property === value)
// do stuff
}
However, it seems that you can synchronously access popup.js from background.js, just like you can synchronously access the other way around. chrome.extension.getViews can get you the popup window object, and you can use that to call functions, access variables, and access the DOM.
var _popup = chrome.extension.getViews( { type: 'popup' } )[0];
_popup.popupJsFunction();
_popup.document.getElementById('element');
_popup.document.title = 'poop'
Note that getViews() will return [] if the popup is not open, so you have to handle that.
I'm not sure why no one else mentioned this. Perhaps there's some pitfalls or bad practices to this that I've overlooked? But in my limited testing in my own extension, it seems to work.