rules for "prevent this page from creating additional dialogs" - javascript

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.

Related

a11y & angularjs - windows screen reader overrides keydown event

im working on making a photo gallery app more accessible.
the app has a feature of showing expanded view of an image when clicked.
one of the a11y requirements is that when a user focus an image and click enter the expand mode will open and the focus will go inside the expanded view, and will be set on one of the buttons in it. it work's fine without screen reader, or with screen reader on mac. but on windows
when using screen reader it seems that the code that fires is the one that subscribed to the click event and not the keydown event. because the flag that suppose to be set to true on keydown is false (both events fire the same function but the keydown also add the enterClicked variable set to true).
this is the div that hold the image and subscribed to the events:
<div
tabindex="0"
id="{{media.id}}"
data-ng-repeat="media in row track by media.id"
data-ng-mouseenter="events.toggleVideoPlay(media.type, media.id, media.link, ( rowNummer ) * (row.length) + ($index + 1))" class="imgContainer"
ng-keydown="$event.keyCode == 13 ? events.openExpandMode(media.id, true) : null"
data-ng-click="events.openExpandMode(media.id)"
>
openExpandMode function:
$scope.events.openExpandMode = (mediaId, isEnterClicked) => {
const state = {
isEnterClicked,
mediasId,
currentIndex,
pagination: $scope.mediasPagination,
settings: {
isUserName: $scope.settings.user_name_checkbox,
isTemplate: !$scope.userConnected && !$scope.userConnectedWithOldApi,
isLikeComments: $scope.settings.like_comments_checkbox,
isDescriptions: $scope.settings.description_checkbox,
isComments: $scope.settings.comments_checkbox,
theme: $scope.settings.expand_theme,
lang: $translate.use()
}
};
localStorageService.set('state', state);
}
expand mode component init:
const _init = () => {
if ($scope.isOpenFromEnter) {
document.getElementById('nextArrow').setAttribute('data-focus-visible-added', "");
document.getElementById('nextArrow').className += ' focus-visible';
document.getElementById('nextArrow').focus();
}
}
is there a way to stop windows screen reader event interception ?
Short answer
It's common to send a click event instead of a press enter event.
The best is probably to adapt your code so that click and enter do the same thing, and that either or both event can be sent, because
you only have a quite limited influence on which is sent or not and when
Longer answer
You haven't indicated which screen reader you were using (Jaws or NVDA), but anyway, it's common for both to send a click event when pressing enter, instead of sending key events.
Reasons for that may seem strange and illogical at first, but there are at least two good ones:
It's certainly as much illogical to have two different things happening when clicking or pressing enter. IN all applications since GUI exist, most often, both do the same action (the only exception I can think of right now is multiline or rich text fields).
Scren readers existed before web accessibility, and accessibility is still rarely implemented nowadays. Sending a click event when pressing enter provide a minimal usability in all the places where designers didn't even thought that the keyboard could be used instead of the mouse.
By the way, screen reader or not, guess which event is sent if you press enter when the focus is on a link or a button?
Depending on the browser, the answer isn't unanimous as far as I know.
And on the screen reader side, it isn't unanimous either. Some even allow to configure the exact behavior to take, in order to adapt to different more or less unaccessible sites.
is there a way to stop windows screen reader event interception ?
You can stop some form of interception by calling preventDefault in your event listener function, if the click event is generated by the browser.
By doing so, you can actually do something different on click and on enter. But ask yourself first if it is really justified. Think about my first point above.
However, you can't prevent screen readers from intercepting keyboard events, translate them to something else and send or don't send them to your page.
There exists the ARIA application mode, but it has several important implications, so you shouldn't use it unless you have true good reasons.
To wrap up, the best is probably to adapt your code so that click and enter do the same thing, and that either or both event can be sent.
adding role="application" to the container div fixed it.

Bootstrap v4 .modal("show") slow execution

I've noticed that bootstrap's modals take time to show as the page's content becomes more significant.
It takes less than 100ms to show when the page is empty, but takes proportionally more time as the amount of content in the page becomes more significant.
I do not understand this correlation. Can anybody explain this behavior and suggest a workaround to make the modals appearance faster independently of the page's size ?
EDIT: You can reproduce the behavior by going i.e here and execute the command
console.time("modalTime"); $("#exampleModal").modal("show"); console.timeEnd("modalTime");
in console, to see how much time it takes. Then add more content to the page by manipulating the DOM and re-execute the command.
My results: modalTime : 70 ms on the original page. modalTime : 1208 ms after making the content of the page 10x larger.
Ok, I am able to reproduce a delay if I add 50.000 lines of text to the document:
https://plnkr.co/edit/hvRAn3wg91GBCPxK2gwb?p=preview
The problem with a huge DOM like this is, that any manipulation will take long.
It might be a problem of jQuery, but I doubt.
To prove that the delay has nothing to do with the Modal, I am painting the button to red when clicking it - even this simple action takes as long as opening the modal window.
jQuery(document).ready(function() {
for (var i = 0; i < 50000; i++) {
$( "#content" ).append( "This is just some test. This is just some test. This is just some test. This is just some test. This is just some test. This is just some test. This is just some test. This is just some test. This is just some test. <br/>" );
}
$("#btnToggleMoadal").click(function(e) {
$("#exampleModal").modal("show");
$(this).css({backgroundColor:"red"});
});
});
Edit: I have also tested jQuery's onClick vs onClick out of the DOM - but there is no difference. https://plnkr.co/edit/483Sk2FGXk9lT8dLZIdo?p=info
Edit: I have to correct my answer. It's definitely the Bootstrap Modal which causes the performance issue. I think the problem is somewhere around _adjustDialog() in modal.js.
I recommend to open an issue at https://github.com/twbs/bootstrap/issues and show the Plunker example.

Can anyone explain why focus() is not working always on IE 10?

I have the following code, which works 100% ok on Chrome and Safari, but on IE 10 sometimes works and sometimes don't.
Sys.Focus = function(obj){
if(Sys.Anim.length>0){
Sys.Fp = obj;
return;
}
obj.focus();
}
.
.
.
function Animate(...){
var i,...
.
.
.
if(Finished(Sys.Anim[i])){
Sys.Anim.splice(i,1);
if(Sys.Anim.length==0){
if(Sys.Fp){
Sys.Focus(Sys.Fp)
Sys.Fp = null;
}
}
}
.
.
.
}
.
.
.
email = document.getElementById("email");
Sys.Focus(email);
email.onkeydown = function(){
debugger
.
.
.
}
In response to different user actions, some objects on screen either change color or move around, this is done by Animate(), objects to be animated are added to an Array (Sys.Anim) and removed when the animation ends. In order to keep everything smooth, if the page becomes ready for input before the animation ends (which almost always happens), the focus() call is delayed until the animation ends, that is about 1/3 of a second.
Everything works just as expected in all browsers except IE 10. At first I thought there was a logic error on my code, however I debugged it with the Developer Tools and I discovered all the steps are carried on correctly, the problem is that focus() is not actually working all the times.
Another important detail... when focus() succeeds email.onkeydown is executed every time I hit a key, however when focus() fails I obviously must click on the input control to focus it manually, but when this happens the email.onkeydown function is never called even when the content of the input control is updated with every key punch.
I tryed:
setTimeout(function(){obj.focus()},100);
which was proposed as a solution for this problem, but it doesn't solve mine.
Why this happens and how can be worked around?
UPDATE:
For testing proposes I added the following function:
email.onfocus = function(){
debugger
}
which brings the debugger only when focus() succeeds, if focus() fails the debugger won't pop up even if you focus the input control manually with a mouse click, because in this case I simply cannot focus the input control by using the Tab or Shift-Tab keys... is just as if it didn't exist!!!
Solved!!!
After lots of frustrating tests I discovered that the input control was nested inside a DIV which in some circumstances was disabled, dumb of me to disable a DIV.
...However all other browsers only actually disable the input control if it is explicitly disabled. The guys at Microsoft always trying to be "too clever" decided to take a conterintuitive approach and leave it half done.
The problem and my complaint is that the input control does not look disabled, it looks normal and the caret actually appears if you click on it, you can even type on it no matter how disabled it was supposed to be... so for the record, always remember IE 10 only half disables input controls which are inside disabled DIV giving you no visual clue of what's going on.

What is best way to make sure alert box doesnt pop up if an alert is already there?

In javascript, if I have an infinite loop:
setInterval("popalert", 5000)
Where popalert() simply pops an alert box, what is the best way to make it such that an alert box does not pop up if there is already a single alert box that has not been closed yet?
There is no way to detect that the alert is there.
Do not use setInterval, use setTimeout.
Reset the timeout after the alert happens.
jsfiddle example
It's impossible to detect the standard javascript alert boxes as they are extremely simple. If you keep spawning them they will just queue and in modern browsers it actually gives you the option to suppress them for a certain page after a few.
I would consider using a different type notification system if having no more than 1 box at any time is important to you. Something like jQuery UI Dialog.
The popalert function could save the state of the alert box.
var bOpen = false;
then when its poped up set it true
and if it closes after pushing ok or something set it false again.
when popalert is called again it checks the bOpen var and if its true, it just doesn't open a new popup.
also I would use settimeout, so you don't get this endless loop stuff blocking your gui.
You can't detect if an alert box is already here.
Your navigator manage this alert box, so they can't popup if another is already here.
You can use a global javascript variable (out of any function) and set this var initially to false. If your popalert function is called, check if the global var is false. If so, pop your alert and set the var to true. Doing this only one alert will be shown, but your function will be executed again and again (if this is important).

How can I control the action of onbeforeunload in IE?

I've got a problem about onbeforeunload recently that I need to pop up a voting page when users try to close their IE browsers.I did it by using:
<body onbeforeunload="makevote()">
And the main structure of makevote() in javascript is as follows:
function makevote()
{
comet.distruct();
if(csid != null && isvote == null)
{
window.event.returnValue = false
window.event.returnValue='press “cancel” to vote please!'
showComDiv(popvote,"popiframe",400,120,'your vote here','dovote()');
}
}
In last three months this voting function performed so ugly that I got only less than 8,000 votes from more than 4,50,000 vistors.I think the problem is, when the users try to close their browsers,the onbeforeunload property pops up a comfirm box which covered my voting box while most users click the OK button,which means close comfirming is done,as a habit.So my question is how can I control the comfirming box made by onbeforeunload myself? For example if I click the "OK" ,I'll go to the voting box instead of closing my IE.So far what I can do is only defining the message it shows.And is there any other better way to do this?Help would be greatly appreciated!
Regards
Quite simply, you can't.
This is built-in behaviour, designed to only allow very minimal changes for security purposes. It's the same in every browser; FF, Chrome, etc, all will behave the same way.
The primary purpose for the beforeunload is for things like allowing the users the option to save changes before their changes are lost.
Besides, if your users are leaving, it's already too late - they won't want to answer a survey anymore, they're done!

Categories

Resources