Document.body.removeChild() only removes modal when in debugging mode - javascript

I have attached a keydown listener in the constructor of my class like
constructor(props: DropDownProps) {
this.wrapper = document.createElement("div");
document.body.appendChild(this.wrapper);
..
this.confirm = this.confirm.bind(this);
this.handleEnterKey = this.handleEnterKey.bind(this);
document.body.addEventListener("keydown", this.handleEnterKey);
}
The attached function, handleEnterKey() checks for the entered keycode and if it is the return key, it calls confirm().
handleEnterKey:
private handleEnterKey(e: any) {
if (e.keyCode === 13) {
this.confirm(e);
}
}
confirm:
private confirm(e: any) {
this.onConfirmIn();
document.body.removeEventListener("keydown", this.handleEnterKey);
document.body.removeChild(this.wrapper);
ConfirmationDialog.isConfirmationDialogOpened = false;
}
Now what is happening is that the modal doesn't vanish and enter needs to be pressed again. It seems the modal doesn't vanish until either:
Enter is pressed the second time
Breakpoint exists (no matter where)
The Modal is clicked upon, and then the enter is pressed
What could be the reason the modal doesn't simply detach itself on the first attempt?

Related

Alert on browser close button but not for every load of the page

I want code to alert the user for closing the close button of the browser, but I am getting alert for every loading or for every refresh and tab change inside the web page.
window.onbeforeunload = function (event) {
var message = 'Sure you want to leave?';
if (typeof event == 'undefined') {
event = window.event;
}
if (event) {
event.returnValue = message;
}
return message;
}
You have to save the alert box state anywhere, so that you can check, if the user has seen it once. You could save the state of your alert box for example in a local storage. I changed the code.
First on the onload event, check if there's a localStorage Item "showConfirmation". If not, create one with the string value "true", otherwise just log the value.
Second, on beforeclose it checks if the item has the value "true". If so, return a string to show the alert message.
Third, on window.close you set the item to string "false", the message will not be shown anymore.
window.onload = checkLocalStorage;
window.onbeforeunload = askForClose;
window.unload = checkLocalStorage;
function checkLocalStorage() {
if (localStorage.getItem("showConfirmation") === null) {
localStorage.setItem("showConfirmation", "true");
} else {
console.log(localStorage.getItem("showConfirmation"));
}
}
function askForClose() {
var showConfirmation = localStorage.getItem("showConfirmation");
if (showConfirmation === "true") {
localStorage.setItem("showConfirmation", "false");
return "You really want to close?";
}
}

Typescript keyboard listener prevents typing into HTML input forms

I'm developing a web application with Angular2, with one component needing to listen to the keyboard to check if the 'D' key is pressed. This works fine, except that it's preventing me from typing into a HTML <input> which resides in another component. I'm guessing it's caused by some piece of code in the keyboard listener class, but I'm not sure where.
Here is the listener class in it's entirety:
export class Keyboard {
private keyboard_d;
constructor(){
this.keyboard_d = Keyboard.keyboard(68);
}
static keyboard(keyCode){
var key = {
code: keyCode,
isDown: false,
isUp: true,
press: undefined,
release: undefined,
downHandler: function(event){
if (event.keyCode === key.code) {
if (key.isUp && key.press) key.press();
key.isDown = true;
key.isUp = false;
}
event.preventDefault();
},
upHandler: function(event) {
if (event.keyCode === key.code) {
if (key.isDown && key.release) key.release();
key.isDown = false;
key.isUp = true;
}
event.preventDefault();
}
}
//Attach event listeners...
window.addEventListener(
"keydown", key.downHandler.bind(key), false
);
window.addEventListener(
"keyup", key.upHandler.bind(key), false
);
return key;
}
//Returns true if the D key is pressed down, false if it is not.
public isDpressed(){
return this.keyboard_d.isDown;
}
}
This class is used in the Angular2 component like this:
var keyboard_listener = new Keyboard(); //create
var dPressed : boolean = keyboard_listener.isDPressed();
Where in this code is it preventing me from typing into HTML input forms?
Note I've purposely left out the angular code of the two relevant components because I don't want to add the angular2 tag if I don't need to, my intuition says the code above is the problem. But if it's deemed necessary I'll edit the post and add the angular code and tag.
The call of event.preventDefault stops the default behaviour of that event and as a result the character is not shown in the input field.

Capturing Tabbed Focus/Blur properly

So for accessibility purposes I am trying to captured tabbed focus and blur events to capture tab order within a modal.
For some reason I am running into some odd browser behavior.
Inside my component I have the following code:
// On Init
ngOnInit (){
// Get all of the buttons and anchors in the modal
var buttons = this.modal.nativeElement.querySelectorAll("button, a");
// Get the number of buttons
var numButtons = buttons.length;
// Get the last button
var lastButton = buttons[numButtons - 1];
// When the last button loses focus
lastButton.addEventListener("blur", (e: any) => {
// Prevent Default
e.preventDefault();
// Focus on the modals close button
this.focusCloseButton();
})
}
And TECHNICALLY this works perfectly. If I log out the active element after the call to this.focusCloseButton, I indeed get a reference to the close button.
HOWEVER, the tab actually moves to the browser itself into whatever the first element is. For Chrome this is the "View site information" button to the left of the URL bar. In Firefox this is the first tab in the list of tabs.
How can I capture this properly so that the browser is not hijacking the tab press?
Apparently the blur event happens too late to be captured before the browser takes over.
Instead I used keybinding to detect when the tab-key was pressed and did the capturing from there.
// The OnInit function handles capturing tab order
ngOnInit (){
// All of the buttons and links in the modal
var buttons = this.modal.nativeElement.querySelectorAll("button, a");
// The first button or link in the modal
var firstButton = buttons[0];
// The last button or link in the modal
var lastButton = buttons[buttons.length - 1];
// Listen for keydown events on the modal
this.modal.nativeElement.addEventListener("keydown", (e: any)=> {
// If the key pressed was the tab button
if ( e.keyCode === 9 && !e.shiftKey ) {
// If the currently active element is the last button
if (document.activeElement == lastButton){
// Prevent default action
e.preventDefault();
// Put focus on the close button
this.focusCloseButton();
}
} else if ( e.keyCode === 9 && e.shiftKey === true ){
// If the key pressed was shift+tab
// And the currently active button is the close button
if ( document.activeElement == firstButton ){
// Prevent Default
e.preventDefault();
// Focus the last button
lastButton.focus();
}
}
})
}
for those wondering about what this.focusCloseButton does:
// Puts focus on the close button
focusCloseButton: Function = function(){
this.closeButton.nativeElement.focus();
};
The reference to closeButton is created by ViewChild:
// Reference to the close button
#ViewChild("closeButton") closeButton: ElementRef;
Which ties into the dom with the marked element:
<button #closeButton></button>

Use a preventdefault to get out of the loop after pressing Enter key

This is a complete revision of my initial question, all unnecessary resources and references were deleted
I am tying the same event listener to 2 different elements: a button and Enter key, and it looks like the following:
var funcelement = function(){
//function code
};
$('#buttonID').click(funcelement);
$('#inputID').keyup(function () {
if (event.which == 13) {
$('#buttonID').trigger('click');
}
})
What I am trying to do is to prevent propagation of the enter key press if focus is on the submit button(#buttonID) by using preventDefault().
So I tried various combinations to make it work. The following is the latest result on my attempts
$('#inputID').keyup(function () {
var hasfocus = $('#buttonID').is(':focus') || false;
if (event.which == 13) {
if (!hasfocus) {
event.preventDefault();
$('#buttonID').trigger('click');
//hasfocus = true;
}
else {
//event.preventDefault();
//$('#buttonID').trigger('click');
}
}
})
After I enter a text into an input box and press Enter key, a confirmation window with yes/cancel buttons pops up with focus on yes button. Once I press Enter again, another window confirming that changes were made pops up with Ok button focused on it. Once I press Enter again, everything I need is being made.
However, there is one problem: after the last step is done, I am going back to the if (!hasfocus) line.
How do I prevent that from happening? Once the stuff I need is done - I don't want to go into that line again.
You can pass a parameter to into the function and stop the propagation there like so:
var funcelement = function(event, wasTriggeredByEnterKey){
if (wasTriggeredByEnterKey && $('#buttonID').is(':focus')) {
event.stopPropagation;
}
//function code
};
$('#buttonID').click(funcelement);
$('#inputID').keyup(function () {
if (event.which == 13) {
$('#buttonID').trigger('click', [true]);
}
}
)
UPDATE
In order to answer your revised issue, you should use the "keydown" event rather than "keyup" when working with alerts. This is because alerts close with the "keydown" event but then you are still triggering the "keyup" event when you release the enter key. Simply change the one word like this:
$('#inputID').keydown(function () {
var hasfocus = $('#buttonID').is(':focus') || false;
if (event.which == 13) {
if (!hasfocus) {
event.preventDefault();
$('#buttonID').trigger('click');
//hasfocus = true;
}
else {
//event.preventDefault();
//$('#buttonID').trigger('click');
}
}
})

Why is tab keypress causing focus change also triggering keyup event?

Pressing the tab key which triggers a focus change is also received by the input receiving the focus as a keyup.
a: <input type='text'/><br/>
b: <input type='text' onkeyup='alert("wtf?")'/><br/>
http://jsfiddle.net/59SnP/
As my control also uses tab (not in the example), I would want the focus related keyup event being consumed (but I want to receive other non-focus-change related tab events). I tried to research the rationale behind the current behavior but found nothing. The question: Where is this current behavior specified (event not consumed by focus change), and what would be a cross-browser workaround to force consuming it. Thx.
You can try this. I changed your keyup event in your input :
<input type='text' onkeyup="if(!tabPressed){ alert('This is it !'); }"/>
And I added a little event handler which will raise a flag when the tab button is pressed :
var tabPressed = false;
document.addEventListener('keydown', function (e) {
if(e.keyCode == 9) {
tabPressed = true;
} else {
tabPressed = false;
}
}, false);
Based on Nathan's insight, here is a fully working example:
// First part of Nathan's HACK (set a sentinel when a focus changing tab has happened)
var tabPressed = false;
// remove this listener to break the functionality
$(document).on("keydown", function (e) {
if(e.keyCode == 9) {
tabPressed = true;
} else {
tabPressed = false;
}
});
// The listener on the client input that would kill the keyup tab event upon focus change
$("#magic").on("keyup", function(e) {
if (tabPressed && e.keyCode==9) {
tabPressed = false; // reset the sentinel
e.stopImmediatePropagation()
e.preventDefault()
}
})
And here is the second part, which is a simple skeleton of something meaningful. We disable TAB inside the input, and log it as we do with other keyups:
$("#magic").on("keydown", function(e) {
if (e.keyCode==9) {
e.preventDefault()
e.stopPropagation()
}
})
$("#magic").on("keyup", function(e) {
$(this).val($(this).val() + " " + e.keyCode)
e.stopPropagation()
e.preventDefault()
})
The HTML backing the story is as simple as:
a: <input type='text'/><br/>
b: <input type='text'/><br/>
c: <input type='text' id='magic'/><br/>
If you want to play with it, here it is on jsfiddle
NOTE: This still is not the perfect solution, the sentinel is just reset inside the control, so if a tabpress moving the focus does not activate our input, the sentinel stucks, and the first event will be swallowed.. So here is an example of wrong behaviour:
Click on input A
Press TAB (focus moves to input B, tabPressed becomes true)
Click on input C
Press TAB (it is eaten up as sentinel is true)
Press TAB (now it goes through)
Still it is slightly better to have to press TAB twice as to have something happening automatically, wo user control...

Categories

Resources