History pushState inside iframe, affecting parent window layout in Chrome? - html

I have an iframe in which the pushState is triggered in order to provide the user with the ability to browse back and forward.
This iframe has some transform applied to it, and the parent window responds to mouse move updating the perspective-origin.
See the page in question.
All is fine in Safari, but when browsing back in history with Chrome, the layout of the parent breaks horribly. This sounds crazy to me, as the iframe contents shouldn't ever influence the layout of the parent window.
To test you can browse a few tabs inside the iframe, then click the back button in the browser.
Also note how if you go to "People" tab, and open any of the persons with a picture, the "Back" button in the top left calls the same function bound to pop state (furnax.goBack), without affecting the parent window.
Either this is a bug, or browsing back the history does more than I think.
I hope anyone has some insight.
Popstate handler:
$(window).on("popstate", function () {
if (furnax.popStoryEnabled) furnax.goBack();
});
goBack function:
goBack: function () {
var myHistory = tempDb.getItem("prev").split(",");
var to = "";
if (myHistory != "") {
to = "#" + document.getElementById(myHistory[myHistory.length - 1]).id;
} else {
to = "#" + $(".view").first().attr("id");
}
furnax.load(to, "pushright", true);
myHistory.pop();
tempDb.setItem("prev", myHistory.toString());
},

This is happening for me in both Chrome 41 and Safari 8 on OS X 10.10.2. I don't think the issue is with pushState. I believe what's happening is that when you change the URL in the iframe, the browser sets focus on the iframe and auto-scrolls the document to show the full iframe.
I believe it's similar to a bug I'm experiencing with focusing on inputs inside a CSS transformed iframe. Webkit bug #143100, Chromium bug #470891.
I'm not sure if your situation qualifies as a bug, as I believe it's intended behavior for browsers to do everything they possibly can to show focused elements, even if that means scrolling an overflow:hidden element. Then again, I'm not positive the iframe is actually receiving focus, it might be a different issue that just has some overlap.
One thing I would try is to make the pop state handler move the "iPhone" to the center of the window, and only change its URL after it has finished animating. If that doesn't work, maybe you can take a look at the example page I reference in my bug reports. It might give you some additional insight into the nature of the automatic scrolling.

Related

Opening a new window/tab without changing focus (Chrome)?

I have a problem with focusing between browser windows/tabs. I would be very grateful for some input! :-)
Our main target browser is Chrome. And I know that the rules for what's allowed has changed over the years - because these features have been constantly abused... I've looked at a lot of older answers, e.g. I need to open a new window in the background with JavaScript, and make sure the original is still focused, but I haven't found anything that will work today. (Apparently this is called a "pop-under" window.)
In our application, in window-A, we want to open another window/tab, window-B, with a certain URL. But the focus should remain on window-A. We have full control of the webpages that are loaded in both windows, and they are loaded from the same domain.
This won't work (in window-A):
window.open('mydomain.com/second-page');
window.focus();
And this won't work (in window-B, after load):
window.opener.focus();
For a number of years now, Chrome hasn't allowed a window to set focus to itself or its parent.
This will actually work:
// in window-A:
window.name = 'HOWDY';
window.open('mydomain.com/second-page');
// in window-B:
window.open('', 'HOWDY');
Opening a blank URL in a named windows, will switch focus to that window - without changing the contents of the target window.
BUT it only works if I put it in an event handler - e.g.:
document.getElementById('mybutton').addEventListener('click', function(e) {
window.open('', 'HOWDY');
});
If I try to do it automatically (after load, or by sending the page a SignalR message), the open-blank-URL-in-named-window trick won't change focus. I suppose it's one of those "only allowed in direct response to user interaction" things. (It will load another page in window-A if I add a URL, though, so the open() call works. But window-B retains focus.)
Is there any way to solve this? Either by not moving focus to window-B in the first place, or by automatically moving focus back from window-B to window-A?
/Anders from Sweden

Browser scrolling to previous position instead of anchors when navigating back / forward

I am building a slider in pure HTML / CSS (no JS). It works very well, see the code.
You will need to download it and execute it locally to understand my problem as it is related to the back and forward buttons of the browser.
When clicking on links to navigate, the URL changes to #a1, #a7, #a5, whatever you are doing. The slider scrolls to the appropriate slide correctly. If you manually change the URL, putting #a3 instead of #a7 for example, slider will also scroll correctly.
However, when you go back (or forward), the URL changes from #a3 to #a7 but the content doesn't scroll.
Any idea why? Any idea what I can do to have the scroll on the back action?
I asked a Firefox developer and he explained to me why this is the expected behavior, and not a bug.
I misunderstood what was going on with the back action. Quick answer: it doesn't go to the previously selected anchor, it goes where the body scroll was.
Still using the code in the codepen in the question:
Remove the overflow-x: scroll from the CSS
Click on #a3, then on #a7. The content scroll to #a7
Click on the back button of your browser
I thought the browser was scrolling back to #a3. But in fact, it is scrolling to where it was before you clicked on the link. To see it in action:
Click on #a5. The URL changes to #a5
Move the scroll to have #a3 on the screen
Click on #a7. The URL changes to #a7
Click on the back button of your browser
The URL changes to #a5 but #a3 is displayed on the screen, as that's where you were before clicking the link.
So, it is the expected behavior according to the whatwg spec.
However, that's not the behavior I want. So, let's go for a dirty hack:
window.onhashchange = function() {
window.location.href = window.location.href;
};
Now, when clicking back, it will force the page to reload locally (no server request) and it will scroll to the element.
Wow, that was an hard one.

Open a new browser window WITHOUT using target="_blank"

Every solution I've seen so far for opening a new browser window uses the target property in to set it to "_blank". This is frustrating because in some browsers it only opens a new tab AND combine that with the auto-resizing behvaiour at http://www.facebook.com/connect/prompt_feed.php?&message=test, it basically mangles my browser whenever I try updating my status from my site.
How can I be sure to open a new window when a user clicks on a link?
Thanks!
Trindaz on Fedang
Popups are windows, they just have some features disables. You can make a popup act like a regular window by enabling these features. For example, if you open a popup with
window.open('url', 'name', 'width=500, height=500, status=1, toolbar=1, location=1, menubar=1, resizable=1');
the window will have a toolbar, a URL bar, a status bar, menus, and it will be resizable. It will the same as any other window.
Keep in mind, however, that many browsers block window.open() under some conditions, and some of them will open new tabs if you specify a lot of features. Some are weird about it too; Chrome, for example, uses scroll bars on popups by default, but if you specifically tell it to use scroll bars in a popup (using scrollbars=1), it will open in a tab instead.
So basically there is no way to be completely sure that your page will always open in a new window, because browsers all handle this stuff differently, users can change settings too. The code above is probably your best bet if you have to have a new window, but you might want to look into other options.
window.open(URL,name,specs,replace)
function newwindow()
{
myWindow=window.open('','','width=300,height=300');
myWindow.document.write("<p>This should open in a popup</p>");
myWindow.focus();
}
There is a legitimate reason for using Target=_blank that everybody has completely overlooked, and that is when a website is written as a BOOK with chapters/pages and the Table of Contents must remain intact without using the BACK button to reload the previous page (Table of Contents). This way all a surfer needs to do is close the Target Page when finished reading and they will be back to the Table of Contents.
Lucky for us that HTML5 has reinstated the Target="_blank" code, but unfortunately the "Block Popups" must be unchecked for it to work.

Scrolling a page using location.hash in Safari

I have a forum page that displays a tree view of messages below the currently selected message. When you click on a message in the tree the new message body is loaded into a div near the top of the page using AJAX and then the following code is run:
window.location.hash = "page_top";
Of course "page_top" is an anchor element near the top of the page, so the newly loaded message body scrolls into view.
This works fine on all the browsers, except Safari. On Safari (tested on PC and iPhone) it only works the first time you set location.hash. If you set it again the page does not scroll.
The end result is that the newly loaded message body does not scroll into view in Safari and you have to scroll back to the top of the page every time you pick a new message from the tree.
Why does Safari not like this and is there anything I can do to fix it ?
Edit:
I'm guessing this is related to a bug that you can find by Googling about location.hash and Safari. It seems Safari used to have a bug where if you set the hash to the same value twice it would cause it to reload the page. I'm guessing when they fixed that bug they fixed it a little too thoroughly and stopped it doing anything when you set hash to the same value again.
http://www.howtocreate.co.uk/safari/locationHashBug.html
You could reset it first:
window.location.hash = "";
window.location.hash = "page_top";
I needed to add:
<div><a name="page_top"></a></div>
<div><a name="page_topnot"></a></div>
Using "a name" instead of "a href". Works great!
Answering my own question. Gumbo was on the right track, but not quite there.
Safari doesn't like location.hash being set to a blank value. Instead you need to set it to a real anchor value.
So along at the top of the page I now have:
<div></div>
<div></div>
I found that I needed the divs around the anchors otherwise Safari was scrolling to an unpredictable part of the page rather than to the anchors.
Then to scroll to the top of the page I have to do:
window.location.hash = "page_topnot";
window.location.hash = "page_top";
With that in place Safari will scroll to top of the page every time.
I had the same problem as you had and this solution worked - the only thing I noticed was that in IE, I could hear two clicks - So I did a variation of yours and just put one anchor and it worked as well (ie, call twice, the first time, a non-existent anchor, the second time the real one)
On top, my anchor:
(tag a)name="top" id="top"(end of tag a)
Within javascript, the two calls:
window.location.hash ="topnot";
window.location.hash ="top";
Thanks for your help!

Why do page anchors sometimes miss?

On an HTML page, a link like this:
Location on Page
...should navigate to this spot on the page:
<a name="pagelocation">
But in my experience, it sometimes misses - especially when linking from another page (like <a href="somepage.html#pagelocation">). By "misses," I mean it scrolls to the wrong spot on the page - maybe close, maybe not.
Normally, the target location ends up at the top of the screen. I know this can fail if there's not enough room below the anchor to scroll it to the top of the screen.
Why else would it fail? Does it depend on layout at all? How can I fix it?
(I'm keeping this general because I'd like a catch-all reference answer.)
Update 1
Thanks for the pointers so far about non-explicit image sizes. But what about on a page where all the elements have explicit size? (I'm dealing with one now.)
Quite often the scrolling can occur before the page has finished loading. If you have images without widths and heights, the page will jump, then load the image and re-layout itself, making the place you previously jumped to seem wrong.
Edit: Anything else that can change page layout should also be considered with suspicion... this include javascript and CSS that's not loaded in the <head> (never mind that all CSS should be loaded in the head; it isn't always).
If the page is bounced through a redirect, I believe IE will scroll the end page but Firefox won't.
JS Solution
Run this function on document ready.
function goToAnchor() {
hash = document.location.hash;
if (hash !="") {
setTimeout(function() {
if (location.hash) {
window.scrollTo(0, 0);
window.location.href = hash;
}
}, 1);
}
else {
return false;
}
}
I believe the behavior you are seeing is the result of the browser locating to that spot on the page before all images have finished loading. Once the images finish loading, then the layout of the page has changed (the page is likely longer vertically, for example), causing the location of where the anchor should be to have changed - but the browser still thinks it has already navigated to that anchor.
As mentioned above, this is probably due to images being rendered late and 'adjusting' the layout as they load.
If you can specify the size of the images then that much room can be allocated before they render, which should prevent the problem.
As a side note I've had this problem before in the form of using forward/back between enough pages that the images needed reloading, causing me to end up in the wrong place after they had rendered.
I have also seen this happen when JavaScript creates a drop-down menu at the top of a page. Then, once the menu has been finished, it is hidden, scrolling up the content below.
In the meantime, the browser has already set the target location at the top of the window. Hiding the menu a the very top of the page moves the target location up off the top of the window.
Note that you can add id="pagelocation" to just about any HTML element, for the same result, which saves you adding the additional anchors for link destinations.
OK. I think this is new. Using HTML5's autofocus will cause a misfire, as will jQuery's focus() method. Took 90 minutes of trial and error to discover this because I thought the issue was image related :)