jQuery selector + variable target match - javascript

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!

Related

tab key focus next empty input in a grid

What I'm trying to achieve is that when tab key is pressed, the cursor will be focused on the next empty input in a grid component. Input field that has value will be skipped. If the cursor currently is in input field 2, and input field 3 has value, when tab is pressed, the cursor will jump to input field 4. This is to speed up the form entry time.
Below is the html grid component that I have created
<div class="col-md-6" id="dcNonRetainValue">
<fieldset class="ES-border frame-height-collapsed">
<legend class="ES-border">{{ 'Data Collection' }} </legend>
<collect-paged-data data="ui.dataCollectionItems" currentPage="ui.dataCollectionItemsCurrentPage" pageSize="ui.dataCollectionPageSize">
</collect-paged-data>
</fieldset>
Trying to focus next input element with js.
setTimeout(function () {
$('#dcNonRetainValue *:input:empty').focus();
}, 50);
It does not seem to work correctly. Any feedback is appreciated.
You can use filter function to select all the empty inputs. Then use eq function to select first input and use focus function. You can do like below Example:
$(document).ready(function() {
$('input').on( 'keydown', function( e ) {
if( e.keyCode == 9 ) {
const allEmptyInput = $('input').filter(function() {
return $(this).val() === "";
});
// Return if there is no Empty Input
if (allEmptyInput.length === 0) return;
e.preventDefault();
const currentInput = $(e.target);
const nextAllEmptyInput = currentInput.nextAll('input').filter(function() {
return $(this).val() === "";
});
// Focus on first input if last is focus
if (nextAllEmptyInput.length === 0) {
allEmptyInput.eq(0).focus();
return;
}
const firstEmptyInput = nextAllEmptyInput.eq(0);
firstEmptyInput.focus();
}
});
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.2.4/jquery.min.js"></script>
<label>First Input</label><br/>
<input type="text"/>
<br/>
<label>Second Input</label><br/>
<input type="text"/>
<br/>
<label>Third Input</label><br/>
<input type="text"/>
Using id will only give you the first element with that id. Use class instead.

focusout handler also fires on focusin

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>

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>

Same function for different sections - relative referencing in jquery

By using relative references I am able to remove items which have been added to the list within a specfic part of the form. For example, by adding a requirement it can be deleted just from the requirement.
My issue is two fold:
Adding an item to references adds it to all three categories
When I try to add values to the other sections (qualifications) it says my input was blank.
http://jsfiddle.net/spadez/9sX6X/60/
var container = $('.copies'),
value_src = $('#current'),
maxFields = 10,
currentFields = 1;
$('.form').on('click', '.add', function () {
value_src.focus();
if ($.trim(value_src.val()) != '') {
if (currentFields < maxFields) {
var value = value_src.val();
var html = '<div class="line">' +
'<input id="accepted" type="text" value="' + value + '" />' +
'<input type="button" value="X" class="remove" />' +
'</div>';
$(html).appendTo(container);
value_src.val('');
currentFields++;
} else {
alert("You tried to add a field when there are already " + maxFields);
}
} else {
alert("You didn't enter anything");
}
})
.on('click', '.remove', function () {
value_src.focus();
$(this).parents('.line').remove();
currentFields--;
});
Is it possible to modify this code without repeating it for each section, by using relatively references such as "parent" for example. I want to use this same script for all three sections but have it so each list is independant.
I'm new to javascript so I was wondering if this is possible because I only managed to get it working on the delete.
You have to use this to get the current element. In your case this refers to the button which was clicked.
The next step is to get the input box which belongs to the button. E.g. $(this).prev(); like in this example:
$('.form').on('click', '.add', function () {
var value_src = $(this).prev();
http://jsfiddle.net/9sX6X/62/
The same is also true for your appending part. Your are appending your html to all three elements which match $('.copies'). Instead you have to try to get there from this.
$('.form').on('click', '.add', function () {
var value_src = $(this).prev();
var copies = $(this).parent().prev();
http://jsfiddle.net/9sX6X/63/
I would suggest adding a wrapping div to each section.
<div class="section">
<h4>Requirements</h4>
<div class="copies"></div>
<div class="line">
<input id="current" type="text" name="content" placeholder="Requirement" />
<input type="button" value="Add" class="add" />
</div>
</div>
Then you can do this:
var $section = $(this).closest(".section");
$(html).appendTo($section.find(".copies"));
This will add to just the related .copies element instead of to all .copies as your code does now. A similar approach can be used for all other elements as well.

Add (and remove) group of textelements dynamically from a web form using javascript/jquery

im very new at javascipt (im php developer) so im really confused trying to get this working.
In my web form i have 3 textfields (name, description and year) that i need to let the user add as many he needs, clicking on a web link, also, any new group of text fields need to have a new link on the side for removing it (remove me).
I tried some tutorial and some similar questions on stackoverflow but i dont get it well. If you can show me a code example just with this function i may understand the principle. Thanks for any help!
this is the simplest thing that has come to my mind, you can use it as a starting point:
HTML
<div class='container'>
Name<input type='text' name='name[]'>
Year<input type='text' name='year[]'>
Description<input type='text' name='description[]'>
</div>
<button id='add'>Add</button>
<button id='remove'>Remove</button>
jQuery
function checkRemove() {
if ($('div.container').length == 1) {
$('#remove').hide();
} else {
$('#remove').show();
}
};
$(document).ready(function() {
checkRemove()
$('#add').click(function() {
$('div.container:last').after($('div.container:first').clone());
checkRemove();
});
$('#remove').click(function() {
$('div.container:last').remove();
checkRemove();
});
});
fiddle here: http://jsfiddle.net/Fc3ET/
In this way you take advantage of the fact that in PHP you can post arrays: server side you just have to iterate on $_POST['name'] to access the various submissions
EDIT - the following code is a different twist: you have a remove button for each group:
$(document).ready(function() {
var removeButton = "<button id='remove'>Remove</button>";
$('#add').click(function() {
$('div.container:last').after($('div.container:first').clone());
$('div.container:last').append(removeButton);
});
$('#remove').live('click', function() {
$(this).closest('div.container').remove();
});
});
Fiddle http://jsfiddle.net/Fc3ET/2/
jsFidde using append and live
String.format = function() {
var s = arguments[0];
for (var i = 0; i < arguments.length - 1; i++) {
var reg = new RegExp("\\{" + i + "\\}", "gm");
s = s.replace(reg, arguments[i + 1]);
}
return s;
}
var html = "<div>" + '<input name="name{0}" type="text" />' + '<input name="description{1}" type="text" />' + '<input name="year{2}" type="text" />' + '<input type="button" value="remove" class="remove" />' + '</div>',
index = 0;
$(document).ready(function() {
$('.adder').click(function() {
addElements();
})
addElements();
$('.remove').live('click', function() {
$(this).parent().remove();
})
});
function addElements() {
$('#content').append(String.format(html, index, index, index));
index = index + 1;
}
Look at this: http://jsfiddle.net/MkCtV/8/ (updated)
The only thing to remember, though, is that all your cloned form fields will have the same names. However, you can split those up and iterate through them server-side.
JavaScript:
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.6.2/jquery.min.js"></script>
<script type="text/javascript">
$(function() {
$("#addnew").click(function(e) {
$("#firstrow").clone() // copy the #firstrow
.removeAttr("id") // remove the duplicate ID
.append('<a class="remover" href="#">Remove</a>') // add a "remove" link
.insertAfter("#firstrow"); // add to the form
e.preventDefault();
});
$(".remover").live("click",function(e) {
// .live() acts on .removers that aren't created yet
$(this).parent().remove(); // remove the parent div
e.preventDefault();
});
});
</script>
HTML:
Add New Row
<form id="myform">
<div id="firstrow">
Name: <input type="text" name="name[]" size="5">
Year: <input type="text" name="year[]" size="4">
Description: <input type="text" name="desc[]" size="6">
</div>
<div>
<input type="submit">
</div>
</form>
Try enclosing them in a div element and then you can just remove the entire div.
Try this
Markup
<div class="inputFields">
..All the input fields here
</div>
Add
<div class="additionalFields">
</div>
JS
$("#add").click(function(){
var $clone = $(".inputFields").clone(true);
$clone.append($("<span>Remove</span").click(functio(){
$(this).closest(".inputFields").remove();
}));
$(".additionalFields").append($clone);
});
There are 2 plugins you may consider:
jQuery Repeater
jquery.repeatable
This question has been posted almost 4 years ago. I just provide the info in case someone needs it.

Categories