I've created a portion of my content through using jQuery to make the same content for each item in my list. It has all worked perfectly except for the last entry. For some reason it acts weird.
An input field is created for each entry that only accepts 2 characters. I have an error script that will parse the entry and see if it's valid. I am only accepting numbers below 61 in this case. All the inputs work except for the last entry.
Additionally, the labels for the 3 inputs created are not putting focus on the respected input value for this entry.
My problem is I don't know why the last entry doesn't work whereas the others will. Can someone explain?
Below are a few functions used.
Populate.js (Used to create content from list)
var $parent = $('div#heroes');
var prestige = '<option value="0">None</option><option value="1">Prestige 1</option><option value="2">Prestige 2</option><option value="3">Prestige 3</option><option value="4">Prestige 4</option><option value="5">Prestige 5</option>'
$.each(heroes, function(index,value) {
$div = $('<div id="hero' + index + '"></div>');
$div.append('<h6>' + value + '</h6>');
$div.append('<span id="active"><input type="checkbox" id="isActive' + index + '" /><label for="isActive' + index + '">Is Active?</label></span>');
$div.append('<span id="level"><label for="level' + index + '">Level: </label><input type="text" size="2" maxlength="2" id="level' + index + '" /></span>');
$div.append('<span id="prestige"><label for="prestige' + index + '">Prestige: </label><select id="prestige' + index + '">' + prestige + '</select></span>');
$parent.append($div);
});
errors.js (Parses the input value and prints the error if not a integer below 61)
$.each(heroes, function(index,value){
$('input#level' + index).change(function() {
var val = $('input#level' + index).val();
if(val > 60) {
alertify.log("Hero " + value + " cannot be above Level 60!", "", 0);
$('#level' + index).addClass('error');
} else if( isNumeric(val) ) {
if( $('#level' + index).hasClass('error') ) {
$('#level' + index).removeClass('error');
}
} else {
alertify.log("Only numbers are accepted.");
$('#level' + index).addClass('error');
}
});
});
function isNumeric(num){
return !isNaN(num);
}
The list used:
var heroes = ["Black Panther","Black Widow","Cable","Captain America","Colossus","Cyclops","Daredevil","Deadpool",/*"Doctor Strange",*/"Emma Frost",
"Gambit","Ghost Rider","Hawkeye","Hulk","Human Torch","Iron Man","Jean Grey",/*"Juggernaut",*/"Loki","Luke Cage",/*"Magneto","Moon Knight",*/"Ms Marvel",
"Nightcrawler",/*"Nova","Psylocke",*/"Punisher","Rocket Raccoon",/*"Silver Surfer",*/"Scarlet Witch","Spider-Man","Squirrel Girl",/*"Star-Lord",*/"Storm",
/*"Sue Storm",*/"Thing","Thor","Wolverine"/*,"Venom"*/];
You can view the page at http://spedwards.cz.cc/new.html
I am still accepting answers. I am stumped to why this isn't working as expected.
Ok I figured out my problem. I'm using the bx-slider plugin and it creates a clone of the last element before the first and a clone of the first, after the last. So my function was getting the clone.
All I had to do was add :not(.bx-clone) to the selector.
So instead of $('input#level' + index); it changed to $('input#level' + index + ':not(.bx-clone)');
Related
Goal: Show a label, and input value from a different div and display it in a different section
I have a div that dynamically generates a set of input fields, and I am trying to then display that input fields value and their corresponding labels in a different section.
For example:
Step 1 - User enters in the number 5 into an input field.
Step 2 - There are 5 input fields created (based on value entered from step 1). Those input fields are labeled #1, #2, #3, etc... all the way to #5 or whatever number the user entered in Step 1.
Step 3 - User is presented with a new HTML section that lists off the labels (#1, #2, #3, etc.) and next to the labels is the value the user entered for those corresponding input fields.
Here is the code created for Step 2:
<label>#' + count + '</label>
<input type="number" name="length_field" value="" class="form-control length_field" />
Then, I need some javascript/jquery to take the labels and their corresponding input values and display then something like this:
<p>[LABEL #1] <span>[LABEL #1 INPUT VALUE]</span></p>
<p>[LABEL #2] <span>[LABEL #2 INPUT VALUE]</span></p>
<p>[LABEL #3] <span>[LABEL #3 INPUT VALUE]</span></p>
Etc...
For step 2 you need to check the value of your length_field input and create that many inputs by JavaScript. Set some helper ID and CLASS attributes so you can get values later.
For step 3 use that attributes to get input field values and set them as result div's html.
$(document).on('change', '#length_field', function() {
var inputsCount = parseInt($(this).val());
$('#inputsWrapper').html('');
$('#result').html('');
for (var i = 1; i <= inputsCount; i++) {
// Create custom input with label
var tempInput = document.createElement('input');
tempInput.setAttribute('name', i);
tempInput.setAttribute('id', i);
tempInput.setAttribute('class', 'customInputs');
var tempInputLabel = document.createElement('label');
tempInputLabel.setAttribute("for", i);
tempInputLabel.innerHTML = 'Input #' + i + ": ";
$('#inputsWrapper').append(tempInputLabel);
$('#inputsWrapper').append(tempInput);
// Create corresponding value presenter in result div
var resultRow = document.createElement('p');
resultRow.setAttribute('id', 'result-' + i);
resultRow.innerHTML = 'Label #' + i + ':';
$('#result').append(resultRow);
}
});
$(document).on('keyup', '.customInputs', function() {
var id = $(this).attr('id');
var inputValue = $(this).val();
$('#result-' + id).html('Label #' + id + ': <span> ' + inputValue + '</span>');
});
#inputsWrapper input {
display: block;
margin-bottom: 10px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<label for="length_field">Enter the number of inputs you want:</label>
<input type="number" name="length_field" id="length_field" />
<br/>
<div id="inputsWrapper">
</div>
<hr>
<div id="result">
</div>
This is really quick'n'dirty but it works.
I'm using a for-loop in both steps, in the first step the for-loop is generating the input fields and outputting them after.
In the second step I'm saving the html of the resulting paragraphs in a variable, because I can't override the document, because my wanted values are in the input fields.
The on keypress listener is optional and ensures that you don't have to press the Submit button with your mouse ;)
If I could help you i would appreciate if you could mark this answer as accepted.
let number = 0;
$(document).on("click", "#step1", function() {
number = $("input").val();
if (number > 0) {
let html = "", i;
for (i = 1; i <= number; i++) {
html += "<label for='input_" + i + "'>#" + i + "</label>: <input type='text' id='input_" + i + "'><br>";
}
html += "<button id='step2'>Submit</button>"
$("body").html(html);
}
})
$(document).on("click", "#step2", function() {
let html = "", i;
for (i = 1; i <= number; i++) {
html += "<p>Label #" + i + ": <span>" + $("#input_" + i).val() + "</span></p>";
}
$("body").html(html);
})
$(document).on('keypress', function(e) {
if (e.which == 13) {
$("button").trigger("click");
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<input type="number" placeholder="Number of fields">
<button id="step1">Submit</button>
I have a dynamic input field that gets appended after a plus button.
The corresponding id of these fields are answer0, answer1, answer2 and so on. That means after button click the id will be dynamically appended to the text field.
Now I want to validate these fields. My validation code is as follows
function showValidation(response) {
var respArray = JSON.parse(response.responseText).errors;
for(var i=0;i<=(Object.keys(respArray).length);i++){
var optionss= 'Enter Answers.';
if($("#answer"+i).val()==''){
$('#answer'+i+' + span').html('');
$('#answer'+i).after('<span class="' + errTextboxClass + '" style="color:#e03b3b">' + optionss+ '</span>');
$('#answer'+i).focus();
}
}
}
I am checking till response error length. But before giving values in these fields, validation works properly(fig 1). But if I enter values for first 2 fields as in the image above, the validation message does not shows for the third field (fig 2). Because at this stage the id is answer2 and the loop 'i' value checks 0 first and next checks 1. So inside loop answer0 and answer1 are having values so the validation stops there. I need to get validation for the next fields too. Thanks in advance.
My HTML and corresponding append function
<input class="form-control" name="answer0[]" id="answer0" placeholder="OPTION 1">
<a class="add-option" onclick="AppendOption()"><img src="{{asset('admin/images/icn-add-option.png')}}" alt=""></a>
function AppendOption(){
var k=1;
$('#appendOption').append('<div class="form-group row"><div class="col-md-4"><input class="form-control" name="answer0[]" id="answer'+k+'" placeholder="OPTION" ></div></div>');
k++;
}
In your AppendOption function, you set k=1 This is an invalid option once you reach the third entry (option 2). You should instead detect that, better yet still make it context sensitive when it executes. I did this by adding a answer-item class and detecting how many we have and using that number instead.
I wrapped all this in a <div id="options-container"> so I would have a place to hook the event handler (delegateTarget) https://api.jquery.com/event.delegateTarget/
I would not have used an ID here and instead used classes, but that is not part of the question but more rather the cause of it.
$('.options-container').on('click','.add-option',function(event){
let k= $(event.delegateTarget).find('.answer-item').length;
$(event.delegateTarget).append('<div class="form-group row"><div class="col-md-4"><input class="form-control answer-item" name="answer0[]" id="answer' + k + '" placeholder="OPTION" ></div></div>');
});
function showValidation(response) {
var respArray = JSON.parse(response.responseText).errors;
for (var i = 0; i <= (Object.keys(respArray).length); i++) {
var optionss = 'Enter Answers.';
if ($("#answer" + i).val() == '') {
$('#answer' + i + ' + span').html('');
$('#answer' + i).after('<span class="' + errTextboxClass + '" style="color:#e03b3b">' + optionss + '</span>');
$('#answer' + i).focus();
}
}
}
<div id="options-container">
<input class="form-control answer-item" name="answer0[]" id="answer0" placeholder="OPTION 1">
<a class="add-option"><img src="{{asset('admin/images/icn-add-option.png')}}" alt=""></a>
</div>
If the fields are required you should mark them as required otherwise you validate every field. In your case another way for validating could look like this
function showValidation(response) {
var respArray = JSON.parse(response.responseText).errors;
$('.form-group input.form-control').each(function(){
if ($(this).val() == '') {
$(this).next('span').html('');
$(this).after('<span class="' + errTextboxClass + '" style="color:#e03b3b">' + optionss+ '</span>');
$(this).focus();
}
});
}
Since I don't know how and where the showValidation() is called I can't improve it further.
I tried to display the error messages inside an input array loop and I got the answer.
var result = document.getElementsByTagName("input");
var optionss= 'Enter Answers.';
for (var j = 0; j < result.length; j++) {
if($("#answer"+j).val()==''){
$('#answer'+j+' + span').html('');
$('#answer'+j).after('<span class="' + errTextboxClass + '" style="color:#e03b3b">' + optionss+ '</span>');
$('#answer'+j).focus();
}
I'm using a set of arrays to populate some radio selects on a page
//holds the set value of the variable
var universalVariables = [thing1, thing2, thing3];
//used for the classes in the radios to get values later
var universalNames = ['thing1','thing2','thing3'];
//used to put a label on each radio
var universalAttributes = ['THING ONE', 'THING TWO', 'THING THREE'];
Followed by:
$.each(universalVariables, function(index, val) {
$('#universalAttributes').append('<br />' + universalAttributes[index] + '<br /><div class="radio"><label><input type="radio" name="' + universalNames[index] + '" value="false">FALSE</label></div><div class="radio"><label><input type="radio" name="' + universalNames[index] + '" value="true">TRUE</label></div>')
});
//set data
$.each(universalVariables, function(index, val) {
if (universalVariables[index] == false) {
$("input[name=" + universalNames[index] + "][value=false]").prop('checked', true);
} else if (universalVariables[index] == true) {
$("input[name=" + universalNames[index] + "][value=true]").prop('checked', true);
}
});
This creates three (because there are three variables in my arrays) radios, but obviously can handle as many as you want. All you need to do is supply the information in the arrays (versus coding the radio selects themselves).
The three pieces of information here
The problem comes in when you have to add a variable. Ideally, I'd like to generate the first two arrays. I could supply the list of words and then generate. The trick (for me anyway) is doing this where one array has string names and the other needs the variable NAMES not the variable VALUES.
There has to be a simple way of doing this. Open to any suggestions.
You can store the "metadata" of the variables in an object, and access them by a key that matches up with the variable name, like so:
You can also set the checked property at the same time you append the input to the container, eliminating the need for that second loop.
var universalVariables = {
"thing1": {
value: true,
attribute: "THING ONE"
},
"thing2": {
value: false,
attribute: "THING TWO"
},
"thing3": {
value: true,
attribute: "THING THREE"
},
};
// used so we can guarantee correct sequential order
var universalNames = ['thing1','thing2','thing3'];
$.each(universalNames, function(index, name) {
var objVar = universalVariables[name];
$('#universalAttributes')
.append('<br />' + objVar.attribute +
'<br /><div class="radio"><label><input type="radio" name="' + name +
'" value="false"' + (objVar.value ? '' : 'checked') + '>FALSE</label></div><div class="radio"><label><input type="radio" name="' + name +
'" value="true"' + (objVar.value ? 'checked' : '') + '>TRUE</label></div>')
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="universalAttributes"></div>
I'm trying to assign variable value to dynamically created input elements. But I couldn't. The input elemts are created but not with id.
$(document).ready(function(){
// Declaring global variables
var cnt = 1;
var fooId = "foo";
var cnt1 ='aaaa';
// Code for Changing the datalist for second input testingphase when ever first input Tasks has been changed.
$("#tasks" + cnt).change(function () {
$("#activitytype" + cnt).replaceWith('<input id="activitytype" + ctn value="asasa" name="ActivityType" placeholder="ActivityType" >');
if (bla1 == 'Service Request') {
$("#testingphase" + cnt).replaceWith('<input id="testingphase" + ctn list="Service Request" name="Tasks" placeholder="Tasks2">');
// changingactivity ();
}
You have to change your replaceWith method slightly to include the variable without quotes. Change:
$("#activitytype" + cnt).replaceWith('<input id="activitytype" + ctn value="asasa" name="ActivityType" placeholder="ActivityType" >');
To something like:
$("#activitytype" + cnt).replaceWith('<input id="activitytype' + ctn + '" value="asasa" name="ActivityType" placeholder="ActivityType" >');
I have this fiddle which is having user tab.In user tab ,there are three fields which accepts name,mobile and email.When a user fills all the three and hits add button then a row is inserted.Now i want to make the new added row editable.This means that I want to keep 2 bootstrap buttons edit and delete.So if delete is pressed then the entire row will be deleted and if edit is pressed then the entire will be editable where user can change the mobile number,name and email.Can any body please tell me how to do.
This js code adds new rows
$('#btn1').click(function () {
if ($(".span4").val() != "") {
$("#mytable").append('<tr id="mytr' + val + '"></tr>');
$tr=$("#mytr" + val);
$tr.append('<td class=\"cb\"><input type=\"checkbox\" value=\"yes\" name="mytr' + val + '" unchecked ></td>');
$(".span4").each(function () {
$tr.append("<td >" + $(this).val() + "</td>");
});
var arr={};
name=($tr.find('td:eq(1)').text());
email=($tr.find('td:eq(2)').text());
mobile=($tr.find('td:eq(3)').text());
arr['name']=name;arr['email']=email;arr['mobile']=mobile;
obj[val]=arr;
val++;
} else {
alert("please fill the form completely");
}
This question is so specific to the OP scenario, so i will try to make the answer a bit more general.
I'm no expert here, but it seems you already capture the user's input and cloned it when they click Add to a new td. Therefore from what I understood is that you need to edit/delete the data from the new created td.
We have a table that contains several fields. We want to apply the following action on them
1- Add
2- Edit
3- Delete
Maybe this isn't the best practice, in short, my approach for this was to insert two spans for each data value:
One hidden that contains an input text field (inputSpan).
Another just contains plain text value (dataSpan).
Whenever you want to edit, dataSpan (just a data container) will disappear and inputSpan (text input field) appears instead enabling you to edit the text field. Once you edit and click Save the data in the text field will be cloned to replace the data in dataSpan. So basically dataSpan is just a reflection to inputSpan text field.
Here is an updated demo:
JSFiddle >> FullView Fiddle
I suggest for readability purposes, you break your code down into small function, it will make life easier, just sayin. So here general logic for your idea:
deleteRow = function (trID) {
// delete code goes here, remove the row
$(trID).remove();
}
manageEdit = function (tdNo) {
if ($("#edit-btn" + tdNo).html() === "Edit") {
$("#save-btn" + tdNo).show();//show save button
$("#edit-btn" + tdNo).html("Cancel");//change edit to cancle
editRow(tdNo);//call edit function
} else if ($("#edit-btn" + tdNo).html() === "Cancel") {
$("#save-btn" + tdNo).hide();//hide save button
$("#edit-btn" + tdNo).html("Edit");//change back edit button to edit
cancelEditRow(tdNo);
}
}
editRow = function (tdNo) {
$(".inputSpan" + tdNo).show();//show text input fields
$(".dataSpan" + tdNo).hide();//hide data display
}
cancelEditRow = function (tdNo) {
//looop thru 3 input fields by id last digit
for (var i = 0; i < 3; i++) {
//get input span that contain the text field
var inputSpan = $("#inputSpan" + tdNo + "-" + i);
//get the data span that contain the display data
var dataSpan = $("#dataSpan" + tdNo + "-" + i);
//text field inside inputSpan
var textField = inputSpan.find('input:text');
inputSpan.hide();//hide input span
textField.val(dataSpan.html());//take original data from display span and put it inside text field to cncle changes.
dataSpan.show();//show data span instead of edit field
}
}
saveRow = function (tdNo) {
//same as edit, but we reverse the data selection.
for (var i = 0; i < 3; i++) {
var inputSpan = $("#inputSpan" + tdNo + "-" + i);
var dataSpan = $("#dataSpan" + tdNo + "-" + i);
var textField = inputSpan.find('input:text');
inputSpan.hide();
dataSpan.html(textField.val());//take data from text field and put into dataSpan
dataSpan.show();
}
$("#edit-btn" + tdNo).html("Edit");//change text to edit
$("#save-btn" + tdNo).hide();//hide same button.
}
Here where I add the spans:
var tdCounter = 0;
$(".span4").each(function () {
var tid = val+"-"+tdCounter;
$tr.append("<td id='#mytd"+tid+"'>
<span id='inputSpan"+tid+"' class='inputSpan"+val+"' style='display:none'>
<input type='text' id='#input"+tid+"' value='"+ $(this).val() + "' /></span>
<span id='dataSpan"+tid+"' class='dataSpan"+val+"'>"+$(this).val()+"</td>");
tdCounter++;
});
Here I just append the buttons to call the functions, each button works for it's own row:
$tr.append("<td><botton id='edit-btn" + val + "' class='btn' onclick=manageEdit('" + val + "');>Edit</botton></td>");
$tr.append("<td><botton style='display:none' id='save-btn" + val + "' class='btn' onclick=saveRow('" + val + "');>Save</botton></td>");
$tr.append("<td><botton id='delete-btn" + val + "' class='btn' onclick=deleteRow('" + trID + "');>Delete</botton></td>");
Below is a sample function, it wont do everyhing you need, but it shows the jquery functions and one possibility how to do it. I only enabled editing name field, and deleting.
You would have to add other fields, + copy id data for the input.
js Fiddle
window.deleteRow = function (tar) {
$(tar).parent().remove();
}
window.editRow = function (tar) {
var row = $(tar).parent(),
cells, name;
cells = row.find("td");
name = $(cells.get(1)).text();
$(cells.get(1)).text('');
$(cells.get(1)).append('<input type="text" value="' + name + '">');
}
window.saveData = function() {
var data = {};
data.name = "some name";//get this from your input
data.email= "some email";//get this from your input
data.phone= "some phone";//get this from your input
$.get("http://yourphpsite.com", data, function(data, status) {
//data contains your server response
if (data.somepositiveservermessage) {
$("#user_notification_field").text("data saved");
$("#user_notification_field").show();
});
}