jQuery Bug - Bind an event from iframe to parent.window - javascript

I have two pages: parent.html and child.html.
child.html is included in parent.html with an iframe.
The child.html page bind a scroll event on its parent.window in order to detect when a scroll event is triggered at the top level. The child page set a property on the parent.window in order to display and update an increment each time the scroll event is triggered.
Here is the code of the two pages:
Page parent.html:
<html>
<body>
<iframe border="1" src="child.html"></iframe>
<div style="height:1600px; width:300px; background:gray;">
A div just here to activate the scrollbar
</div>
</body>
</html>
Page child:
<html>
<body>
<a target="_self" href="">Reload this page</a>
<div class="test"></div>
<script type="text/javascript">
parent.window.increment = 1;
var onScroll = function (event) {
parent.window.increment++;
$('.test').html(parent.window.increment);
};
$(parent.window).off('scroll');
$(parent.window).on('scroll', onScroll);
</script>
</body>
</html>
The problem with this setup is the following :
On Chrome (it works on Firefox), if you load the page for the first time the parent.window.increment is correctly incremented by 1 each time a scroll event is detected (when the parent page scrollbar is moved). But if you press on the "Reload" link the parent.window.increment is no more incremented by one when a scroll event is triggered but by two. If you press again on the Reload link the increment property is incremented by 3, etc.
A working example can be found here : http://jsfiddle.net/cm0s/ngZkq/16/.
I'm not really looking for a solution (the code I posted is just an example of a problem I'm facing in another project). I'd rather like to understand what's happening. If I'm making a rookie mistake?
Here are two things I really don't understand :
1. parent.window.increment not reset
I don't understand why the increment property is not always reset to 1. When we press on the "Reload" link the following line is always executed :
parent.window.increment = 1;
2. Works on Firefox but not on Chrome
What I also don't understand is why it doesn't work on Chrome but works fine on Firefox. With Firefox if you try the fiddle demo and click multiple times on the Reload link the parent.window.increment is always incremented by 1 when you move the scroll bar.
EDIT NOTE:
I also created a fiddle to show the same problem with a click event :
http://jsfiddle.net/cm0s/WYy6U/3/
And another one which use the onscroll javascript function (as explained by #hex494D49) and thus works perfectly in all browsers :
http://jsfiddle.net/cm0s/D6j5G/1/
EDIT NOTE 2:
I posted a ticket on the jquery bug tracker: http://bugs.jquery.com/ticket/15204.
The ticket has been closed. The bug has been described as "an unusual browser behavior".

You just might found a bug in jQuery :) or at least a weird behavior of jQuery's onscroll event implementation. Perhaps, this could be a shorter answer on your both questions but let's analyze this behavior in more details.
If you add this console.log(parent.window.increment); in your code, you will see that at the first time Chrome is increasing the value of increment value just fine; but at the second time, the amount of the scroll is increasing by two as following 1-2, 3-4, 5-6, ... and that's way the increment value within the div seem disordered (like 2, 4, 6, ...); at the third time Chrome starts skipping steps like this 2-3, 5-6, 8-9, 11-12, ... and the values within the div came in as 3, 6, 9, 12, ...; at the fourth time values goes like this 3-4, 7-8, 11-12, 15-16, ... which makes the increment value within the div even more fuzzy.
On the other hand, the snippet above works fine in Firefox but the amount of scroll isn't increasing by 1 but at least by 5 and this could be seen only observing the console. Maybe this could be adjusted - I tried to change a few values related to scroll in Firefox about:config section but without success so far.
Then I just thought I could change your snippet a bit (excluding jQuery) and here we are - the snippet below works just as expected in all browsers. The scroll amount on Firefox is still about 5 but you'll see that the increment value on reload is always resetting to 0 and there are no skippings as mentioned in case with jQuery snippet.
// Modified code of child.html (iframe) file
// HTML
<a target="_self" href="">Reload this page</a>
<div id="test"></div>
// JavaScript
parent.window.increment = 0;
parent.window.onscroll = function(){
parent.window.increment++;
document.getElementById('test').innerHTML = parent.window.increment;
console.log(parent.window.increment);
};
Working jsFiddle (Tested on IE, Firefox, Chrome and Opera)
EDIT: As #NicolasForney (the OP) says in the meantime in his edit section, the same weird behavior is experienced using onclick event. I'd like to add that the same would be avoided not using jQuery, just as shown in the previous case with onscroll event.
<!-- HTML -->
<a target="_self" href="">Reload this page</a>
<div id="counter"></div>
// JavaScript
parent.window.counter = 0;
parent.window.onclick = function(){
parent.window.counter++;
document.getElementById('counter').innerHTML = parent.window.counter;
console.log(parent.window.counter);
};
Working jsFiddle (Tested as above)
This definitely leads to a bug which should be explored in more details in the meantime...

Related

Form Submit not working in latest chrome build (83)

Chrome : chrome update Version 83.0.4103.97 (Official Build) (64-bit)
Flow
Function function_name is called from a page (this page remains the main parent page in the whole scenario) which has a table with multiple records and a record has a hyperlink which fetches more data and displays in an overlay/popup.
The code etc. mentioned in the code section in the bottom is on that Popup/Overlay piece where form & iframe exist and facilitate the whole process.
On Form submit here another piece of html code is called which is then populated in iframe, please check the target of the iframe.
Issue
The form submit was working earlier for all browsers and post new update it's not
working on latest chrome build but it is working on other browsers at the moment without any issue.
Explanation of not working
I have added logs, it works as expected till form submit line is called. On Form submit we expect the new html piece to be called and then that to be loaded in the iframe. That page never gets invoked on the latest chrome build (does get invoked in all other browsers), there is no reflection on network tab either which should happen because on form submit another file is called. (happens in all other cases)
Observations
The popup flow is initiated from a button click in parent page (as explained in the flow)
< a href="#" onclick="function(this,val1,val2); return false;">
The code for the same is given above, if the same piece of code is removed from the parent page and then replaced with something else and then again changed back to this same code then it works normally. (I have no clue why!)
The behavior is erratic too, once in a blue moon even on latest chrome it works properly, once or twice. But the efficiency of system on all other browsers is 100%.
Code : Minimal (Comments are added for understanding separately)
<div id="divid" class="dialog" title="">
<!-- Iframe -->
<center>
<iframe name="frameid" id="frameid" src="/images/somegif.gif" width=820 height=400 frameborder=0 style="border:0; padding:0; margin:0;"></iframe>
</center>
</div>
<!-- Form -->
<form id="formid" name="formid" method="post" action="/somefile.html" target="framename">
<!-- Some Form Elements -->
</form>
<script>
//Javascript
$(function() {
$("#divid").dialog({
width: 860,
autoOpen: false,
modal: true,
resizable: false,
open: function(e, ui) {
$(this).siblings(".ui-dialog-titlebar").find("button").blur();
},
close: function() {
jQuery('#framename').attr('src','/images/somegif.gif')
}
});
});
function function_name(val1,val2) {
var form_obj;
form_obj=document.getElementById('formid');
if (form_obj) {
//some operation, validation etc.
jQuery("#divid").dialog('open');
somefun(form_obj, "var_name", var_name); //They are working fine
somefun2(form_obj, "var_name2", var_name2); //They are working fine
form_obj.submit();
}
}
</script>
I just noticed that form name and id is same, same goes for the iframe. The developer who wrote this is not with us anymore, in short, not my code.
#Gandalf, found this issue on chromium.
Issue 1092200: Submitting form whose target is an iframe randomly fail siliently
A bug fix for it was merged into 84, but a bugfix for Issue 1092313: Form submission takes precedence over window.location navigation
caused a regression, and looks like they are still looking into it..
We are also experiencing the same problem, and watching 1092200

Page reload doesn't reset jQuery / CSS styles

I'm designing an HTML page which has one button. The user clicks the button and a simple jQuery script animates that div away, revealing lower page content. You can see it here.
I've noticed that it looks/works fine the first time, but if I refresh the page with the browser button, it doesn't fully reset. The initial container is only half on the page. If I enter the URL again and load the page, it resets as expected.
NOTE: This only happens if you scroll down a bit after clicking the initial button... which seems weird.
I had no idea that there was any difference between these two operations, but there clearly is. What is the difference and how can I fix this problem from happening?
Here's my jQuery code, in case it's relevant:
$(document).ready(function(){
var faqs = $("#FAQ");
$("#learnmore").click(
function(){
$("#home").animate({top:'-=1066px'},600);
$("#more").animate({top:'-=1066px'}, 600, function() {$("#background").hide();} );
$("body").css('overflow-y', 'scroll');
//$("#home").slideUp();
console.log("jquery loaded");
}
);
});
It happens because it is cached by the browser.
If you styles are regularly modiefied, then as easy fix is to attach a unique id on the end of the reference, like
<link href="style.css?time=168768234928" ..../>
What it does, it makes the browser think it is a new request everytime it loads.
It happens because browser trying to scroll to the same position, what was before page reload. To check it, try press button and don't scroll to bottom of page and then reload page.
Okey, the reason is clear.
Now we need solution. Try this:
#more {display:none}
in your css. And then use
$("#more").show().animate(...
in your $("#learnmore").click() function. I hope this will solve the problem.

rules for "prevent this page from creating additional dialogs"

I try to understand Firefox's behavior regarding the added "prevent this page from creating additional dialogs" on dialog boxes.
Using jquery, if I add the following listeners :
//html
<input class="testInput" />
//javascript
$('.testInput')
.click(function(){ alert('clicked') })
.keyup(function(){ alert('keyup') })
When clicking on the input, the alert box appears normally, until the
~13th time.
When hitting a key, on the other hand, the second message box already
appears with the message "prevent this page from creating additional
dialogs". Actually, there seems to be some tiemout, and if I wait
like 2 seconds between two keystrokes, the message disappears.
From my informal tests, 2. actually applies whenever the alert box is not called from within a onclick callback (e.g : keyup callback, displaying an alert box in answer to an ajax action...)
I am using Firefox 9.0.1 under Ubuntu, as far as I know I haven't tweaked firefox's settings regarding these thresholds.
I imagine it happens with any recent version of any browser.
I am using the jQuery library, but I don't think it is relevant here.
My question is :
What are the exact rules which make this warning appear in a dialog box ?
[Edit]
Using Chromium/Ubuntu (version 17.0.963.26), the threshold seems to be only the delay between two dialog boxes.
You can test this from jsfiddle here (thx Rory McCrossan)
The exact rule(s): A timed interval between the dialog boxes popping up.
The value used to determine this is set in SUCCESSIVE_DIALOG_TIME_LIMIT
Check out line 2614 in the link below the snippet:
nsGlobalWindow::DialogOpenAttempted()
TimeDuration dialogDuration(TimeStamp::Now() - topWindow->mLastDialogQuitTime);
if (dialogDuration.ToSeconds() < Preferences::GetInt("dom.successive_dialog_time_limit",SUCCESSIVE_DIALOG_TIME_LIMIT)){topWindow->mDialogAbuseCount++;return (topWindow->GetPopupControlState() > openAllowed || topWindow->mDialogAbuseCount > MAX_DIALOG_COUNT);}topWindow->mDialogAbuseCount = 0; return false;}
Link to source
You can kick around the Firefox source if you like. Note that different browsers will have different rules.
The relevant code for Firefox is in nsGlobalWindow.cpp and nsGlobalWindow.h (the links below are to line numbers, and so will slowly rot as the source changes). It appears to be controlled by the constants MAX_DIALOG_COUNT (10) in nsGlobalWindow.h and SUCCESSIVE_DIALOG_TIME_LIMIT (3, units are seconds). nsGlobalWindow.cpp keeps a count (mDialogAbuseCount). Apparently, the dialogDuration function either increments or clears mDialogAbuseCount depending on whether the dialog has been open longer than the SUCCESSIVE_DIALOG_TIME_LIMIT. The AreDialogsBlocked function uses the mDialogAbuseCount (in part) to decide whether they're blocked.
So in short: If you're repeatedly opening pop-ups and then closing them within three seconds, after 10 or so you'll trigger something.

HTML anchor link with no scroll or jump

I have various links which all have unique id's that are "pseudo-anchors." I want them to affect the url hash value and the click magic is all handled by some mootools code. However, when I click on the links they scroll to themselves (or to the top in one case). I don't want to scroll anywhere, but also need my javascript to execute and to have the hash value in the url update.
Simulated sample code:
button 1
button 2
Home
So if you were to click on the "button 1" link, the url could be http://example.com/foo.php#button1
Does anyone have any ideas for this? Simply having some javascript return void kills the scrolling but also kills my javascript (though I could probably work around that with an onclick) but more importantly, prevents the hash value in the url to change.
The whole point of an anchor link is to scroll a page to a particular point. So if you don't want that to happen, you need to attach an onclick handler and return false. Even just adding it as an attribute should work:
button 1
A side of effect of the above is that the URL itself won't change, since returning false will cancel the event. So since you want the URL to actually change, you can set the window.location.hash variable to the value that you want (that is the only property of the URL that you can change without the browser forcing a reload). You can probably attach an event handler and call something like window.location.hash = this.id though I'm not sure how mootools handles events.
(Also you need all of the IDs to be unique)
You can use the code below to avoid scrolling:
linktxt
I'm probably missing something, but why not just give them different IDs?
button 1
button 2
Home
Or whatever convention you'd prefer.
Also, preventDefault
$(your-selector).click(function (event) {
event.preventDefault();
//rest of your code here
}
I found the solution. Here I save an old location from calling href
and restore it after scrolling
<script language="JavaScript" type="text/javascript">
<!--
function keepLocation(oldOffset) {
if (window.pageYOffset!= null){
st=oldOffset;
}
if (document.body.scrollWidth!= null){
st=oldOffset;
}
setTimeout('window.scrollTo(0,st)',10);
}
//-->
</script>
and in body of page
<a href="#tab1" onclick="keepLocation(window.pageYOffset);" >Item</a>
Thanks to sitepoint
An easier way would probably be to add it as a GET. That is, http://example.com/foo.php?q=#button1 instead of http://example.com/foo.php#button1
This won't have any effect on how the page is displayed (unless you want it to), and most scripting languages already have tools in place to easily (and safely) read the data.
Well here we are 7 years after this answer was published and I found a different way to make it work: just point the window.location.hash to a non-existent anchor! It doesn't work for <a>s but works perfectly in <div>s.
<div onclick="window.location.hash = '#NonExistentAnchor';">button 1</div>
Worked fine in Chrome 56, Firefox 52 and Edge (IE?) 38. Another good point is that this doesn't produce any console errors or warnings.
Hope it helps somebody besides me.
There is a solution without any JavaScript at all:
I will not jump to the top
Use
button 1
where
function setHash(hash) {
event.preventDefault();
history.pushState(null, null, "#"+hash);
}
event.preventDefault() stops browser from what it normally would do on clicking, and history.pushState adds to the sessions history stack.
For further discussion, see here and here

How to bring focus to a window in jquery?

I am trying to bring focus to window using jquery. The window is popup initiated through a button click on the parent page. I have some ajax calls going on in the child window, so data is being updated. My issue is that if the user clicks on the parent window and hides the child behind it, i would like to bring that child window back to the forefront if there is a data update.
inside $(document).ready I wire up these events:
$(window).blur(function(){
WindowHasFocus =false;
}).focus(function(){
WindowHasFocus =true;
});
Then, if data is updated, I call this function:
function FocusInput(){
if(!WindowHasFocus){
$(window).focus();
}
}
This works as expected in IE8, but in FireFox(and all other browsers) the Blur event nevers seem to fire if I click the parent window. Any suggestions/ideas on how achieve this?
update:
Total facepalm moment:
In FireFox:
* Tools
* Options…
* Content tab
* Advanced button next to “Enable JavaScript”
* check the box named "Raise or Lower Windows"
Total facepalm moment: In FireFox:
Tools
Options…
Content tab
Advanced button next to “Enable JavaScript”
check the box named "Raise or Lower Windows"
This is turned off by default and must be enabled. And also, i assumed that since it didnt work in Chrome, that Safari would be the same, but you know what they say about "assuming" (it works in Safari, but not Chrome).
If there is not a strong reason for having two separate windows then it would be better use "modal boxes", there are plenty of examples out there and jquery plugins to achieve that. An example of such a plugin:
http://www.84bytes.com/2008/06/02/jquery-modal-dialog-boxes/
You're absolutely correct. In FF, it seems as though it does fire the event, but at that same time, it seems like it doesn't register the element as being focused. Therefore the blur event can never be fired. Not sure I'm even explaining that correctly... The following code says it all.
In this example, the box is hidden by default, but is displayed via the focus event listener. In IE 8, if you click the main window, it still fires blur, but in FF it doesn't:
<html>
<head>
</head>
<body>
<div id="hiddenWin" style="width: 100px; height: 100px; background-color: Black; display: none;"></div>
<script type="text/javascript" src="http://jqueryjs.googlecode.com/files/jquery-1.3.2.min.js"></script>
<script type="text/javascript">
var something = 12;
something += 4;
$(document).ready(function()
{
$("#hiddenWin").focus(function()
{
$(this).show();
}
).blur(function()
{
$(this).hide();
}
)
$("#hiddenWin").focus();
}
);
</script>
</body>
</html>
For your need, would it be feasible to setup an overlay background? Something that is a fixed position # top:0 and left:0 which takes up the whole screen and has a z-index that is less than your popup. That way, when they click the overlay, it will steal focus and then you can hide everything...? IDK, just a suggestion. I'll keep messing around and see if I can figure it out. Good question. +1
It seems like you shouldn't care to know when your window got blurred. When your data updates, your window is either not in focus, in which case you want to focus it, or it is already in focus, and focusing it again doesn't hurt you any.
Yeah the modal thing is probably the way to go but sometimes you just need to do it the way you want to do it.
I would use plain old JavaScript. Name the window and the bring it into focus.
function showImageWindow(imageURL)
{
var imageWindow = window.open(imageURL,"My_Window","width=1000px,height=1000px,menubar=0,titlebar=0,toolbar=0,location=0,scrollbars=0,status=0");
imageWindow.focus();
}

Categories

Resources