I am wondering if there is a function for saving the last viewed window when a user quits the application, so when they go into the app again, it goes to the last viewed page, instead of restarting. I have looked at Ti.App.Properties but haven't really found what I was looking for. Can anyone point me in the right direction, or if this is even possible.
Thanks
Ti.App.Properties is the way to go.
If you are just looking to save which window the user was on, simply save the current window that the user is on every time the window changes.
If you want to save the current state, as your title suggests, you will also want to create a javascript object that holds all the data on the page, do JSON.stringify(object) and then save that string in a property as well.
There is an example of code you can use to manage the state of the last opened window :
// Windows types
var TYPE_HOME = 'HomeWindow',
TYPE_BLUE = 'BlueWindow';
// Properties' keys
var PROPERTY_LAST_OPENED_WIN = 'lastOpenedWindow';
// open the last opened window
var win = openLastWindow();
// Uncomment to open the blue window
// Then, comment and reopen the app => the blue window will be opened
//createAndOpenBlueWindow();
// Save the last window configuration
function setLastWindow(params) {
Ti.App.Properties.setString(PROPERTY_LAST_OPENED_WIN, JSON.stringify(params));
}
// Create and open the last window opened
// (the function you have to call when you re-open the app)
function openLastWindow() {
var params = JSON.parse(Ti.App.Properties.getString(PROPERTY_LAST_OPENED_WIN, '{}'));
switch (params.type) {
case TYPE_HOME: return createAndOpenHomeWindow();
case TYPE_BLUE: return createAndOpenBlueWindow();
default : return createAndOpenHomeWindow();
}
}
// Create a window with the given params AND
// save this window as last opened window
function createAndOpenWindow(params) {
var win = Ti.UI.createWindow(params);
setLastWindow(params);
win.open();
return win;
}
// Create windows of type "HomeWindow"
function createAndOpenHomeWindow() {
return createAndOpenWindow({type:TYPE_HOME, backgroundColor:'#FF0000'});
}
// Create windows of type "BlueWindow"
function createAndOpenBlueWindow() {
return createAndOpenWindow({type:TYPE_BLUE, backgroundColor:'#0000FF'});
}
This code creates and opens the last window opened thanks to the openLastWindow function.
The first time you open the app, the Home one will be opened (the red).
By uncommenting this line :
//createAndOpenBlueWIndow();
you will open the BlueWindow the next time you run the app.
Then, re-comment this line. The blue window will be opened (since it is the last opened).
Hope this helps !
Related
The question is as simple as that. In Cypress, how can I access a new window that opens up when running the test.
Steps to recreate :
Run the test. After some action, new window pops up (the url is dynamic in nature).
Fill in the fields in the new window, and click a few buttons.
After required actions are completed in the new Window, close the new window and move back to the main window.
Continue execution with the main window.
Point of interest: the focus should be
main window -> new window -> main window
I have read few things that relate to use of iframe and confirmation box, but here its none of those. Relates to accessing a whole new window. Something like Window Handlers in Selenium. Unfortunately could not find anything related to it.
Accessing new windows via Cypress is intentionally not supported.
However, there are many ways this functionality can be tested in Cypress now. You can split up your tests into separate pieces and still have confidence that your application is covered.
Write a test to check that when performing the action in your app, the window.open event is called by using cy.spy() to listen for a window.open event.
cy.visit('http://localhost:3000', {
onBeforeLoad(win) {
cy.stub(win, 'open')
}
})
// Do the action in your app like cy.get('.open-window-btn').click()
cy.window().its('open').should('be.called')
In a new test, use cy.visit() to go to the url that would have opened in the new window, fill in the fields and click the buttons like you would in a Cypress test.
cy.visit('http://localhost:3000/new-window')
// Do the actions you want to test in the new window
Fully working test example can be found here.
I am not cypress expert, just started using it few days ago, but I figured out this kind solution for stateful application with dynamic link:
// Get window object
cy.window().then((win) => {
// Replace window.open(url, target)-function with our own arrow function
cy.stub(win, 'open', url =>
{
// change window location to be same as the popup url
win.location.href = Cypress.config().baseUrl + url;
}).as("popup") // alias it with popup, so we can wait refer it with #popup
})
// Click button which triggers javascript's window.open() call
cy.get("#buttonWhichOpensPopupWithDynamicUrl").click()
// Make sure that it triggered window.open function call
cy.get("#popup").should("be.called")
// Now we can continue integration testing for the new "popup tab" inside the same tab
Is there any better way to do this?
// We can remove the offending attribute - target='_blank'
// that would normally open content in a new tab.
cy.get('#users').invoke('removeAttr', 'target').click()
// after clicking the <a> we are now navigated to the
// new page and we can assert that the url is correct
cy.url().should('include', 'users.html')
Cypress - tab handling anchor links
I was able to achieve the same requirement via the following:
let newUrl = '';
cy.window().then((win) => {
cy.stub(win, 'open').as('windowOpen').callsFake(url => {
newUrl = url;
});
})
cy.get('.open-window-btn').click()
cy.get('#windowOpen').should('be.called');
cy.visit(newUrl)
Here's a solution i'm using on my project based on "Cypress using child window"
Cypress Window Helpers (aka. Cypress Tab Helpers)
They're really popup-windows or child-windows, but i call them tabs for api brevity
cy.openTab(url, opts)
cy.tabVisit(url, window_name)
cy.switchToTab(tab_name)
cy.closeTab(index_or_name) - pass nothing to close active tab
cy.closeAllTabs() - except main root window
I was recently faced with this issue as well - url for the new tab is dynamic, so I don't know what it is. After much searching, some trial and error, and input from co-workers, resolved by doing the following:
// AFTER cy.visit()
cy.window().then((win) => {
cy.spy(win, 'open').as('windowOpen'); // 'spy' vs 'stub' lets the new tab still open if you are visually watching it
});
// perform action here [for me it was a button being clicked that eventually ended in a window.open]
// verify the window opened
// verify the first parameter is a string (this is the dynamic url) and the second is _blank (opens a new window)
cy.get('#windowOpen').should('be.calledWith', Cypress.sinon.match.string, '_blank');
this is how you can handle tabs in same window..
use this code snippet
cy.xpath("//a[#href='http://www.selenium.dev']").invoke('removeAttr','target').click();
I'm using node-webkit 0.13.4.
When I open second window with nw.gui.Window.open and change its location to completely another url (with different domain than previous), I have broken second window object and can't do anything with second screen including changing location one more time.
That's how I open window and save instance of new window.
_initSecondWindow: function(){
this.gui = window.require('nw.gui');
this.gui.Window.open('view/second_window.html', {}, _.bind(function (newWin) {
this.secondWindow = newWin;
}, this));
}
Then I change location of second window
function(channel){
if (channel == 1){ this.secondWindow.window.location.replace('/view/second_window.html');
}else{
var url = 'http://some-remote-address.com/index.php?channel=0';
this.secondWindow.window.location.href = url;
}
}
},
Note that we have two different domains (second_window.html and some-remote-address.com) and load them one by one many times.
At first time when loaded second_window.html I change location to some-remote-address.com normally. at second time when I'm changing location from some-remote-address.com to second_window.html all is fine too. But when I change url from second_window.html to some-remote-address.com at second time this.secondWindow.window is broken and have empty location object
When I located on some-remote-address.com and change not url, but change get parameter "channel" all is fine
I am working on a web based application, in which I have to open popup window. I am using window.open() method to open the popup, like this:
window.open(url, "popupWin");
where url contains the URL I would like my popup window to navigate to. Now, the problem is, if I execute window.open() from multiple tabs (with same or different URLs), at least on Chrome, it might / might not give you the same window which was opened earlier. This behaviour is inconsistent, I mean, either it should get me fresh window every time, or it should get me previously opened window every time.
I need to persist the same popup window for entire domain. How can I do that?
Well looks like there is a direction to go or at least to give it a try.
It fully remains on localStorage which gives you ability to share the knowledge across your tabs within a single domain.
The code I give below does not work yet (it is only a direction), so don't expect too much from running it as it is.
What it does: it saves the popups by the url in a localStorage and when you try to open a new one with the same url it won't do that. If you don't want to distinguish them by URL it is even simpler: store boolean in a localStorage instead of an object.
What it does not do but should:
it should listen to the popup onunload (close) event and reset the localStorage information accordingly. Best for you here is just to set your localStorage boolean value to false
it should listen to the current tab onunload (reload, close) event and also reset something according to Your logic. As I understand the best for you would be just check whether this tab is the last one from your domain (you can also do this using localStorage, e.g. on every new tab adding its identifier, e.g. creation timestamp and destroying it on tab close) and if it is set your localStorage boolean value to false.
This, I think, would be enough to solve the problem. And finally a small piece of code:
// get the localstorage url map
function getOpenPopups() {
var obj = localStorage.getItem('mypopups');
return obj ? JSON.parse(obj) : {};
}
// set the localstorage url map
function setOpenPopups(object) {
localStorage.setItem('mypopups', JSON.stringify(object))
}
// open the popup
function popup(url, title) {
var popups = getOpenPopups();
// check whether popup with this url is already open
// if not then set it and open the popup
if (!popups[url]) {
popups[url] = true;
setOpenPopups(popups);
return window.open('abc', 'cde');
}
else {
return false;
}
}
jsFiddle
From w3c documentation we can see that window.open() returns a reference to the newly created window, or null if the call failed. That means we can keep it in memory and check for closed flag of that window.
var newWindow = window.open('/some/path', 'TestWindow');
// ...
if (!newWindow.closed) {
}
Keep in mind that if window with following name exists, page will be loaded in the same window without opening new one.
Other variants of name parameter like _blank, _self, _top, _parent you can find in official docs too.
In a Firefox Add-on SDK add-on, how do I tell whether a window is in the background, ie. visible but not focused?
For example, if I bring a different application to the foreground, the Firefox window becomes unfocused but is still visible.
The reason why I want to do this is because I have a CPU-intensive content script running in the active window, and I'd like to pause it to avoid unnecessary overhead whenever the user isn't actively engaged with the window - meaning it's in the background or minimized.
require("sdk/windows").activeWindow keeps returning the last clicked window even if it's in the background or minimized. There doesn't seem to be any property for the window's focus state.
I can also get use the following code to get an nsIDocShell:
var mostRecentWindow = require("sdk/window/utils").getMostRecentBrowserWindow();
var docShell = require("sdk/window/utils").getWindowDocShell(mostRecentWindow);
Now when I query the docShell.isActive property, it returns true even if the window is in the background.
The one advantage of docShell.isActive is that it returns false when the window is minimized, while activeWindow returns true even in this case. But it's still missing information about whether the window is in the background or not.
Based on the suggestion by #willlma, this code seems to do the trick:
const windows = require('sdk/windows').browserWindows;
const tabs = require("sdk/tabs");
var anyWindowActive = true;
var refreshTimeoutId;
windows.on('deactivate', function(window) {
if (window == windows.activeWindow) {
anyWindowActive = false;
}
clearTimeout(refreshTimeoutId);
refreshTimeoutId = setTimeout(refreshTabStates, 50);
});
windows.on('activate', function(window) {
anyWindowActive = true;
clearTimeout(refreshTimeoutId);
refreshTimeoutId = setTimeout(refreshTabStates, 50);
});
tabs.on('activate', function(tab) {
clearTimeout(refreshTimeoutId);
refreshTimeoutId = setTimeout(refreshTabStates, 50);
});
function refreshTabStates() {
refreshTimeoutId = null;
for (let win of windows) {
for (let tab of win.tabs) {
var shouldBeActive = anyWindowActive
&& tab == tabs.activeTab
&& win == windows.activeWindow;
notifyTab(tab, shouldBeActive);
}
}
}
where notifyTab() is a function that posts a message to that tab's content script (if any) about whether it should be running or not.
setTimeout is used to avoid multiple calls to refreshTabStates in quick succession. For example, if you click on an inactive tab in a window that's not the current one, that one click results in window.deactivate, window.activate and tab.activate events.
Also, the initial state is a problem. What if the user launches Firefox and puts it in the background before any script has managed to run?
and thanks for taking a look at this seemingly simple question.
The scenario is as follows: I have a website Homepage named 'welcome.html'. From here users can select from a list of URLs and on clicking on the URL a simple Javascript function is called which opens a new Window.
Once the user has finished in the newly opened Window I want them to click on a button which calls a Javascript function to return them to the Homepage. It seems so simple.
However, if the Homepage Window is still open I want to return to this and not open another new Window displaying the Homepage. If the Homepage Window has been closed then I want a new Window to open displaying the Homepage.
I would be very grateful for some guidance here as I can't seem to get it to work.
Regards
Chris
As others have said, it is not the greatest design. However, I've run into scenarios like this in the past, where the business logic stipulates that a new window must be opened and there is no ability to change that.
As Pointy said, the biggest thing is just to keep track of the windows opened, and if you need some further help, perhaps this may help:
http://www.quirksmode.org/js/popup.html
But if possible, I would consider a different design (ask here if you need help implementing it!)
and thank you everyone who went to the trouble of sharing their thoughts.
I solved the problem in the following way:
When navigating from the Homepage to the new Window the following Javascript is used to open a new Window:
function popupFull(url)
// For explanation of this code see: http://www.quirksmode.org/js/popup.html
// Note: If fullscreen = 1 you can't see the menubar, toolbar, status etc.
// It is advisable to have no spaces around the commas in the parameters.
{
//alert("Opening: " + url)
// Prepare the parameter string
params = 'width='+screen.width;
params += ',height='+screen.height;
params += ',top=0,left=0';
params += ',fullscreen=0';
params += ',menubar=0';
params += ',toolbar=0';
params += ',directories=0';
params += ',status=0';
params += ',scrollbars=0';
params += ',resizable=1';
// Open a new window.
newWin=window.open(url, "fullWindow", params);
// If the current Window is in focus, switch focus to the new Window.
if (window.focus)
{
newWin.focus()
}
// Return the new Window object reference.
return newWin;
}
So the new Window can be opened and I have left the Homepage Window open but out of focus behind the new Window.
In the new Window there is a 'Menu' button. Clicking on this calls the following Javascript function:
function openMenu(winURL, winName, winFeatures)
{
// Create a reference of the Window which opened this Window. This should be
// the Main Menu Window.
var winObj=window.opener;
var menuOuterWidth = 1080;
var menuOuterHeight = 896;
var menuInnerWidth = 1068;
var menuInnerHeight = 767;
var menuX = (screen.width - menuOuterWidth) / 2;
var menuY = (screen.height - menuOuterHeight) / 2;
// Prepare the parameter string for re-opening the Menu
params = 'width='+menuInnerWidth;
params += ',height='+menuInnerHeight;
params += ',top='+menuY+',left='+menuX;
params += ',fullscreen=0';
params += ',menubar=1';
params += ',toolbar=1';
params += ',status=1';
params += ',scrollbars=1';
params += ',location=1';
params += ',resizable=1';
try
{
// Check to see if the window reference already exists.
if (winObj)
{
// Check to see if the Menu window is closed.
if (winObj.closed)
{
// The Menu window is closed.
// Open the Menu Window.
winObj = window.open(winURL, winName, params);
// Close this Course Window.
window.close();
// Return the Menu Window object reference should the caller want it.
return winObj;
}
else
{
// The Menu Window has not been closed. Set the Window's size and position.
// Note: When resizing the outerWidth/outerHeight value has to be passed.
winObj.window.resizeTo(menuOuterWidth, menuOuterHeight);
winObj.window.moveTo(menuX, menuY);
// Bring it into focus (bring to front).
winObj.focus();
// Close this Course Window.
window.close();
// Return the Menu Window object reference should the caller want it.
return winObj;
}
}
else
{
// The winObj object does not exist. Open the Menu.
winObj = window.open(winURL, winName, params);
// Close this Course Window.
window.close();
// Return the Menu Window object reference should the caller want it.
return winObj;
}
}
catch(err)
{
txt="There was an error on this page.\n\n";
txt+="Error description: " + err.description + "\n\n";
txt+="Click OK to continue.\n\n";
//alert(txt);
// When IE6 tries to obtain the winObj.closed property, when the window is closed, it can cause
// an error "Permission Denied". This error is caught here. Open the Menu.
// Open the Menu Window.
winObj = window.open(winURL, winName, params);
// Close this Course Window.
window.close();
// Return the Menu Window object reference should the caller want it.
return winObj;
}
}
The comments should explain everything. The key is to get a reference to the Homepage Window where we started. (var winObj=window.opener;).
What caused me such a headache was that if I opened the new Window (using IE6), switched back to the Homepage and closed the Homepage Window, and then in the new Window clicked on the 'Menu' button nothing happened! I tried everything and then, after a cup of tea, realised that I would never write code in any application I was developing without any form of error capture. I added a Try, Catch statement and reported the error in an 'alert'. I got a 'Permission Denied' error.
After a lot of reading I figured I couldn't eliminate the error I would simply handle the error as elegantly as I could. This resulted in the code above.
It works a treat and I hope this helps someone.