I have a web application that I need to open a new browser window from and load an angular application into it. I Dont see any problems with that by dong the following:
var windowObjectReference = window.open(strUrl, strWindowName, [strWindowFeatures]);
After getting a reference to a new window I can call its function and send data to it. Sending data is the critical function. I am a bit fuzzy however how exactly Angular app will be getting this data. Will I be able to call a $rootScope function using windowObjectReference?
Any ideas?
Thanks
I would use whatever backend api you are using for your web app to pass the data instead. That way, your angular app should be set up to use the http library that's built in to request that data from there on load. That way you have a lot more angular constructs that can help you along the way. An example of the code in your angular app would look like this:
var onGetResponse = function(data) {
$scope.appData = data;
}
var onGetError = function(reason) {
$scope.responseError = "Could not get the app data.";
alert($scope.responseError);
}
$http.get('/appData').success(onGetResponse).error(onGetError);
The bottom statement actually makes the call to your backend api and when it gets a successful response, it will call the top. Then your angular app can access the information with {{appData}}.
There are many method by which a window can talk with a window, from the same domain, it opened:
Shared Workers and Service Workers can communicate with all windows from the same domain.
With window.postMessage you can send a receive messages from
opened windows, and iFrames.
Local storage can be used for communications between windows
from the same domain, using the storage event that is fired when a key content is changed.
The old method is using window.opener. The opened window can
refer to it's parent and request the information it needs. The
parent just have to store an object on the window with the needed
methods.
You can also send information via the url using the hash # part.
You can encapsulate most of this methods in a service on both the opened an window and the opener. btw - don't forget $apply with any of this methods.
Related
I have a webview with a url (for example a payment processing page). When the url is loaded, certain api calls are done and i want to know how to get data from the internal api calls of that particular url.
It is not something like communication between webpage and react native code. ( window.ReactNativeWebView.postMessage or onMessage )
I need internal api call response data from the webpage.
Solution 1:
you can inject js into webview to get api detail
var open = XMLHttpRequest.prototype.open;
XMLHttpRequest.prototype.open = function() {
this.addEventListener("load", function() {
var message = {"status" : this.status, "responseURL" : this.responseURL}
webkit.messageHandlers.handler.postMessage(message);
});
open.apply(this, arguments);
};
Solution 2:
right now, there is no way to intercept webview internal API calls.
you can add support for this in webview
Android
In android you have to use
WebViewClient.shouldInterceptRequest()
you can add bridging method REF
I think you can inspect/log the network requests by setting up a (WiFi) proxy:
Step-by-step instructions for Fiddler
Another how-to for Proxyman
Related StackOverflow question
I use service worker with sw-toolbox library. My PWA caches everything except API queries (images, css, js, html). But what if some files will be changed someday. Or what if service-worker.js will be changed.
How application should know about changes in files?
My service-worker.js:
'use strict';
importScripts('./build/sw-toolbox.js');
self.toolbox.options.cache = {
name: 'ionic-cache'
};
// pre-cache our key assets
self.toolbox.precache(
[
'./build/main.js',
'./build/main.css',
'./build/polyfills.js',
'index.html',
'manifest.json'
]
);
// dynamically cache any other local assets
self.toolbox.router.any('/*', self.toolbox.cacheFirst);
// for any other requests go to the network, cache,
// and then only use that cached resource if your user goes offline
self.toolbox.router.default = self.toolbox.networkFirst;
I don't know what is the usual method to update cache in PWA. Maybe PWA should send AJAX request in background and check UI version?
AFAIK the sw_toolbox does not have a strategy for cache with network update. This is really what you want I think.
You want to modify the cache-network race strategy - > https://jakearchibald.com/2014/offline-cookbook/#cache-network-race
Instead of just letting the loser fade away, once the network responds you will want to update the client. This is a little more advanced that I have time or time to explain here.
I would post a message to the client to let it know there is an update. You may want to alert the user to the update or just force the update.
I don't consider this to be an edge case, but a very common, but advanced scenario. I hope to publish a more detailed solution soon.
There is nice solution written here where he states (in a nutshell) to either not use cache-first strategy or update a UX pattern of displaying a "Reload for the latest updates."
I dealt with services workers without using any library and the solution I ended up coming up with involved a bit of server side code and some client side. The strategy in a nutshell
Firstly the variables you will need and where:
On the server side have a "service worker version" variable (Put this in a database or config file if you are using something like php that will update immediately on the server side without requiring a redeploy. Let's call it serverSWVersion
On one of the javascript files you cache (I have a javascript file dedicated to this) have a global variable that will also be the "service worker version". Let's call it clientSWVersion
Now how to use the two:
Whenever a person lands on the page make an ajax call to your server to get the serverSWVersion value. Compare this with the clientSWVersion value.
If the values are different that means your web app version is not
the latest.
If this is the case then unregister the service worker and refresh the page so that the service worker will be re registered and the new files will be cached.
What to actually do when new file is available
Update the serviceSWVersion and clientSWVersion variables and upload to server where applicable.
When a person visits again then the service worker should be re registered and all the cached files will be retrieved.
I have provided a php server side based code that I used while I was implementing this strategy. It should show you the principles. Just drop the "Exercise" folder in a htdocs of a php server and it should work without you having to do anything else. I hope you find it useful... And remember you could just use a database instead of a config file to store the server side service worker variable if you are using some other server instead of php:
Zip file with code:
ServiceWorkerExercise.zip
When a service worker is altered, the browser will install it, but the new version will not be activated until the browser tab or PWA app window is closed and re-opened.
So, if you change the cache name, the new cache will not serve any files until the browser re-opens, nor will the old cache be deleted until that time.
You can detect service worker changes in your page javascript using registration.onupdatefound and ask the user to close and re-open the window - something like this:
// register the service worker
navigator.serviceWorker.register('sw.js').then(function(registration)
{
registration.onupdatefound = function()
{
console.log("ServiceWorker update found.");
alert("A new version is available - please close this browser tab or app window and re-open to update ... ");
}
}, function(err)
{
console.log('ServiceWorker registration failed: ', err);
});
change self.toolbox.router.any('/', self.toolbox.cacheFirst); to self.toolbox.router.any('/', self.toolbox.fastest);
Today we can find many examples of sending message from a service worker to a client, but always following the reception of a message event in the service worker.
I would like to know if we can send messages independently of this event? And if yes, how? I tried few things, without success...
In my case, it's for redirect a client to a new page when my service worker receives a push event.
client.js :
const swListener = new BroadcastChannel('swListener');
swListener.onmessage = function(e) {
console.log('swListener Received', e.data);
};
service-worker.js
const swListener = new BroadcastChannel('swListener');
swListener.postMessage('This is From SW');
The interface for Client.postMessage() is described at https://github.com/slightlyoff/ServiceWorker/issues/609. Unfortunately, it is not fully implemented in Google Chrome as of version 45, though I'd expect it to make it into a version at a later date.
When the functionality's available, you could use self.clients.matchAll() to obtain a list of any open pages that are being controlled by the service worker, and call the postMessage() method on the specific client that you care about. You need to keep in mind that it's entirely possible that there won't be any tabs open with a page controlled by your service worker, in which case you'd want to do something like open a new client page with your target URL.
But, there's a method that's probably more appropriate for your use case (though also not currently support in Chrome 45): WindowClient.navigate(), which will instruct an open tab controlled by your service worker to navigate to a different URL on the same origin.
hi
I want to build a control panel for a web art application that needs to run in fullscreen, so all this panel, that controls stuff like colors and speed values, have to be located at a different window.
My idea is to have a database storing all these values and when I make a change in the control panel window the corresponding variable in the application window gets updated too. So, it's basically a real-time update that I could do with AJAX setting a interval to keep checking for changes BUT my problem is: I can't wait 30 seconds or so for the update to happen and I guess a every-1-second AJAX request would be impossible.
Final question: is there a way to create a sort of a listener to changes in the database and fire the update event in the main application only immediately after I change some value in the control panel? Does Angular or another framework have this capability?
(Sorry for the long explanation, but I hope my question is clearer by offering the context [: )
A web socket powered application would have this benefit. This carries a bit more complexity on the back end, but has the benefit of making your application as close to real-time as can be reasonably expected.
The Mozilla Development Network has some good documentation on websockets.
On the front end, the WebSocket object should work for you on most modern browsers.
I'm not sure what your back end is written in, but Socket.IO for Node.js and Tornado for Python will make your applications web-socket capable
If one window is opening the other windows via JavaScript, you can keep the reference to the opened window and use otherWindow.postMessage to pass messages across
"Parent" window looks like
// set up to receive messages
window.addEventListener('message', function (e) {
if (e.origin !== 'http://my.url')
return; // ignore unknown source
console.log(e.message);
});
// set up to send messages
var otherWindow = window.open('/foo', '_blank');
otherWindow.postMessage('hello world', 'http://my.url');
"Child" windows look similar
// same setup to recieve
// ...
// set up to send
var otherWindow = window.opener;
// ... same as before
For the realtime I would recommend using a library like socket.io or using a database like firebase.
For the fullscreen I would recommend using a library like angular-screenfull
i use https://pushjs.io/, had exactly the same problem and this is a really simple solution for your problem. It is capable of sending and listening to events without any database interference.
I am displaying a list of tweets in my BlackBerry WebWorks application that the user should be able to share via Twitter.
I want to use Twitter's native BlackBerry client, and am calling it via an invoke object. I can launch the Twitter application fine, but does anyone know what parameters are needed to skip directly to sharing content from my application?
I am using the following to successfully invoke the Twitter client:
try{
var params = new Array();
var args = new blackberry.invoke.JavaArguments('net_rim_bb_twitter', params);
blackberry.invoke.invoke(blackberry.invoke.APP_JAVA, args);
}catch(e){
alert("Could Not Invoke App: "+e.name+" : "+e.message);
}
Thanks everybody!
From WebWorks in order to invoke other application you need to use JavaArguments (as you do), but don't add parameters as it won't work use only module name:
new blackberry.invoke.JavaArguments('net_rim_bb_twitter');
This way the code will try to invoke 'net_tim_bb_twitter'.
Looking in BB's github and how JavaArguments are implemented - it takes the first parameter and creates a URL query from the Array arguments. If you add parameters like ["par=val","par2=val2"] then the code will try to start 'net_rim_bb_twitter?par=val&par2=val2" which won't start anything if not specified by the OS or the app. The idea with parameter is to invoke apps that are listening for URLs.
Using without parameters will just start the app but it won't prefill the desired fields within the app, so you need to create a screen in your app to post to twitter or just use the web intents https://dev.twitter.com/docs/intents and BrowserArguments to start nice little twitter web app prefilled with data from your web app.