focusout handler also fires on focusin - javascript

I have jQuery code that executes an AJAX request every time the text input is focused out. The thing I don't understand is when I focus back in the AJAX request gets executed. There's no focusin function defined. Code snippet below:
$(function() {
// some other functions here but no focusin function defined.
$( "#additem" ).click(function(e) {
e.preventDefault();
var _id = "new_pn", _holder = "Enter part number here", btnId = "post", btnIcon = "fa fa-save", btnText = " Add Serial", formId = "new-sn";
openModal(_id, _holder, btnId, btnIcon, btnText, formId);
});
var openModal = function(a,b,c,d,e, f) {
var txtInput = $("#myModal form input")[1], btn = $("#myModal form button")[0], icon = $("#myModal form i")[0], form = $("#myModal form")[0];
txtInput.id = a;
txtInput.placeholder = b;
btn.id = c;
icon.className = d;
form.id = f;
$($("#myModal form span")[1]).text(e);
$("#myModal").attr('style', 'display:block');
};
//Check serial before saving when text field is focusout. 2nd argument, #new-sn is a dynamically created form id.
$('#myModal').on('focusout', $('#new-sn input')[0], function() {
var sn = $("#serial").val();
if (sn) {
Promise.resolve(GetDocumentItems(serialsDb, sn)).then(function() {
console.log(sn.toUpperCase() + " already exists in the database");
}).catch(function() {
console.log(sn.toUpperCase() + " is cleared to save in database.");
});
}
});
});
What am I doing wrong here? Cheers
Added HTML code below:
<div id="myModal" class="modal">
<div class="modal-content">
<!--variable form id (depends on the caller)-->
<form>
<div class="container">
<span class="close">×</span>
<input id="serial" type="text" placeholder="Enter serial number here">
<!--2nd text box, variable id and placeholder (depends on the caller)-->
<input type="text">
<!--button variable id and i variable class (invoker dependent).-->
<button class="green"><i></i> <span></span></button>
</div>
</form>
</div>
</div>

Related

Ajax populated select elements conflicting with each other on ajax database insert call that retuns json

I have a rather complicated form that allows the ability to add additional data (make, model, etc.) dynamically via a modal window that once the value is added via an ajax db insert call, the modal window is closed and jQuery is used to refresh the select element the data was added to. I have 5 of these type of select elements in use by my form.
Here's the problem, when I update a select element like explained above, when the modal window closes, all of the select elements on the page will refresh to the selected value of the select that completed the db insert. This id variable is the primary key of the data just inserted and will update the select list with the new value but also have the unintended side effect of making all the other select elements change to a non existing option (blank).
I've been trying to find a way for days to make it so that only the select that initiated the db insert would be the one to refresh, but I'm not sure how to do that. Could anyone point me in the right direction?
Here's my code:
JSON that populates select elements in the form:
{"suppliers":{"1":"Amazon"},"manufacturers":{"1":"Apple"},"categories":{"2":"Tablet"},"status":{"1":"Ready to Deploy","2":"Deployed","3":"Damaged"}}
JSON that is returned after db insert containing the new id from the db
{"success":true,"id":$id}
Script that populates the select elements and handles select refreshes
$(document).ready(function() {
refreshData();
});
function refreshData(newId) {
$.ajax({
url: '/json/collection.json',
type: 'GET',
dataType: 'json',
success: function(data) {
refreshSelect('inputSupplier', data.suppliers, newId);
refreshSelect('inputManufacturer', data.manufacturers, newId);
refreshSelect('inputStatus', data.status, newId);
refreshSelect('inputCategory', data.categories, newId);
refreshSelect('inputManufacturerModel', data.manufacturers); //modal window select element
}
});
}
function refreshSelect(name, data, newId) {
// Select by id
let $elem = $('#' + name);
// Get current value
let oldValue = $elem.val();
// Get option with value 0, which is the first element
let emptyOption = $elem.children('option').first();
// Empty the element and add the option. We are back to initial state
$elem.html(emptyOption);
// Append elements retrieved from backend
$.each(data, function(key, value) {
$elem.append('<option value="' + key + '">' + value + '</option>');
});
if(newId){
$elem.val(newId);
}else{
$elem.val(oldValue);
}
}
The js ajax call that processes the modal form db insert
$(document).ready(function () //function to process modal form via ajax
{
$('.modal-submit').on('submit', function(e){
e.preventDefault(); //prevent default form submit action
$(".backend-error").html(''); //clear out previous error messages
$('input').removeClass('input-error'); //clear error border class
var data = $(this).serialize();
var type = $(this).find('input[name="type"]').val(); //get value of hidden input
var url = $(this).attr('action'); //get action from form
var modal = $(this).closest('.modal');
var modalInput = $(this).find('.form-row input'); //get input from form
var modalName = '#' + type + 'Modal'; //form modalName variable from var 'type'
$.ajax({
url:url,
method:'POST',
data:data,
success:function(response){
refreshData(newId = response.id); // set newId to the id of the newly inserted item
modal.modal('hide'); //hide modal
$(modalInput).val(''); //clear input value
},
error:function(e){
$.each(e.responseJSON.error, function (i, error) {
$(modalInput).addClass('input-error');
$(modalName + ' .backend-error').html(error[0]); //return error from backend
});
}
});
});
});
Example of html layout of the modal that contains the form (1 of 5)
<!-- Add New Supplier Modal -->
<div class="modal fade" id="supplierModal" tabindex="-1" role="dialog" aria-labelledby="supplierModalLabel" aria-hidden="true">
<div class="modal-dialog modal-dialog-centered" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="supplierModalLabel">Add new asset supplier</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
<div class="modal-body">
<form method="post" class="modal-submit" autocomplete="off" action="{{ action('AddAssetController#addDescriptor', ['type' => 'supplier']) }}">
<input type="hidden" name="_token" value="{{ csrf_token() }}">
<input type="hidden" name="type" value="supplier">
<div class="form-row">
<div class="col-md-12 mb-3">
<label for="inputModelNew">Supplier name *</label>
<div class="input-group">
<input type="text" name="inputSupplierNew" id="inputSupplierNew" class="form-control" placeholder="Enter supplier name" required="required">
</div>
<div class="backend-error"></div>
</div>
</div>
<div class="float-right">
<button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button>
<button type="submit" class="btn btn-primary">Save changes</button>
</div>
</form>
</div>
</div>
</div>
</div>
<!-- / Add New Supplier Modal -->
Visuals:
All other selects updated when it should only update the one that was updated:
Is it possible to only update that one select element and not all of them?
In your Modal on click of submit you can passed the id of modal in your refreshData function and depending on which modal is open you can change value of that select only .So, your code will look like below :
Your jquery submit event :
..
//getting modal id i.e: supplierModal
var modal_id = $(this).closest('.modal').attr('id');
console.log(modal_id);
$.ajax({
..
success: function(response) {
//passing id of modal
refreshData(newId = response.id, modal_id ); // set newId to the id of the newly inserted item
modal.modal('hide'); //hide modal
$(modalInput).val(''); //clear input value
},
...
});
Your refreshData() will look like below :
function refreshData(newId, idofmodal) {
$.ajax({
url: '/json/collection.json',
type: 'GET',
dataType: 'json',
success: function(data) {
//checking value
if (idofmodal != null) {
if (idofmodal == "supplierModal") {
refreshSelect('inputSupplier', data.suppliers, newId);
} else if (idofmodal == "manufacturerModal") {
refreshSelect('inputManufacturer', data.manufacturers, newId);
}
//same for other selects
} else {
refreshSelect('inputSupplier', data.suppliers, newId);
refreshSelect('inputManufacturer', data.manufacturers, newId);
refreshSelect('inputStatus', data.status, newId);
refreshSelect('inputCategory', data.categories, newId);
refreshSelect('inputManufacturerModel', data.manufacturers); //modal window select element
}
}
});
}

Display textbox multiple times

The HTML part contains a textarea with a label.The user has to enter text and the form should be submitted and refreshed for the user to enter text again for say 5 more times. How can I do this using Javascript?
This is the html code:
<form name="myform" method="post">
<div class="form-group col-sm-5">
<label for="ques"><p id="p1">Question:</p></label>
<textarea class="form-control" rows="5" id="ques"></textarea>
</div>
</form>
<button type="button" class="btn" id="sub" onclick="func()">Next</button>
The javascript code:
var x=1;
document.getElementById("p1").innerHTML="Question"+x;
function func()
{
var frm = document.getElementsByName('myform')[0];
frm.submit();
frm.reset();
return false;
}
Here are two methods you can use. Both of these require you to add a submit button to your form, like this:
<form name="myform" method="post">
<div class="form-group col-sm-5">
<label for="ques"><p id="p1">Question:</p></label>
<textarea class="form-control" rows="5" id="ques"></textarea>
</div>
<!-- add this button -->
<input type="submit" value="Submit" class="btn">
</form>
<!-- no need for a <button> out here! -->
Method 1: sessionStorage
sessionStorage allows you to store data that is persistent across page reloads.
For me info, see the MDN docs on sessionStorage. This method requires no external libraries.
Note that in this method, your page is reloaded on submit.
window.onload = function() {
var myForm = document.forms.myform;
myForm.onsubmit = function(e) {
// get the submit count from sessionStorage OR default to 0
var submitCount = sessionStorage.getItem('count') || 0;
if (submitCount == 5) {
// reset count to 0 for future submissions
} else {
// increment the count
sessionStorage.setItem('count', submitCount + 1);
}
return true; // let the submission continue as normal
}
// this code runs each time the pages loads
var submitCount = sessionStorage.getItem('count') || 0;
console.log('You have submited the form ' + submitCount + ' times');
if (submitCount == 4) {
console.log("This will be the final submit! This is the part where you change the submit button text to say \"Done\", etc.");
}
};
Method 2: AJAX with jQuery
If you don't mind using jQuery, you can easily make AJAX calls to submit your form multiple times without reloading.
Note that in this example your page is not reloaded after submit.
window.onload = function() {
var myForm = document.forms.myform;
var submitCount = 0;
myForm.onsubmit = function(e) {
$.post('/some/url', $(myForm).serialize()).done(function(data) {
submitCount++;
});
console.log('You have submited the form ' + submitCount + ' times');
if (submitCount == 4) {
console.log("This will be the final submit! This is the part where you change the submit button text to say \"Done\", etc.");
}
e.preventDefault();
return false;
};
};
Hope this helps!
You shuld create an array and push the value of the textbox to the array in func().
We can create a template using a <script type="text/template>, then append it to the form each time the button is clicked.
const btn = document.getElementById('sub');
const appendNewTextArea = function() {
const formEl = document.getElementById('form');
const textareaTemplate = document.getElementById('textarea-template').innerHTML;
const wrapper = document.createElement('div');
wrapper.innerHTML = textareaTemplate;
formEl.appendChild(wrapper);
}
// Call the function to create the first textarea
appendNewTextArea();
btn.addEventListener('click', appendNewTextArea);
<form name="myform" method="post" id="form">
</form>
<button type="button" class="btn" id="sub">Next</button>
<script id="textarea-template" type="text/template">
<div class="form-group col-sm-5">
<label for="ques"><p id="p1">Question:</p></label>
<textarea class="form-control" rows="5" id="ques"></textarea>
</div>
</script>

Displaying Counter on The Actual HTML Button

I have a 'like' button; and underneath the button, I can display the 'like count'.
However, I want the 'like count' value to be displayed on the actual button itself. For example, I want the button to say: "Like 5"
How can I display both text and a variable value on a button?
Maybe you can improving with this code that i did.
HTML
<form id = "form" method = "POST">
<input type = "submit" value = "Like" />
</form>
<br />
<div id = "clicks">
counter = <label id = "count">0</label> clicks !
</div>
JS
function CountOnFormSubmitEvent(form_id, _callback_)
{
var that = this, count = 0, callback = _callback_;
var form = document.getElementById(form_id);
if(form === null) { return null; }
var reset = function(){
count = 0;
};
form.addEventListener("submit", function(evt){
callback(evt, ++count, reset);
}, false);
}
//Reseting Process You can delete if you dont want it.
var counter = new CountOnFormSubmitEvent("form", function(event, count, reset_callback){
event.preventDefault();
if(count >= 10)
{
alert("Reseting the process");
reset_callback();
}
document.getElementById("count").innerHTML = count;
});
Here is the link Jsfiddle.
DEMO JSFIDDLE

Click of any button submits form.how to stop this?

I am trying to create a form which will take the user input to create a query for database. I have three buttons: And, Or, Run.
I am creating dynamic elements on click of buttons And and Or.
The div search_list is the container for containing the elements.
I need the form to be submitted on click of Run.
The weird thing is, whenever I click on any button the form gets submitted. How do I stop it ? Please let me know If you need more info.
Thanks
<html>
<head>
<script type="text/javascript">
var count = 0;
function loadfirst(){
count=1;
addFilter('');
}
function addFilter(flag){
var div = document.querySelector("#search_list");
tr = document.createElement("tr");
select = document.createElement("select");
var sear_value = document.createElement("input");
var and_or = document.createTextNode(flag);
tr.id='tr_'+count;
select.id='sl_'+count;
sear_value.id='sear_value_'+count;
select.options.add( new Option("user id","user_id", true,true) );
select.options.add( new Option("First name","first_name"));
select.options.add( new Option("Last name","last_name"));
select.options.add( new Option("Course","course"));
sear_value.type="text";
if(count<=1){
var bt_and= document.createElement("button");
bt_and.id='and';
var bt_label = document.createTextNode("And");
bt_and.appendChild(bt_label);
bt_and.addEventListener('click', function() {
addFilter('and');
return false;
});
var bt_or= document.createElement("button");
bt_or.id='or';
var bt_label = document.createTextNode("Or");
bt_or.appendChild(bt_label);
bt_or.addEventListener('click', function() {
addFilter('or');
return false;
});
}
else{
var bt_rem= document.createElement("button");
bt_rem.id='rem_'+count;
var bt_label1 = document.createTextNode("x");
bt_rem.appendChild(bt_label1);
var tr_id = 'tr_'+count;
bt_rem.addEventListener('click', function() {
var element= document.getElementById(tr_id);
element.parentNode.removeChild(element);
return false;
});
}
tr.appendChild(and_or);
tr.appendChild(select);
tr.appendChild(sear_value);
if(count<=1){
tr.appendChild(bt_and);
tr.appendChild(bt_or);
}
else{
tr.appendChild(bt_rem);
}
div.appendChild(tr);
count++;
}
function getFilter(){
alert();
}
</script>
</head>
<body onload="loadfirst()">
<span id='manage_stud_header' class= 'list_header'>
<label><?php echo $module_name;?></label>
<center>
<form>
<div id='search_list' class='search'></div>
<button id="run_filter" type="submit">Run</button>
</form>
</center>
</span>
</body>
</html>
The default type for buttons is "submit", so you have to explicitly say you want a plain button:
var bt_and= document.createElement("button");
bt_and.type = "button";
This way it won't submit the form when clicked. (unless of course you tell it to :))
you have to change
<button id = "run_filter" type = "submit" > Run </button>
in
<input id = "run_filter" type = "submit" value="Run" />
and then if the behaviour of click on button is forced to reload the page try to change button on other form element or see e.preventdefaulT of jquery

jQuery selector + variable target match

HTML
<form id="myForm">
<input type="text" id="fname">
<input type="text" id="sname">
<input type="text" id="email">
<input type="tel" id="phone">
<select id="status">
<option>1</option>
<option>2</option>
<option>3</option>
<option>4</option>
</select>
<input type="submit" value="send">
</form>
...
<div id="output_fname"></div>
<div id="output_sname"></div>
<div id="output_email"></div>
<div id="output_phone"></div>
<div id="output_status"></div>
Request:
Please help me figure out how to pass all the values from input, select, etc.. (what might show up in a form) into a "preview" (in this case - into the div's).
PS:I have tried this (force me to paste the script numbers of times i have inputs and matching output_ divs - at least with my knowledge today):
$("#fname").on("focusout",function(){
setTimeout($.proxy(function(){
$("#output_fname").text(this.value);
},this),10);
});
But is there a possibility to do something like:
<input type="text" class="grab-val" id="fname">
and then:
.val() from (all inputs)
.this class="grab-val" and
send to (output_ + matching id)........ //something like that
OR (sorry for all the back and forward, but with this question I want to solve a problem but I also kindly ask for a lesson...)
What would a good solution be to create a preview on submit - before sending data into db. Data sent after a "is-the-data-correct-"-submit-button.
You can just give your preview divs a class of "preview"
<div class="preview" id="output_fname"></div>
<div class="preview" id="output_sname"></div>
<div class="preview" id="output_email"></div>
<div class="preview" id="output_phone"></div>
<div class="preview" id="output_status"></div>
Then on the preview button submit
$('.preview').text(function(){
return $('#' + this.id.replace('output_','')).val();
});
I've created two JS Fiddles:
This one updates the preview realtime: http://jsfiddle.net/ChrisBerragan/zcspmfmd/5/
..and this displays the preview on submit: http://jsfiddle.net/ChrisBerragan/ub3y4ycj/15/
The realtime one has a function to bind the value of the registered input id to the text of the registered target id:
function bindToElement(sourceElement, targetElement) {
var source = jQuery('#' + sourceElement),
sourceType = source[0].tagName,
target = jQuery('#' + targetElement);
switch (sourceType) {
case 'INPUT':
source.on('keyup', function (event) {
var sourceValue = event.target.value;
target.text(sourceValue);
});
break;
case 'SELECT':
target.text(source.val());
source.on('change', function (event) {
var sourceValue = event.target.value;
target.text(sourceValue);
});
break;
}
}
bindToElement('fname', 'output_fname');
bindToElement('sname', 'output_sname');
bindToElement('email', 'output_email');
bindToElement('phone', 'output_phone');
bindToElement('status', 'output_status');
.. but a simple loop would allow you to save the repetition.
The preview on submit version has a function to convert a form into a previewable form - you simply provide the function with the formId and the previewAreaId and when the preview button is click it runs a showPreview function that finds every element in the form that is an input or a select and that isn't an input type 'button' and creates a div in the preview area with the value and adds a submit button to the form to confirm:
function previewOnSubmit (formId, previewAreaId) {
var form = jQuery('#' + formId),
previewButton = jQuery('#previewFormButton'),
formInputs = form.children().filter(function (index, element) {
var tag = element.tagName,
inputType = jQuery(element).attr('type'),
tagIsValidInput = (tag === 'INPUT' && inputType !== 'button') || tag === 'SELECT';
return tagIsValidInput;
}),
preview = jQuery('#' + previewAreaId);
function showPreview () {
var confirmationButton = jQuery('<input type="submit" value="Confirm" />');
preview.empty();
jQuery.each(formInputs, function (index, element) {
var value = element.value,
inputPreview = jQuery('<div>' + value + '</div>');
preview.append(inputPreview);
});
form.append(confirmationButton);
}
previewButton.on('click', function (event) {
event.preventDefault();
showPreview();
});
}
previewOnSubmit('myForm', 'myFormPreview');
Hope these help!

Categories