Unwanted Multiple KeyDown Events triggered on single keydown - javascript

So basically what I need to do is detect a keydown event of spacebar and hence perform some logic based on it in my javascript file.
So as you can see in my html, that there is a button "compose" on clicking which the message-container is displayed.
Now I need to implement Gmail like feature of converting the mail ids in recipients as tags but in my case a valid mail-id will be converted to a tag as soon as a space-bar is pressed, i.e, the string before the space bar will be checked for valid email-id.
So i've written the on-click function of the recipient container and the keydown function for spacebar.
Now here comes the problem. When the page is loaded for the first time, it works perfectly fine. I click inside the recipient box and as soon as i hit space bar, "spacebar pressed" gets printed on the browser console one time for one key down.
Now if I hide this message-container div by clicking the "close" button, and then again show the message-container div by clicking the "compose" button, and then when i click in the recipients box, it fires two keydown events for spacebar i.e., "spacebar pressed" will be printed twice.
And consequently, if i again close and reopen the box and click again, it will print "spacebar pressed" three times for every keydown of spacebar.
So is it something related to binding and unbinding of events or something else? Coz i have gone through similar links in which the key down event was getting binding again and again, but could really figure out how I would like kill the event on clicking of "close" button.
Here is html:
<!DOCTYPE html>
<html>
<head>
<title>ZMail</title>
<link rel="stylesheet" type="text/css" href="css/fonts.css" />
<link rel="stylesheet" type="text/css" href="css/main.css" />
<script type="text/javascript" src="js/jquery.min.js"></script>
<script type="text/javascript" src="js/jquery-ui.min.js"></script>
<script type="text/javascript" src="js/jquery.validate.js"></script>
<script type="text/javascript" src="js/main.js"></script>
</head>
<body>
<div class="header">
<h2>ZMail</h2>
</div>
<div class="body-container">
<button type="button" class="compose-button" id="compose-button">Compose</button>
<div class="message-container" id="message-container">
<div class="compose-form-header">
<p> New Message </p>
<button type="button" class="close-button" id="close-button">x</button>
</div>
<form id="compose-form" method="POST" action="">
<div class="recipient-container" id="recipient-container">
<div class="to-box" id="to-box">
<p>To</p>
</div>
<div class="input-elements-container" id="input-elements-container">
<input type="text" id="recipient-box" name="recipients" placeholder="Recipients">
</div>
</div>
<input type="text" id="subject-box" name="subject" placeholder="Subject">
<textarea form="compose-form" id="message-text-box" name="message-text" ></textarea>
<div class="send-button-container">
<button type="submit" class="send-mail-button" id="send-mail-button">Send</button>
</div>
</form>
</div>
</div>
</body>
And here is the JS
var contacts = ['ankush.rgv#gmail.com']
$(document).on('ready', function(){
$("#message-container").hide();
$("#to-box").hide();
$("#compose-button").click(function (event) {
if($("#message-container").is(':hidden')){
$(function() {
$("#recipient-box" ).autocomplete({
source: contacts
});
});
$("#message-container").show();
}
});
$("#close-button").click(function (event) {
$("#message-container").hide();
$("#to-box").hide();
$("#recipient-box").val('');
$("#subject-box").val('');
$("#recipient-box").attr('placeholder', 'Recipients');
$("#subject-box").attr('placeholder', 'Subject');
});
$("#recipient-container").click(function (event) {
console.log("recipients clicked");
$("#to-box").show();
$("#recipient-box").attr('placeholder', '');
$(document).keydown(function(e) {
if (e.keyCode == 32) {
console.log("spacebar pressed!!");
}
});
});
$("#subject-box").click(function (event) {
$(this).attr('placeholder', '');
});
});
Any help will be appreciated.

Everytime you click on #recipient-container, .keydown() will add an extra event handler to the document, without removing the existing ones.
The easiest solution here would be to remove the handler when you click on #close-button. Unbinding events can be done with .off().
$(document).off('keydown');

Related

Javascript removeAttribute style not working properly

I have a simple code in order to hide objects inside a div until a button is pressed.
The code works, but after execute the alert, the code roll back.
I understand there are several options to do the same, but same behavior occurs for others I have attempt (such as https://www.w3schools.com/jsref/prop_style_visibility.asp).
So I have attempt the removeAttribute style because it's easier to watch on Console.
I have attempt to put the script before the form, and after form, but same behavior occurs.
I have add some snapshots from Console in order to demonstrate it, please see below.
I am not sure what am I doing wrong. Tested on Chrome (89.0.4389.114) and Edge (89.0.774.75).
Any help is highly appreciated!
Thank you in advance.
PS. It is running inside a php code (using echo) due it has conditional values.
**PS. It works fine outside a form**
<body>
<form ...
(...)
<div class="field" id="pwdDIV" style="visibility: hidden">
..somocode..
</div>
<button class="button" onclick="showPwd()">Show Password</button>
</form>
<script>
function showPwd() {
var z = document.getElementById('pwdDIV');
alert("Get Style: "+z.style.visibility);
if (z.style.visibility === 'hidden') {
z.removeAttribute("style");
alert("Change to Style: "+"visible");
} else {
(...)
}
}
</script>
</body>
Before Press Show Password button
After press Show Password button - executing alert parameter
After execute Javascript code
Outside form sample (works fine outside forms)
<html>
<head>
<script type="text/javascript">
function showPwd() {
var z = document.getElementById('pwdDIV');
if (z.style.visibility === 'hidden') {
z.removeAttribute("style");
} else {
z.setAttribute("style", "visibility: hidden");
}
}
</script>
</head>
<body>
<button onclick="showPwd()">Show Password</button>
<div id="pwdDIV" style="visibility: hidden">
<input type="password" id="pwd1" name="pwd1">
</div>
</body>
</html>

Code to click outside of element not firing

This is my code:
<div class="titfx">
<div class="clk1">CLICKME</div>
</div>
<div class="here" style="display:none;">info for here</div>
<script src="https://code.jquery.com/jquery-3.3.1.js" integrity="sha256-2Kok7MbOyxpgUVvAk/HJ2jigOSYS2auK4Pfzbm7uH60=" crossorigin="anonymous"></script>
<script>
$(document).ready(function() {
$('.clk1').on("click", function(event) {
//first code
var here = $(this).parent(".titfx").next(".here");
here.toggle();
//second code
if (!here.is(event.target) && here.has(event.target).length === 0) {
here.hide();
}
});
});
</script>
What the first part of javascript code does: When the word "CLICKME" is clicked, then the hidden div with text "info for here" shows.
What the second part of javascript code should do: When any part of the screen that is not class="here" is clicked on, then the text "info for here" should hide. The second part of my code is unable to achieve that. I'm not sure what I'm doing wrong. Please help me fix this issue.
you need to bind two event listeners to achieve this, one for the "clk1" element, and one for the whole page.
when fires document click event, just hide the text,
when fires ".clk1" click element, you need to stop propagation first and then write the toggle behaviour.
this is my solution
$(document).ready(function() {
$('.clk1').on("click", function(event) {
//first code
event.stopPropagation();
$(".here").toggle();
});
//second code
$(document).on("click", function(event){
$(".here").hide();
});
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="titfx">
<div class="clk1">CLICKME</div>
</div>
<div class="here" style="display:none;">info for here</div>
Here is a potential solution. The first click binding works for the toggle logic. However, for your second scenario, you said you want it to close them if they click any where on the page, other than the two areas. In that regard, you are concerned with the click events for the body, not just the two areas.
The second logic binds to the body, and checks to see if the clicked element is a child of the .clk1 or the .here. If it is not a child of either one, it will hide the .here.
The css was added to force the page size to be larger than just the html provided so you could actually click on something not them, :)
$(document).ready(function() {
$('.clk1').on("click", function(event) {
var here = $(this).parent(".titfx").next(".here");
here.toggle();
});
$(document.body).on('click', function(event){
var clickedElement = $(event.target);
if (!clickedElement.closest('.clk1').length
&& !clickedElement.closest('.here').length) {
$('.here').hide();
}
});
});
body {
min-width: 800px;
min-height: 600px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="titfx">
<div class="clk1">CLICKME</div>
</div>
<div class="here" style="display:none;">info for here</div>

preventDefault form submit not working in bootstrap popover

I have a bootstrap popover element with a form inside.
I do a preventDefault() when the form is submitted but it doesn't actually prevent the submit.
When I don't use the popover and a modal instead it works perfectly.
Here is my HTML:
<div class="hide" id="popover-content">
<form action="api/check.php" class="checkform" id="requestacallform" method="get" name="requestacallform">
<div class="form-group">
<div class="input-group">
<input class="form-control" id="domein" name="name" placeholder="domein" type="text">
</div>
</div><input class="btn btn-blue submit" type="submit" value="Aanmelden">
<p class="response"></p>
</form>
</div>
Here is my JavaScript file where I create the popup (main.js)
$('#popover').popover({
html: true,
content: function() {
return $("#popover-content").html();
}
});
And this is where I do my preventDefault() in an other JavaScript file
$(".checkform").submit(function(e) {
e.preventDefault();
var request = $("#domein").val();
$.ajax({
// AJAX content here
});
});
Why the preventDefault() isn't working?
You're trying to append event handler for .checkform before adding it to DOM. You need to load second javascript file after loading contents html or append event globaly:
$("body").on("submit",".checkform", function(e){
e.preventDefault();
var request = $("#domein").val();
$.ajax({
...
});
You can read more about events binding on dynamic htmls here
Try it like this please:
$(document).on('submit', '.checkform', function(e){
e.preventDefault();
var request = $("#domein").val();
$.ajax({
...
});
It is possible that the popover isn't loaded on page load and is getting generated just when it is needed so you need the document selector.
Because whenever the popover is opened a new dom fragment is created on the fly you may take advantage on this to attach events or manipulate the html itself like you need.
From bootstrap popover docs you need to listen for this event:
inserted.bs.popover: This event is fired after the show.bs.popover event when the popover template has been added to the DOM.
So, my proposal is to avoid the event delegation and attach the event directly to the correct element:
$(function () {
// open the popover on click
$('#popover').popover({
html: true,
content: function () {
return $("#popover-content").html();
}
});
// when the popover template has been added to the DOM
// find the correct element and attach the event handler
// because the popover template is removed on close
// it's useless to remove the event with .off('submit')
$('#popover').on('inserted.bs.popover', function(e){
$(this).next('.popover').find('.checkform').on('submit', function(e){
e.preventDefault();
var request = $("#domein").val();
// do your stuff
$('#popover').trigger('click');
});
});
});
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css">
<script src="https://code.jquery.com/jquery-1.12.1.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/js/bootstrap.min.js"></script>
<body>
<button type="button" class="btn btn-default popover-content" role="button" id="popover">
Click to open Popover
</button>
<div id="popover-content" class="hidden">
<form action="z.html" id="requestacallform" method="GET" name="requestacallform" class="checkform">
<div class="form-group">
<div class="input-group">
<input id="domein" type="text" class="form-control" placeholder="domein" name="name"/>
</div>
</div>
<input type="submit" value="Aanmelden" class="btn btn-blue submit"/>
<p class="response"></p>
</form>
</div>
Thanks for the responses, I was using Meteor and had the same problem. I used #Marcel Wasilewski's response like so...
Template.voteContest.onRendered(function() {
$(document).on('submit', '.keep-vote', function(event){
// Prevent default browser form submit
event.preventDefault();
// Clear all popovers
$("[data-toggle='tooltip']").popover('hide');
});
});

What is the Dojo Equivalent to Button Click

In JavaScript - If I want to fire a button I do this -
<button type = 'button' id='myButton'>HiddenButton</button>
<script>
function callAutoClick(){
document.getElementById('myButton').click();
}
</script>
When I want to fire this button click, say, onChange of a text field -
<input type= 'text' onchange ='callAutoClick()'/>
I am not able to do the same in DOJO. I have found a solution using Javascript -
var divId = document.getElementById('myDivID');
divId.getElementsByTagName("button")[0].click();
But I don't want to have the dependency with the DivID. Is it possible to click a button just knowing the button's controlID. All I could find online were methods to define an OnClick() using dojo for a button and not clicking the button itself.
Plus I am designing the page with a BPM Tool so on including sections the DivID changes. When I open the page in FireBug I can see this -
<div id="div_1_1_2_1" class="Button CoachView CoachView_invisible CoachView_show" data-ibmbpm-layoutpreview="vertical" data-eventid="boundaryEvent_2" data-viewid="Hidden_Cancel" data-config="config23" data-bindingtype="" data-binding="" data-type="com.ibm.bpm.coach.Snapshot_2d5b8abc_ade1_4b8c_a9aa_dfc746e757d8.Button">
<button class="BPMButton BPMButtonBorder" type="button">Hidden_Cancel</button>
</div>
If you guys could suggest me a way to access the DOM object using the data-viewId also it would cater to my need.
Thanks in advance :)
You can use dojo/query:
function progClick() {
require(["dojo/query"], function(query) {
query("div[data-viewid=myViewId] > button").forEach(function(node) {
node.click();
});
});
}
<html>
<head>
<script src="http://ajax.googleapis.com/ajax/libs/dojo/1.10.1/dojo/dojo.js" data-dojo-config="async: true"></script>
<link rel="stylesheet" href="http://ajax.googleapis.com/ajax/libs/dojo/1.10.1/dijit/themes/claro/claro.css">
</head>
<body class="claro">
<div id="everChangingId" data-viewid="myViewId">
<button type="button" onclick="alert('my button got clicked!')">My Button</button>
</div>
<hr/>
<button type="button" onclick="progClick()">Programatically Click My button</button>
</body>
</html>

Display the last state of HTML display after clicking back

I have this problem let say I click an event (e.g. radio button 2) to show() div2 and hide() div1. After that I click a link to redirect to the next page.
Then I click back button (browser <-). Radio button 2 is checked, but the display is div1 instead of div2. Here is a sample source code. Could anyone help me if this can be fix.
<!-- test.php START -->
<div id="div_1" style="display: block;">
<p>First Paragraph</p>
</div>
<div id="div_2" style="display: none;">
<p>Second Paragraph</p>
</div>
<div>
<input type="radio" id="rdo1" name="radio" checked/>First
<input type="radio" id="rdo2" name="radio" />Second
</div>
<div>
Just to reload the page or go to other page
</div>
<script type="text/javascript" src="js/jquery-1.8.0.min.js"></script>
<script>
$(document).ready(function() {
$("#rdo1").click(function () {
$("#div_1").show();
$("#div_2").hide();
});
$("#rdo2").click(function () {
$("#div_1").hide();
console.log('test');
$("#div_2").show();
});
});
</script>
<!-- test.php END-->
<!-- test1.php START -->
DISPLAY SOMETHING
<!-- test1.php END -->
Web is stateless and by default the browser does not remember any settings of the previous page.. SO when you press the back button it is just like a page refresh like you opened the default page with default HTML
This is the expected and default behaviour
If you want the behavior you are expecting then you need to cache the page or store the state , either in a session or a cookie..
You can on DOMReady check which radio input is selected.
$(document).ready(function() {
var ind = $('input[name=radio]:checked').index();
$('div[id^=div]').hide().eq(ind).show()
$("#rdo1").click(function () {
$("#div_1").show();
$("#div_2").hide();
});
$("#rdo2").click(function () {
$("#div_1").hide();
console.log('test');
$("#div_2").show();
});
})
You would have to save the state somehow, either server-side with ajax or form posts or via client-side with cookie or localStorage.
You can set cookies easily with the jquery-cookie plugin or you can use vanilla javascript to set localStorage like this quick example:
<!doctype html>
<meta charset="utf-8">
<title>html5 notepad</title>
<textarea></textarea>
<script>
var n = document.getElementsByTagName('textarea')[0];
n.onchange = function(){localStorage.setItem("n",n.value);}
n.value = localStorage.getItem("n");
</script>
if ($('#rdo1').attr('checked')){
$("#div_1").show();
$("#div_2").hide();
}
if ($('#rdo2').attr('checked')){
$("#div_1").hide();
$("#div_2").show();
}
$("#rdo1").click(function () {
$("#div_1").show();
$("#div_2").hide();
});
$("#rdo2").click(function () {
$("#div_1").hide();
console.log('test');
$("#div_2").show();
});​

Categories

Resources