I need your help guys.
I use a textarea that automatically expands by changing the number of rows.
In my project, the page does not reload and stays as it is after submitting the form. I need to change dynamically the number of rows (2) on submit.
Also one can send the form by Enter. So I need to change the number of rows after pushing a button or hitting the Enter key.
I've coded a rough sketch of the form that I have in my project so that you could test it: https://codepen.io/C3La-NS/pen/NagZbr
<form id="NewMessage">
<textarea id="shoutbox-comment" data-min-rows="2"></textarea>
<button id="send_message" type="submit" onclick="chatSubmit();">send</button>
</form>
JS:
// auto-resizing textarea
const textarea = document.getElementById("shoutbox-comment");
textarea.addEventListener("input", function() {
this.rows = 2; // Erm...
this.rows = countRows(this.scrollHeight);
});
function countRows(scrollHeight) {
return Math.floor(scrollHeight / 20); // 20px = line-height: 1.25rem
}
// submit by Enter
$(document).ready(function() {
$("#shoutbox-comment").on("keypress", function(event) {
if (event.keyCode == 10 || event.keyCode == 13) {
event.preventDefault();
chatSubmit();
}
});
});
// submit FORM
function chatSubmit() {
$("#NewMessage").submit();
}
Thank you!
jQuery submit accept as parameter a callback that is triggered before submit so, you can do:
$("#NewMessage").submit(function( event ) {
event.preventDefault();
$('#shoutbox-comment').attr('rows', 2);
});
Just couple of changes in your script:
const textarea = $("#shoutbox-comment");
const minRows = textarea.data('minRows');
textarea.on("input", function(e) {
this.rows = 1; // Erm...
this.rows = countRows(this.scrollHeight);
});
function countRows(scrollHeight) {
var toReturn = Math.floor(scrollHeight / 20); // 20px = line-height: 1.25rem
return toReturn > minRows ? toReturn : minRows;
}
// submit by Enter
$(document).ready(function() {
$("#shoutbox-comment").on("input", function(e) {
if (e.keyCode == 10 || e.keyCode == 13) {
e.preventDefault();
chatSubmit();
}
});
});
// submit FORM
function chatSubmit() {
// Send the message via AJAX;
textarea.val('').trigger('input');
return false;
}
#shoutbox-comment {
width: 220px;
outline: none;
resize: none;
line-height: 20px;
overflow: hidden;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<form id="NewMessage">
<textarea id="shoutbox-comment" data-min-rows="2"></textarea>
<button id="send_message" type="submit" onclick="chatSubmit();">send</button>
</form>
I've also included data-min-rows attribute inside the script.
Also on CodePen.
Related
I'm trying to make website which will enable button when the certain condition is met. But when I run it within simple if the condiiton is checked only at the beginning and it doesn't enable and disable on changing condition. Condition is changing inside other event listener so the condition is dynamically. The condition is met when the dicitonary consists only of true which means that input is proper
`var submitButton = document.getElementById("submit_button");`
And after some event listeners connected to inputs
`if(Object.values(check_dict).filter(x=>x==true).length === 6)
{
submitButton.disabled = false;
}
else
{
submitButton.disabled = true ;
}`
pretty straight forward. add an eventlistener to the input you want to watch and then disable the submit button inside the function
document.getElementById('test').addEventListener('input',myFunc)
function myFunc(){
if(event.target.value == "x")document.getElementById("submit_button").disabled = true;
else document.getElementById("submit_button").disabled = false;
}
<input id ='submit_button' type='submit'>
<input id='test'>
You could use removeAttribute() and setAttribute() to toggle the state of the submit button using a conditional.
See the snippit for a very simple example of how to toggle states using classes with .classList along with add/remove attribute method.
const checkInput = (e) => {
if(e.target.value.length >= args.rules.length){
e.target.classList.remove('error')
e.target.classList.add('success')
submitBtn.removeAttribute('disabled')
inputDisplay.textContent = args.success.value
}else{
e.target.classList.add('error')
e.target.classList.remove('success')
submitBtn.setAttribute('disabled', 'true')
inputDisplay.textContent = args.error.value
}
}
const args = {
rules: {
length: 8
},
success: {
value: "Success! You may submit now!"
},
error: {
value: "Input must contain 8 or more characters!"
}
}
const fname = document.getElementById('fname')
const submitBtn = document.getElementById('submit')
const inputDisplay = document.getElementById('input-display')
inputDisplay.textContent = args.error.value
submitBtn.disabled = 'true'
fname.addEventListener('input', checkInput)
.success {
color: darkgreen;
background-color: lightgreen;
}
.error {
color: darkred;
background-color: pink;
}
<input name="firstname" id="fname" placeholder="Please enter your first name">
<button id="submit" type="button">Submit</button>
<div id="input-display"></div>
Currently having some issues with jQuery Form Submissions in my project.
My project contains a general jQuery Code which prevents form double submissions (e.g. someone clicks the 'submit' button multiple times).
//prevent multiple form submissions
jQuery.fn.preventDoubleSubmission = function () {
$(document).on('submit', this, function (e) {
let $form = $(this);
if ($form.data('submitted') === true) {
e.preventDefault();
} else {
$form.data('submitted', true);
}
});
return this;
};
$(function () {
$('form').preventDoubleSubmission();
});
This code is included into every single page - so every form should be 'protected'.
For some specific forms I need to check some values before they are submitted - and show a confirm box, if some values are missing (e.g. Are you sure you want to submit this form without value X?)
Here's the code:
$(document).on('submit', 'form[name="article"]', function (e) {
e.preventDefault();
let form = this;
let $form = $(form);
let $category = $form.find('select#article_category'); //get category
if ($category.length && !$category.val()) { //check if category is selected
$.confirm({ //jquery confirm plugin
title: "Are you sure?",
content: "Value X is missing - continue?",
buttons: {
confirm: {
action: function () {
$form.off('submit');
form.submit();
}
}
}
});
} else {
$form.off('submit');
form.submit();
}
});
So basically, if the user tries to submit the form, but the value X is missing, there will be a Yes/No Popup first - if the value exists, the form will be submitted right away.
Problem:
When I want to submit the form, I call $form.off('submit'); to remove the event handler and submit afterwards with form.submit();. Sadly this also removes my preventDoubleSubmission event handler, which allows double submissions again.
Is there a way to fix my issue? Thanks
Below is a code snippet with a correct solution. There were multiple issues with your original approach, highlighted below the snippet. Better to run this snippet in a different code playground, where action with javascript work, e.g. JSFiddle.
//prevent multiple form submissions
function submitOnce (e, $form) {
alert('submitted = ' + $form.data('submitted'));
if ($form.data('submitted') === true) {
e.preventDefault();
alert('Double-submission prevented!');
} else {
$form.data('submitted', true);
alert('Double-submission param saved');
}
}
$(document).on('submit', 'form[name="article"]', function (e) {
let form = this;
let $form = $(form);
let $category = $form.find('select#article_category'); //get category
if ($category.length && !$category.val()) { //check if category is selected
if ( confirm("Are you sure?") ){
submitOnce(e,$form);
}
else {
e.preventDefault();
}
} else {
submitOnce(e,$form);
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<form name="article" action="javascript:alert('Form submitted!');">
<select id="article_category" name="select1">
<option></option>
<option>option1</option>
<option>option2</option>
</select>
<input type="submit" />
</form>
edit: adding explanations
$form.off() would work if you would bind 'submit' event handler directly on the form element, but in both cases handlers are registered on the document.
Calling form.submit() is not necessary, since we are already in a submit handler, hence submit already called. We just need to prevent submissions to continue.
Better is to have just one submit handler, and deal with double submits there.
e.preventDefault(); has to be just in the else clause for a non-confirmed case and in submitOnce(). You had it at the beginning of the main handler, but it was useless there, since form.submit() was called again inside, and this call does not prevent the default.
My approach is not bullet-proof and serves just as a demonstration of what needed to be changed.
One approach is to use a normal span with a click event. Once it is clicked you can disable it (using a class for example) and then submit form. This approach allows you to control form submission without the need of extra coding.
See this example:
$submitBtn = jQuery(".submit");
$form = jQuery("form[name='article']");
$submitBtn.on("click", function() {
if (jQuery(this).hasClass("disabled"))
return;
let $category = $form.find('.name'); //get value
if ($category.length && !$category.val()) { //check if value is set
$.confirm({ //jquery confirm plugin
title: "Are you sure ?",
content: 'Value x is missing - continue ?',
buttons: {
confirm: {
action: function() {
$form.submit();
$submitBtn.addClass("disabled");
}
},
cancel: function() {
//$.alert('canceled');
}
}
});
return;
}
$submitBtn.addClass("disabled");
$form.submit();
});
form {
border: 1px solid rgba(0, 0, 0, 0.1);
padding: 1.5rem;
display: flex;
flex-direction: column;
width: 200px;
}
form input {
margin-bottom: 0.5rem;
padding: 0.3rem;
border-radius: 3px;
border: 1px solid gray;
}
form .submit {
padding: 0.3rem 1rem;
cursor: pointer;
border-radius: 3px;
background-color: rgba(0, 0, 0, 0.1);
text-align: center;
transition: all 0.3s;
}
form .submit.disabled {
opacity: 0.5;
cursor: default;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<link href="https://cdnjs.cloudflare.com/ajax/libs/jquery-confirm/3.3.2/jquery-confirm.min.css" rel="stylesheet" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery-confirm/3.3.4/jquery-confirm.min.js"></script>
<form action="" name='article'>
First name:<br>
<input type="text" name="firstname" value="My First Name" class='name'>
<br> Last name:<br>
<input type="text" name="lastname" value="My Last Name">
<br><br>
<span class='submit'>Submit</span>
</form>
So I finally figured out a relatively ok solution for me. However it is very simple and I might stick with it.
//form submission function
function submitForm(form) {
let $form = $(form);
let $submit = $form.find('button[type=submit]'); //find submit button
$submit.attr('disabled', true); //disable button = prevent double submission
form.submit(); //submit form
}
//submission for every form but not .form-confirm
$(document).on('submit', 'form:not(.form-confirm)', function (e) {
e.preventDefault();
submitForm(this); //call function
});
$(document).on('submit', 'form[name="article"]', function (e) {
e.preventDefault();
let form = this;
let $form = $(form);
let $category = $form.find('select#article_category'); //get category
if ($category.length && !$category.val()) { //check if category is selected
$.confirm({
title: "Are you sure?",
content: "Value X is missing - continue?",
buttons: {
confirm: {
action: function () {
submitForm(form); //call function
}
}
}
});
} else {
submitForm(form); //call function
}
});
So how does it work?
Basically I just disable the submit button after submitting (=prevent double submissions). I added a class called form-confirm to the specific form which the popup should show, so the general rule does not work there.
I always use preventDefault and use form.submit() to submit right away in my code.
In IE 11 if I have an empty email input with a placeholder, then on clicking (focusing) it, the input event is being triggered.
Does anyone know why and is there a solution to this, since the input value hasn't really changed?
var el = document.getElementById('myEmail');
el.addEventListener("input", myFunction, true);
function myFunction()
{
alert("changed");
}
<input id="myEmail" type="email" placeholder="Email">
I came very late to the party, but I had the same problem, and I came to a workaround to fix this behavior on IE.
In fact, there's two different bugs (or rather, only one bug but with two behavior depending on whether the target is an input or a textarea).
For input : the event is triggered each time the visual content of the field change, including keyboard inputting (naturally), but also when a placeholder appears/disappears (blur when no content), or when a visible placeholder is changed programmatically.
For textarea: it's basically the same, exepts that the event don't trigger when the placeholder disapears.
function onInputWraper(cb) {
if (!window.navigator.userAgent.match(/MSIE|Trident/)) return cb;
return function (e) {
var t = e.target,
active = (t == document.activeElement);
if (!active || (t.placeholder && t.composition_started !== true)) {
t.composition_started = active;
if ((!active && t.tagName == 'TEXTAREA') || t.tagName == 'INPUT') {
e.stopPropagation();
e.preventDefault();
return false;
}
}
cb(e);
};
}
var el = document.getElementById('myEmail');
el.addEventListener("input", onInputWraper(myFunction), true);
function myFunction() {
alert("changed");
}
<input id="myEmail" type="email" placeholder="Email">
And there's a full-working example, where you can also change placeholders value
function onInputWraper(cb) {
if (!window.navigator.userAgent.match(/MSIE|Trident/)) return cb;
return function (e) {
var t = e.target,
active = (t == document.activeElement);
if (!active || (t.placeholder && t.composition_started !== true)) {
t.composition_started = active;
if ((!active && t.tagName == 'TEXTAREA') || t.tagName == 'INPUT') {
e.stopPropagation();
e.preventDefault();
return false;
}
}
cb(e);
};
}
function handle(event) {
console.log('EVENT', event);
document.getElementById('output')
.insertAdjacentHTML('afterbegin', "<p>" + event.type + " triggered on " + event.target.tagName +
'</p>');
}
var input = document.getElementById('input'),
textarea = document.getElementById('textarea');
input.addEventListener('input', onInputWraper(handle));
textarea.addEventListener('input', onInputWraper(handle));
// input.addEventListener('input', handle);
// textarea.addEventListener('input', handle);
// Example's settings
function removeListeners(elem) {
var value = elem.value,
clone = elem.cloneNode(true);
elem.parentNode.replaceChild(clone, elem);
clone.value = value;
return clone;
}
document.querySelector('#settings input[type="checkbox"]').addEventListener('change', function (event) {
if (event.target.checked) {
document.getElementById('output').insertAdjacentHTML('afterbegin', '<p>Filter enabled !</p>');
//input = removeListeners(input);
console.log(input.value.length, (input == document.activeElement));
input = removeListeners(input);
input.addEventListener('input', onInputWraper(handle));
input.composing = input.value.length > 0 || (input == document.activeElement);
textarea = removeListeners(textarea);
textarea.addEventListener('input', onInputWraper(handle));
textarea.composing = textarea.value.length > 0 || (textarea == document.activeElement);
} else {
document.getElementById('output').insertAdjacentHTML('afterbegin', '<p>Filter disabled !</p>');
input = removeListeners(input);
input.addEventListener('input', handle);
input.composing = void 0;
textarea = removeListeners(textarea);
textarea.addEventListener('input', handle);
textarea.composing = void 0;
}
});
document.getElementById('input_cfg').addEventListener('click', function () {
document.getElementById('input').setAttribute('placeholder', document.getElementById(
'input_placeholder').value);
});
document.getElementById('textarea_cfg').addEventListener('click', function () {
document.getElementById('textarea').setAttribute('placeholder', document.getElementById(
'textarea_placeholder').value);
});
* {
font: 15px arial, sans-serif;
}
dd {
background: FloralWhite;
margin: 0;
}
dt {
padding: 15px;
font-size: 1.2em;
background: steelblue;
color: AntiqueWhite;
}
p {
margin: 0;
}
button,
label {
width: 300px;
margin: 5px;
padding: 5px;
float: left;
color: DarkSlateGray;
}
#settings label {
width: 100%;
margin: 15px;
}
#forms input,
#forms textarea,
#settings input:not([type]) {
display: block;
width: calc(100% - 340px);
padding: 7px;
margin: 0;
margin-left: 320px;
min-height: 25px;
border: 1px solid gray;
background: white;
cursor: text;
}
::placeholder {
/* Chrome, Firefox, Opera, Safari 10.1+ */
color: LightBlue;
opacity: 1;
/* Firefox */
}
::-ms-input-placeholder {
/* Microsoft Edge */
color: LightBlue;
}
:-ms-input-placeholder {
/* Internet Explorer 10-11 */
color: LightBlue;
}
<dl>
<dt>Forms</dt>
<dd id="forms">
<label for="input">Input: </label>
<input id="input" name="input" class="testing" placeholder="Type some text" />
<label for="texarea">Textarea: </label>
<textarea id="textarea" name="textarea" placeholder="Type some text"></textarea>
</dd>
<dt>Settings</dt>
<dd id="settings">
<p>
<label><input type="checkbox" checked>Enable filtering script</label>
<button id="input_cfg">Change input's placeholder to</button><input id="input_placeholder" />
</p>
<p>
<button id="textarea_cfg">Change textarea's placeholder to</button>
<input id="textarea_placeholder" />
</p>
</dd>
<dt>Output</dt>
<dd id="output"></dd>
</dl>
or on jsfiddle
It seems like a bug. oninput has been supported since IE9 should only fire when the value is changed. An alternate approach would be to use onkeyup
https://developer.mozilla.org/en-US/docs/Web/Events/input
If you want to handle input and validation you can just add a second eventlistener (assuming your html is the same as above).
var el = document.getElementById('myEmail');
function myFunction() {
console.log("changed");
}
el.addEventListener("keyup", myFunction, true);
function validation() {
console.log("validated");
}
el.addEventListener("keyup", validation, true);
The solution is very short!
At first we don't need so much of code what we can see in accepted answer. At second you have to understand why it is happening:
Fake oninput event triggers only on inputs with a placeholder on getting a focus and only if the input value is empty. It happens because bad developer from IE had thought that the input value changes from placeholder value to real value, but it is misunderstanding from this bad developer from IE.
An input without placeholders doesn't have this problems.
The first solution is very simple: do not use a placeholder if you do not really need it. In most cases you can add a title to the element instead of a placeholder. You could also write your placeholder text before, below or above the input.
If you have to use a placeholder
The second solution is also very simple and short: save the previous value on the input object and compare it with a new value – if it was not changed then return from the function before your code.
Life examples
var input = document.querySelector('input[type=search]');
input.addEventListener('input', function(e)
{
if(this.prevVal == this.value /* if the value was not changed */
|| !this.prevVal && '' == this.value) //only for the first time because we do not know the previous value
return; //the function returns "undefined" as value in this case
this.prevVal = this.value;
//YOUR CODE PLACE
console.log('log: ' + this.value)
}, false);
<input type="search" placeholder="Search..."/>
Or if you use it as inline JavaScript:
function onSearch(trg)
{
if(trg.prevVal == trg.value /* if the value was not changed */
|| !trg.prevVal && '' == trg.value) //only for the first time because we do not know the previous value
return; //the function returns "undefined" as value in this case
trg.prevVal = trg.value; // save the previous value on input object
//YOUR CODE PLACE
console.log('log: ' + trg.value);
}
<input type="search" placeholder="Search..." oninput="onSearch(this)"/>
I am trying to implement Ctrl+B for a contenteditable div which should make the text bold.
The only problem I'm getting is that when Ctrl+B is pressed, browser's bookmark tab appears.
(fiddle)
$(document).ready(function() {
$('#editable').designMode = 'on';
$('#editable').on('keyup', function(e) {
console.log(e.which);
if(e.which == 66 && e.ctrlKey) {
e.preventDefault();
console.log('bold');
document.execCommand ('bold', false, null);
return false;
}
});
});
#editable {
width:200px;
height:100px;
border:1px solid #999;
border-radius: 3px;
padding: 10px;
box-sizing:border-box;
}
#editable:focus {
outline: none;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script>
<div contenteditable="true" id="editable"></div>
Please help me find a way to disable that bookmark when I'm focussed inside that editable div.
check this solution
jsFiddle
var g_state = 0;
$(document).ready(function() {
$('body').keydown( function ( eve ) {
if (eve.which === 17) {
eve.preventDefault();
g_state = 1;
}
return true;
});
$('body').keyup( function ( eve ){
if (eve.which === 17) {
eve.preventDefault();
g_state = 0;
}
return true;
});
$('body').keypress( function ( eve ) {
eve.preventDefault();
if (eve.ctrlKey && (eve.which === 78)) {
alert("(eve.ctrl + 'n')");
}
else {
if (g_state && (eve.which === 78)) {
alert("(ctrl tracking by key up/down + 'n', resetting)");
g_state = 0;
}
else {
if (eve.shiftKey && (eve.which === 78)) {
alert("(eve.shift + 'n')");
}
else {
alert("pass");
}
}
}
});
});
Hi Dangling Cruze,
Here there is no any rocket science , What we are doing here is to Prevent the event bubing. And stopping event to reach at web browser.
The preventDefault() method cancels the event if it is cancel-able, meaning that the default action that belongs to the event will not occur.
In single term
For example, this can be useful when:
Clicking on a "Submit" button, prevent it from submitting a form
Clicking on a link, prevent the link from following the URL
At the document level we are binding all main three event
keydown
keyup
keypress
and identifying key combination as well to prevent some key combination that is being used by browser as well.
let me know if you require any further help
When someone starts typing (number or alphabets), I want a search bar to appear and it should take the alphabets that are being written by the user in it, ie, I want it to automatically focus on the field.
So far I have this..
if (window.addEventListener) {
var keys = [], listen= /^([0-9]|[a-z])\i$/ ;
window.addEventListener("keydown", function(e){
keys.push(e.keyCode);
if(keys.match(listen))
{
$('#searchBar').fadeIn();
$('#searchBar input').text(keys);
$('#searchBar input').focus();
keys = [];
}
},true);
}
I want the first character that was typed in to show in the field too.
Ty.
Hope this works for you. If you prefer jQuery, minor changes needs to be made.
<style>
#searchBar { display: none; }
.search { width: 250px; height: 20px; }
</style>
<div id="searchBar">
Search Here: <input type="search" id="searchInput" class="search" />
</div>
<script>
window.onload = function() {
var listen = /^[a-z0-9]+$/i;
var searchInput = document.getElementById('searchInput');
var searchBar = document.getElementById('searchBar');
if ( window.addEventListener )
window.addEventListener( 'keyup', insertKey, false);
function insertKey( e ) {
// Get the character from e.keyCode
var key = String.fromCharCode( e.keyCode ).toLowerCase();
// Match the character
if( key.match(listen) ) {
// Change display: none; to display: block;
searchBar.style.display = "block";
// Append every new character
searchInput.value += key;
// Focus on input
searchInput.focus();
// Since you focused on the input you don't need to listen for keyup anymore.
window.removeEventListener( 'keyup', insertKey );
// I didn't tested with jQuery
// $('#searchBar').fadeIn();
// $('#searchBar input').append(keys);
// $('#searchBar input').focus();
}
}
};
</script>
var listen= /^([0-9]|[a-z])\i$/;
var key = [];
window.addEventListener('keydown', function (e) {
keys.push(e.keyCode);
if(keys.match(listen)) {
$('#searchBar').fadeIn();
$('#searchBar input').append(keys);
$('#searchBar input').focus();
keys = [];
}
});