First of all, please don't recommend me to use the native iOS/Android objects, this is a test about custom controls and I need it to work.
I'm encountering a strange behavior while using a custom Navbar in Android or iOS. All seems to be right until I close a window directly (by code) in the custom navBar. The secont time I open another window with the navBar, the old objects (label, buttons, etc.) are still there.
I post an example:
First, from a main window I call the AddForm in the NavBar:
var ui = require('navigation');
var nav = ui.createNavigatorGroup();
Alloy.Globals.navBar = nav;
nav.open(winAddPill, {animated: true});
When user press ADD button (you can't see, is in bottom of a form), I autoclose the window in the nav, after save the data, with this code:
Alloy.Globals.navBar.close($.win);
If I do that, when now I call another window, e.g., show info (which has a DELETE button in right), the title label is mixed with previous window:
Alloy.Globals.navBar.open(winPill, {animated: true});
As you can see, all is mixed, this is what must be shown instead:
If I continue to open new windows, all is still mixing.
Any help to avoid this behavior? I was fighting with this problem 4 days and don't find the solution.
Finally, the custom navBar that I'm using:
exports.createNavigatorGroup = function() {
var me = {};
var navViews = []; // A stack of navigation bars
var navView;
function pushNavBar() {
navView = Ti.UI.createView({
top: 0,
height: 44,
backgroundColor: '#BBB'
});
navViews.push(navView);
};
function popNavBar() {
navViews.pop();
navView = navViews[navViews.length - 1];
};
// Make sure we always have a navView available to prepare
pushNavBar();
me.open = function(win) {
navView.add(Ti.UI.createLabel({
text: win.title,
color: 'black'
}));
navView.win = win;
win.add(navView);
win.navBarHidden = true;
win.open();
// Prepare for the next window
pushNavBar();
};
me.close = function(win) {
if (navViews.length > 1) {
// Close the window on this nav
popNavBar();
win.close();
}
};
return me;
};
Also I added a simple and runable project in GitHub with only 3 empty windows for testing. You can see the question here and the project is here.
I found the f***g problem!!!
I analized with detail the code and found it. All the problem resides in that a new navView is always prepared for config new objects, so, lets say, we have 2 windows opened, then we have 3 navViews. The number 3 is clear, nothing inside, just ready to setLeftButton before open new window with it.
But if we close the actual window, with the navView 2 with objects, the code makes "popNavView" that only remove the last (empty) navView 3 and SETS the actual navView 2 as ready to use... with all its actual objects inside.
The simple solution is... remove it after set, with this simple line inside popNavBar:
function popNavBar() {
navViews.pop();
navView = navViews[navViews.length - 1];
navView.removeAllChildren();
};
I will re-do the github code to let it available for others who wants to use a functional custom NavBar.
Related
My page opens a popup and communicates with it using window.postMessage. To know when it is ready, one of the first things in the popup-script is:
window.opener.postMessage("initialize")
and then I reply and give the data and so on.
However if I have two instances of the same page open I'm running into a few problems. In Chrome and Firefox it actually opens individual popups even when the windowName is set. Setting focus using myPopup.focus() doesn't even seem to bring them up to the top. In IE however it reuses the same window, which I initially thought was a great improvement.
As stated in the spec, the window.opener reference is however never updated, even when another parent reopened it. Meaning the initial code will communicate with my first instance. I've tried in various ways to change the behavior, but I can't seem to communicate between these in any way.
Then I found a clever way of detecting this, storing the dimensions and position, then closing and reopening it. It looks like this:
const createPopup = (dimensions) => {
let features = "menubar=0,toolbar=0,status=0,personalbar=0,location=0,resizable=1,scrollbars=1";
const myPopup = window.open("/imageViewer.html", "ImageViewer", features);
if (myPopup.opener !== window) {
dimensions = { height: myPopup.outerHeight, width: myPopup.outerWidth, X: myPopup.screenX, Y: myPopup.screenY };
myPopup.close();
return createPopup(dimensions);
}
if (dimensions) {
myPopup.moveTo(dimensions.X, dimensions.Y);
myPopup.resizeTo(dimensions.width, dimensions.height);
} else {
myPopup.focus();
}
return myPopup;
};
The problem is that the main use I have for this is when the popup is located on a secondary monitor, and it doesn't seem to be allowed to neither move the popup outside the dimensions of the primary screen.
Is there anyway to solve this problem with using postMessage? My only other alternative which comes to mind is using localstorage to put information and look this up on intervals, but I'm not very happy with such a solution.
So to sum up I need to have a function (createPopup) which will create or bring a secondary window/popup to the front. The main window needs to be able to communicate with it, and it must work when using different instances of the same main page. (but running the function again when switching instances is OK.)
While setting in JavaScript failed, it works when setting directly when opening the window in the features-parameter:
export const createPopup = (dim) => {
let features = "menubar=0,toolbar=0,status=0,personalbar=0,location=0,resizable=1,scrollbars=1";
if (dim) {
features += ",left=" + dim.X + ",top=" + dim.Y + ",width=" + dim.width + ",height=" + dim.height;
}
const myPopup = window.open("/imageViewer.html", "ImageViewer", features);
try {
if (myPopup.opener !== window) {
throw Error("just trying to read opener will throw exception in IE if the opening window has been closed");
}
} catch {
dim = { height: myPopup.outerHeight, width: myPopup.outerWidth, X: myPopup.screenX, Y: myPopup.screenY };
myPopup.close();
return createPopup(dim);
}
myPopup.focus();
return myPopup;
};
Focus still doesn't seem to work in chrome-based browsers, but that is a very different bug indeed.
Do we have to create new popup if google crome updated or we can continue with the older one.
No one is sure what you're asking, but I'm going to take a stab at it. I believe you're asking if you have to use a new popup every time an advertisement is changed? If that is the case, the answer is no, you don't always have to have a new popup. HOWEVER, if the window was closed by the user, a new popup will have to be created. The following code will bring a named window to the front:
function GetAdWindow() {
// Change the window.open parameters to your liking
var AdWindow = window.open("", "AdWindow", "toolbar=no,location=no,status=no,menubar=no,scrollbars=yes,resizable=no,width=500,height=500");
return AdWindow;
}
After that, you have to determine if the page is blank, or already has an advertisement on it.
function UpdateAd(){
var AdWindow = GetAdWindow();
// If the AdWindow wasn't populated (meaning it was closed)
if (AdWindow.location.href === "about:blank") {
AdWindow.location = /*ADVERTISEMENT URL*/
} else {
// DO WHATEVER YOU WANT IF THE WINDOW HAD CONTENT
}
}
If you asking if your popup will go away if Chrome has an update, the answer is yes. Chrome as a whole will shot down and close all of the windows, then start back up clean.
I have an object wich caches windows with all their internal structure (form, other ui elements). So when a user opens a window which has already been cached, it does create it from scratch, but takes if from cache and just show it like this:
winCache[id_group].show();
So, for each id_group, there is a window which may be cached in winCache. The problem is that I want to reset a form, which is inside the window, and populate it with new data from database. I try to do it like this:
if(winCache[id_group]){
winCache[id_group].removeListener('show');
winCache[id_group].addListener('show', function () {
populate_form(this, id_field); // <-- this method retreives data from database
// and sets the form
});
winCache[id_group].show();
}
else { // window was not cached and has to be created from scratch
var win = ...
win.show();
// ... some BIG procedure
winCache[id_group] = win; // next time it will be taken from cache
}
But the problem is, for some insane reason, ExtJS duplicates show listeners infinitely. So, for example, if I open winCache[10] seven times for the same id_group = 10, but for different id_fields (id_field = 1, id_field = 2, ..., id_field = 7), then show listener will be triggered seven times - for each id_field. And that is incredible stupidity. So, my question is why ExtJS duplicates listeners? And why doesn't removeListener work???
The removeListener expects a function reference as the second argument.
If this code you've added is executed each time the window should be displayed may be using single: true on the addListener will solve your issue (so you don't need to removeListener), try:
winCache[id_group].addListener('show', function () {
}, null, { single: true });
If that's not the case, you'll need to save a reference to the show function you'r passing to addListener so you'll be able to pass it to removeListener, or may be use destroyable, like:
winCache[id_group].destroyShowEvent && winCache[id_group].destroyShowEvent.destry();
winCache[id_group].destroyShowEvent = winCache[id_group].addListener('show', function () {
}, null, { destroyable: true });
Made some changes based on help from engineering. Here is the final code I used for grabbing the new window handle:
localdriver = #driver
#driver.getAllWindowHandles()
.then (handles) ->
localdriver.switchTo().window(handles[1])
I'm currently running an automation stack that uses Selenium Webdriver, Mocha, Chai, and Grunt. I'm creating scripts in Coffeescript, but an answer to my question in Javascript would be perfectly fine.
What I'm trying to do:
Click button on main browser window
Switch driver to the second window that opens after button click
Perform actions in the second window
Close second window and return to the first.
I've scoured the internet looking for an answer on how to do this. Just started learning all this stuff a few months ago, and I'm still stumbling through creating stuff. I'm seeing a lot of Java and C+ examples, but not much on the Javascript side. Can anyone provide an example of how to set up the code for the above scenario using Selenium Webdriver and Javascript?
var parent = driver.getWindowHandle();
var windows = driver.getAllWindowHandles();
driver.switchTo().window(windows[1]);
// do some stuff
driver.close();
driver.switchTo().window(parent);
What you want is driver.getAllWindowHandles(), but because this returns a promise, make sure that you then use the handles inside of the then function
// select the newly opened window
driver.getAllWindowHandles().then(function gotWindowHandles(allhandles) {
driver.switchTo().window(allhandles[allhandles.length - 1]);
});
Whenever new tab opens, it takes some time to come up and render. In this situation, it is difficult to switch the tab because the tab is not opened yet and driver.getAllWindowHandles() will not give handler for that tab. I solved this problem in this way, I am assuming I have one opened tab and on some button click, I am opening new 2nd tab.
function openNewTab(driver) {
driver.wait(function () {
return driver.getAllWindowHandles().then(function (handles) {
var isHandleCount2 = (handles.length == 2);
if (isHandleCount2) {
driver.switchTo().window(handles[1]);
}
return isHandleCount2;
});
}).then(function () {
// Now do some stuff in new tab
var buttonElement = driver.wait(until.elementLocated(By.xpath("//td[*//span[text()='Click me']]")));
buttonElement.click();
});
}
This code will wait until the number of handles or tabs will not equal to 2.
#Jai Prak's answer is brilliant.What about the case of three tabs or more? The newest tab will always be the last Tab.
return await driver.wait(async function () {
return await driver.getAllWindowHandles().then(async function (handles) {
// var isHandleCount2 = (handles.length == 2);
if (handles.length > 1) {
return driver.switchTo().window(handles[handles.length - 1]);
}
return false;
});
}).then(function () {
// Now do some stuff in new tab
});
The above will apply except in cases you switch between Tabs.To move the next tab, get the current Tab's index -1
References: https://developer.chrome.com/apps/notifications
I am using the chrome.notifications.create(string id, object options, function callback); to create a chrome notification.
var id = 'list';
var options = {};
options.title = 'test';
options.iconUrl = 'notification_icon.png';
options.type = 'list';
options.message = "test";
options.buttons = [{title: 'test'}];
options.items = [{title: 'test', message:'test'}];
var createCallback = function(notificationId) { console.log(notificationId); };
chrome.notifications.create(id, options, createCallback); // returns 'list';
This creates a notification as expected. All working correctly.
I then call chrome.notification.clear(string id, function callback);
var id = 'list';
var clearCallback= function(wasCleared) { console.log(wasCleared); };
chrome.notification.clear(id, clearCallback); // returns true;
This does clear the notification. All working correctly.
EXCEPT it does not clear the notification out if the notification panel is open. This is not a major problem 99% of the time. Until I implemented the button code within the notification.
Using chrome.notifications.onButtonClicked.addListener(function callback); On click I am calling the clear notification panel code, and it reports back as it has been cleared.
var onButtonClickedCallback = function (notificationId, buttonIndex) {
console.log(notificationId, buttonIndex);
if ( notificationId == 'list' ) {
chrome.notification.clear(id, clearCallback); // returns true;
}
}
chrome.notifications.onButtonClicked.addListener(onButtonClickedCallback); // onClick it returns 'list', 0
But I am looking right at it.. Once the notification panel closes and opens again, I can confirm it has actually gone. But obviously since I am clicking a button on the notification, the panel is open, but it does not clear away as I would have liked.
All this is running in an extension background without the persistence: false property (so the script is always loaded, and since I can see the output, I know the functions are being called).
Have I overlooked something? I do not see any functions that deal with closing the notification panel. So as far as I can tell, I am clearing the notification but the panel is not updating it's display.
I am using Chrome 37.0.2019.0 canary on Win8
If anyone can suggest something I may have missed, I would be greatful. My google searches reveal people having problems with the HTML notification.
This is a known bug, or rather an old design decision, with little progress.
Star the issue to raise its priority. I also suffer from the same.
Here's the workaround solution I've been using for several months now:
// open a window to take focus away from notification and there it will close automatically
function openTemporaryWindowToRemoveFocus() {
var win = window.open("about:blank", "emptyWindow", "width=1, height=1, top=-500, left=-500");
win.close();
}
chrome.notifications.clear("", function(wasCleared) {
openTemporaryWindowToRemoveFocus()
});