Returning focus, contenteditable misses keypress event - javascript

Story
In a custom content editor component (contenteditable div), in which I need to prevent certain character inputs. If the user tries to input a restricted character, a bootstrap modal dialog is shown explaining the restriciton ("You are not allowed to use 'x') and the event is prevented (preventDefault). After dismissing the dialog, the focus goes back to the contenteditable and input can resume.
Issue/Bug?
After dismissing the dialog, the focus is indeed returned to the contenteditable. However, the first key event doesn't trigger keypress on the contenteditable bypassing the keypress event listener.
I tried setting manually the focus and setting the document selection explicitly on the contenteditable, with no luck. I've tried both with jquery and pure js.
Any ideas why is the first event bypassing the keypress listener?
Illustration
JSFiddle here, example restricting "." input:
<div id="testMe" contenteditable="true" class="form-control"></div>
<div id="myModal" class="modal fade">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-body">
<p> You are not allowed to use this character.</p>
<p> Press OK to dismiss.</p>
</div>
<div class="modal-footer">
<button id="closeAlert" type="button" class="btn btn-danger">OK</button>
</div>
</div>
</div>
</div>
$("#testMe").keypress(function(event) {
console.log("key pressed");
if (String.fromCharCode(event.which) == ".") {
event.preventDefault();
$('#myModal').modal('show');
}
});
$("#closeAlert").click(function() {
$('#myModal').modal('hide');
});
Click inside the contenteditable
Press "." character (no input appears and a "keypress" message is printed to the console).
Dismiss the dialog
Press "." character again (the input appears and no keypresssmessage appears in the console log).

It turns out that the problem was in setting back the focus of the element. Adding
$("#testMe").focus();
after hiding the modal fixes it.
I had originally used the bootbox library for showing modals. For unclear reasons, setting focus immediately after the dialog close callback doesn't work with it.

Related

Method not called on blur event applied to span element

I would like the following method to be run:
setHeroButtonTextOption(heroButtonText) {
this.builderComponentsService.setPageComponentById(this.componentId, 'heroButtonText', heroButtonText);
}
Each time the user loses focus of the following element:
<div class="builder-components hero-button-click button-outer-container text-center text-md-left mt-5">
<div (click)="selectHeroButton($event, componentId + '-button')"
[attr.data-cy]="'hero-button-container'" [class]="setActiveElement('button')"
[ngClass]="setHeroClass('hero-button')" class="builder-components hero-button-click button-container"
id="{{componentId}}-button" style="display:inline-block">
<button [attr.data-cy]="'hero-button'" [ngStyle]="heroButtonStyle"
class="builder-components hero-button-click btn hero-button">
<span (blur)="removeLineBreaks($event); setHeroButtonTextOption($event.target['innerText']);"
(keydown.enter)="setHeroButtonTextOption($event.target['innerText']); $event.preventDefault()"
[attr.contenteditable]="setContentEditable()" [attr.data-cy]="'hero-button-text'"
[innerText]="heroButtonText" class="builder-components hero-button-click">
</span>
</button>
</div>
</div>
Currently, it isn't happening even though I have a blur event on <span>. How can I fix this?
The blur event will be raised from the button, not the span. If you are trying to include the innerText of the span with the event handler, it looks like it is already bound with heroButtonText, which you can pass as a function argument or reference from the component.
<button (blur)="setHeroButtonTextOption(heroButtonText)">
<span>{{ heroButtonText }}</span>
</button>
Edit - The button should be emitting that blur event. If that isn't working you will need to post more code, it could be that removeLineBreaks($event) is throwing an error, preventing the next call from being made.

How to prevent modal click-through?

I have a modal that looks something like this:
<div className="modal modal-focuser" tabindex="1" style="z-index: 5;">
<div className="handle-modal-close"></div>
<div className="modal-content modal-content">
<div className="body">
<span>
<div className="container">
<div className="title-text">Title Text</div>
<div className="body-text">Body Text</div>
</div>
<button onClick={this.toggleView} className="toggle-view">Switch View</button>
</span>
</div>
</div>
</div>
With the click code like the following:
toggleView = e => {
e.stopPropagation();
this.setState(prevState => ({ view: !prevState.view}));
}
But for some reason (despite the stop propagation), when I click the button, sometimes the parent's event handlers are still being activated.
That is, there is a table behind the modal with click-able rows, and when I click the Toggle button in the modal, not only is that button clicked, but also the table row behind the behind (which also has its own click event handlers)
The stranger thing is that this only sometimes happens, and only happens on mobile. Try as I might, I can't replicate the behavior on my PC in Chrome or Firefox.
What could be causing this?
You're using the onclick handler, which essentially ignores all the propegation through down-up events. Try using onmousedown. Chances are the thing underneath the modal has a down or up event. Learn about "bubbling" : What is event bubbling and capturing?
<button onMouseDown={this.toggleView} ... yada yada
Using the mousedown will allow you to prevent bubbling through the stopPropegation, and maybe also look into stopImmediatePropegation -- which prevents other listeners of the same type (click, down, up) from getting called: https://developer.mozilla.org/en-US/docs/Web/API/Event/stopImmediatePropagation

How to make click only on modal exterior and not on dialog/content?

So I'm making an extension for Google Chrome with my friend, and for most of the features (i.e. calendar, settings, etc.) we open a modal so we don't have to redirect to another page. We are trying to get the modal to close when you click outside of the content. Here's a little markup screenshot to give you an idea of what I'm talking about.
I want to be able to close the modal by clicking outside the white area. Currently it closes even when I click inside the white area. I have tried pretty much everything, including stopPropagation(), pointer-events:none;, and jquery disabling. None of them work for reasons unknown to me. Something weird about Chrome Extensions, I guess.
Here's some of my code so far:
function calendar() {
document.getElementById("calendmodal").style.display = "block";
}
document.addEventListener("DOMContentLoaded", function () {
document.getElementById("calendicon").addEventListener("click", calendar);
document.getElementById("calendmodal").addEventListener("click", closeModal);
document.getElementById("calendmodal").addEventListener("click", function(event) {
event.stopPropagation();
});
});
And HTML:
<div class="icons" id="icons_calendar">
<img src='https://preview.ibb.co/jE76Bm/calendar.png' alt="calendar" border="0" id="calendicon"/>
</div>
<div id=calendmodal class="generalmodal">
<div class="modal-content" id="calendcontent">
<iframe src="https://calendar.google.com/calendar/embed?src=googleapps.wrdsb.ca_ptpdj55efmhg1nb89ruc15fi3k%40group.calendar.google.com&ctz=America%2FToronto" style="border: 0" width="800" height="600" frameborder="0" scrolling="no" visibility="hidden" id="calendiframe"></iframe>
<p id=infostuff>For a more extensive calendar and<br>more school tools, visit The SJAM Website.</p>
</div>
</div>
Not really sure what I'm doing wrong, I don't know how to do this in an extension.
I don't know exactly how you show your modal dialog, but my approach for this issue is like this (you may be able to adapt it ot your particular case):
I have a transparent <div> as container that takes up the whole screen, and inside it, using CSS, I position the modal dialog. Something like:
<div id="container" style="position:fixed;top:0;bottom:0;left:0;right:0;display:none">
<div id="myModal" style="position:absolute;width:300px;height:200px;left:100px;top:100px">
<!-- Here goes my content -->
</div>
</div>
With this approach, to display the dialog I do something like:
function openModal(){
document.getElementById("container").style.display = "block";
}
And to close it when clicked on the transparent background but not on the dialog I have:
document.getElementById("container").onclick = function(event) {
if (event.target === this) {
this.style.display = "none";
}
};
In your earlier attempts, where did you execute event.stopPropagation()? It's not included in your code example.
What you need to do is prevent a click event on #calendmodal from bubbling up the DOM and triggering a click event on the body (or another container element) whose event handler closes your modal dialog.
You can do so like this:
document.getElementById("calendmodal").addEventListener("click", function(event) {
event.stopPropagation();
});

Jquery mobile button click at corner not working

I created a mobile app using cordova and jQuery mobile as the UI framework. It is working fine, except that the click event on the jQuery mobile buttons does not trigger when clicking on the corners. I see a hover effect (button color change) when clicking at corner, but click event not triggered. Click event is triggered when clicked a little inside from button corner.
I am using jQuery mobile 1.4.2. Below is my button (anchor tag with class showOptions and ui-btn) markup and click handler:
<div data-role="header" data-theme="b" data-position="fixed" data-tap-toggle="false">
<img src="images/logo_small.png" class="appLogoImg dontDisplay ui-btn-left" style="margin-top: 6px;" />
<h1 class="ui-title">All Packages</h1>
<div class="ui-controlgroup ui-controlgroup-horizontal ui-btn-right">
Options
</div>
</div>
$('.showOptions').on('click', function() {
console.log('button clicked');
return false;
});
Is anybody out there also facing same issue? Please help me.
Instead of using <button> or <input type="submit">, it's better to use <a> (like you) with data-role="button" attribute.
Options
Anchors with data-role=button dont get wrapped with a .ui-btn div. Hence, you have will have the whole button responsive to any event.

Modifying a page from JQM dialog

What I'd like to achieve is a page that has a couple of buttons inside a div. When the user presses one of these buttons a dialog opens, asking follow up questions. After this the user is returned to the same page but the div with the buttons is hidden.
What I've tried is the following, inside a JQM page i have div called buttons which contains the buttons(logically). this opens the dialog and also calls a function which saves to local storage which button was pressed. Then the dialog opens which actually sends the data to the server.
For some reason the div is never hidden when I return from the dialog. I even tried to save a variable to the sessionStorage and hide the div on pageload, but seems that the page load event does not fire when returning from the dialog. Any suggestions or am I missing something basic?
<div class="ui-grid-b" id="buttons">
<div class="ui-block-a"></div>
<div class="ui-block-b"></div>
<div class="ui-block-c"></div>
</div><!-- /grid-b -->
// the dialog:
<div data-role="dialog" id="Popup" data-overlay-theme="b" data-theme="a" class="ui-corner-all">
<form>
<div style="padding:10px 20px;">
<h3>Heading</h3>
<textarea name="comments" id="popuptextarea"></textarea>
<button type="submit" data-theme="b" onClick="save()">Selvä</button>
</div>
</form>
</div>
I have two javascript functions which try to save the data and also hide the div,
function savePushedButton(color) {
//save which button was pressed to local storage
$('#buttons').hide();
console.log("asd");
}
function save() {
//send data to server
}
onclick is your problem (onchange also), do not use it with jQuery Mobile. jQuery Mobile has already started transition to the dialog, before onclick has been triggered. You will need to manually bind a click event to the button and hide buttons before transition to dialog can occur.
Here's a working example: http://jsfiddle.net/Gajotres/uhsfs/
$(document).on('pagebeforeshow', '#index', function(){
$(document).on('click', '#test-button', function(){
$('#buttons').hide();
savePushedButton($(this).attr('data-color'));
});
});
function savePushedButton(color) {
console.log(color);
$.mobile.changePage('#Popup', {transition: 'pop', role: 'dialog'});
}

Categories

Resources