I have built a function using jQuery to insert into a table a new row including some inputs, like textboxes, checkboxes and one button.
This is the code I have:
$('#AddEntry').click(function () {
var lastTrClass = $('tr:last').attr('class');
var textBoxTitle = '<input id="titleid" type="text" value="" style="width: 100%; vertical-align: middle">';
var textBoxStartDate = '<input id="StartDate" type="text" class="required DatePicker" value="" style="width: 100%; vertical-align: middle">';
var checkBoxSync = '<input id="Sync" type="checkbox" checked="checked" disabled="disabled" value="true" style="vertical-align: middle">';
var lastDate = '<input id="LastSyncDate" class="required DatePicker" type="text" value="" style="width: 100%; vertical-align: middle">';
var buttonEdit = '<button id="btnEditar" class="EditButton icon_only text_only" style="vertical-align: middle;" type="button">Editar</button>';
if (lastTrClass == 'gradeA odd') {
$('#DataTable > tbody:last').append("<tr class='gradeA even'><td>#</td><td>" + textBoxTitle + "</td><td>" + textBoxStartDate + "</td><td>" + checkBoxSync + "</td><td>" + lastDate + "</td><td>" + buttonEdit + "</td></tr>");
}
else {
$('#DataTable > tbody:last').append("<tr class='gradeA odd'><td>#</td><td>" + textBoxTitle + "</td><td>" + textBoxStartDate + "</td><td>" + checkBoxSync + "</td><td>" + lastDate + "</td><td>" + buttonEdit + "</td></tr>");
}
})
As you can see in my code, I'm generating the inputs into a var, but my question is whether or not this is safe. Is my code vulnerable to a JS injection or something like that? Is there a better way to do this?
All of this happens on the client so you're code should be fine. You may want to check out client templating for this sort of thing though - then you can scrap the vars altogether and editing the html will be more pleasurable. I use jqote when I need to render relatively complex stuff from javascript.
Related
I have an html form. Whenever i click add button another copy of it appends. Whenever i click add button, id of my elements increases such as username_0, username_1, username_2... There are 2 radio buttons on my form that whenever i choose second radio button, a hidden textarea appears. Problem is i'm having problem with choosing my dynamic id's of radio buttons. I made a function but its only working for first element since i can't get dynamic id's
<label for="evetKontrol_0">Evet</label>
<input type="radio" id="evetKontrol_0" name="uygun_0" onclick="javascript:yesnoCheck();" value="uygun" checked>
<label for="hayirKontrol_0">Hayır</label>
<input type="radio" id="hayirKontrol_0" name="uygun_0" onclick="javascript:yesnoCheck();" value="uygunDegil">
<div id="ifNo_0" style="visibility:hidden">
<strong>Uygun Olmama Sebebi:</strong> <input type="textarea" id="hayirSebep_0" name="hayirSebep" style="height: 75px"><br>
</div>
function yesnoCheck() {
if (document.getElementById('evetKontrol_0').checked) {
document.getElementById('ifNo_0').style.visibility = 'hidden';
}
else document.getElementById('ifNo_0').style.visibility = 'visible';
}
I need to be able to get my evetKontrol_#somenumber for my function for every copy of my form.
JSfiddle/ all of my code
I tried to use jQuery( "[attribute*='value']" ) but i couldn't manage to work it out.
Consider the following.
Working Example: https://jsfiddle.net/Twisty/sonvakq2/21/
JavaScript
$(function() {
function addElement(tObj) {
var counter = $("[id^='ogrenci']", tObj).length;
var html = '<div class="col-auto" id="ogrenci_' + counter + '"><label for="ad">Ad</label><input type="text" name="ad[]" class="form-control" id="ad_' + counter + '" placeholder="Öğrencinin Adı"/><label for="soyad">Soyad</label><input type="text" name="soyad[]" class="form-control" id="soyad_' + counter + '" placeholder="Öğrencinin Soyadı"/><label for="no">No</label><input type="text" name="numara[]" class="form-control" id="no_' + counter + '" placeholder="Öğrencinin Numarası"><label for="course">Bölümü</label><input type="text" name="bolum[]" class="form-control" id="course_' + counter + '" placeholder="Öğrencinin Bölümü"><label for="alKredi">Almak İstediği Kredi</label><input type="text" name="alKredi[]" class="form-control" id="alKredi_' + counter + '" placeholder="Almak İstediği Kredi"><label for="verKredi">Alabileceği Kredi</label><input type="text" name="verKredi[]" class="form-control" id="verKredi_' + counter + '" placeholder="Alabileceği Kredi"><label for=""><strong>Uygun mu?</strong> </label><br><label for="evetKontrol_' + counter + '">Evet</label><input type="radio" id="evetKontrol_' + counter + '" name="uygun_' + counter + '" value="uygun" checked><label for="hayirKontrol_' + counter + '">Hayır</label><input type="radio" id="hayirKontrol_' + counter + '" name="uygun_' + counter + '" value="uygunDegil"><div id="ifNo_' + counter + '" style="visibility:hidden"><strong>Uygun Olmama Sebebi:</strong> <input type="textarea" id="hayirSebep_' + counter + '" name="hayirSebep" style="height: 75px"><br></div><div class="input-group-addon"><span class="glyphicon glyphicon glyphicon-remove" aria-hidden="true"></span> Remove</div></div>';
tObj.append(html);
}
function showHidden() {
$("[id^='evetKontrol']").each(function(i, el) {
var rel = $("#ifNo_" + i);
if ($(el).is(":checked")) {
rel.show();
} else {
rel.hide();
}
});
}
//add more fields group
$("#add").click(function() {
addElement($("#container"));
});
//remove fields group
$('#container').on('click', "a[id^='remove']", function() {
$(this).parents('div.col-auto').remove();
});
$("#container").on("click", "input[type='radio']", showHidden);
});
Your fiddle wasn't configured properly, so I addressed that first. I moved a lot of the repeatable items into Functions. Switched it all the jQuery and removed any of the local javascript calls.
You can see examples of how to use the Attribute selector in a relative manner to select items you want.
See More: https://api.jquery.com/category/selectors/attribute-selectors/
You shouldn't need to use IDs for this. Just capture the onclick event and pass a boolean to determine if the hidden input should be shown. If you have multiple inputs to show and hide separately, you could pass the ID of the input along with the boolean.
function yesnoCheck(show) {
var ta = document.getElementById('hiddenTA');
if (show) {
ta.style.visibility = 'visible';
} else {
ta.style.visibility = 'hidden';
}
}
<label for="user1_0">User 1</label>
<input type="radio" name="users" id="user1_0" onclick="yesnoCheck(false)" checked />
<label for="user2_0">User 2</label>
<input type="radio" name="users" id="user2_0" onclick="yesnoCheck(true)" />
<input style="visibility:hidden" id="hiddenTA" />
In order to get the evetKontrol_#somenumber, pass that number in the onclick function.
In your JSfiddle, this would mean concatenating the counter variable into the function parameters like
... onclick="javascript:yesnoCheck(' + counter + ');" ...
Then update the function to use that value:
function yesnoCheck(counter) {
if (document.getElementById('evetKontrol_' + counter).checked) {
document.getElementById('ifNo_' + counter).style.visibility = 'hidden';
} else {
document.getElementById('ifNo_' + counter).style.visibility = 'visible';
}
I have three check boxes with two is auto selected and I am displaying the text field with a label which check box is selected.
But after clicking on preview from I am getting input field twice. I mean I am getting four text field instated of two.
There is some issue with my ready script.Would you help me out in this?
<!--If any check box clicked then active this script-->
$(function() {
$(".add_student_input").change(function() {
if (this.checked) {
$(".students_items").append('<div class="form-group row ' + this.id + '"><label class="col-sm-4 col-form-label">' + $(this).next('label').text() + '</label><div class="col-sm-8"><input type="' + $(this).data('type') + '" name="input[]" placeholder="' + $(this).next('label').text() + '" class="form-control" /></div></div>');
} else {
$('.students_items').find('.' + this.id).remove();
}
});
});
<!--end script -->
$(document).ready( function(){
$checkbox=$(".add_student_input");
$checkbox.each(function(){
var isChecked = $(this).is(":checked");
if(isChecked) {
$(".students_items").append('<div class="' + this.id + '"><label>' + $(this).next('label').text() + '</label><input type="' + $(this).data('type') + '" name="input[]" placeholder="' + $(this).next('label').text() + '" class="form-control" /></div>');
} else {
//check false
$('.students_items').find('.' + this.id).remove();
}
});
});
/*form preview*/
function PrintPreview() {
var toPrint = document.getElementById('open_in_preview');
var popupWin = window.open('', '_blank');
popupWin.document.open();
popupWin.document.write('<html><title>::Print Preview::</title><link rel="stylesheet" type="text/css" href="Print.css" media="screen"/></head><body>')
popupWin.document.write(toPrint.innerHTML);
popupWin.document.write('</body></html>');
popupWin.document.close();
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
<body id="open_in_preview">
<input type="checkbox" name="a" id="class_1" class="add_student_input" data-type="text" checked><label for="class_1">number1</label>
<input type="checkbox" name="b" id="class_2" class="add_student_input" data-type="text" checked><label class="class_2">number2</label>
<input type="checkbox" name="c" id="class_3" class="add_student_input" data-type="text"><label class="class_3">number3</label>
Preview form
<span class="students_items"></span>
</body>
I am getting output like this.
as comment, why the script putting at the below of your page will cause multiple input, as when onload, it will run document ready and append again based on the checkbox, so to solve the issue, put empty() onto it will "reset" the input before append with a new 1
$(document).ready( function(){
$checkbox=$(".add_student_input");
$(".students_items").empty(); //add this to clear it
$checkbox.each(function(){
var isChecked = $(this).is(":checked");
if(isChecked) {
$(".students_items").append('<div class="' + this.id + '"><label>' + $(this).next('label').text() + '</label><input type="' + $(this).data('type') + '" name="input[]" placeholder="' + $(this).next('label').text() + '" class="form-control" /></div>');
} else {
//check false
$('.students_items').find('.' + this.id).remove();
}
});
});
update with another question by OP
please look at the plnkr
https://plnkr.co/edit/wnGWwcgAySrjfNQwqX3J?p=preview
the issue here is not related to empty(), it is how it behave on DOM ready(but i remove it as your question is different now), I had enhance your script so that it take only the needed tag, and also combine the script to make it clearer, please have a look, so in order to really read the checked behavior in the html, we need to add
this.setAttribute("checked", "checked");
this will force the checked is being render in the html, and also
$(function(){}) is the same as $(document).ready(function(){})
The following code is a snippet of a JavaScript append function:
var $newLi = $("<li><div1><img src='" + src + "' id='logo" + counter + "' name='logo" + counter + "'/></div1><div2><input type='text' id='college" + counter + "' name='college" + counter + "' value='" + task + "' readonly/></div2><div4><input type='text' id='sports" + counter + "' name='sports" + counter + "' value='" + sports + "' readonly/></div4><div5><input type='text' id='interest" + counter + "' name='interes" + counter + "' value='" + interest + "' readonly/></div5></li>");
The following is the html dropdown list:
<form name="newItem" id="newItem">
<select id="interestresults" required>
<option value="">Select Level of Interest...</option>
<option>Low</option>
<option>Medium</option>
<option>High</option>
<option>Extreme</option>
</select>
<button type="reset" id="reset">Reset</button>
<input type="button" id="addItem" value="Add" />
</form>
So, essentially, what is happening is a list is being appended on button click and is creating 4 div's. div1, div2, and div4 are of no concern. div5 though is what I am targeting.
div5 is created and displays "interest" text that was selected from a dropdown list and submitted. The interest options are "low", "medium", "high", and "extreme". At the moment, div5 css background is set to green, however, my question is how to set the div5 background color based on which interest option is selected from dropdown list. For example, if low was selected, div5 will be red and if extreme is selected, then div5 will be green.
Full JavaScript here:
$("#addItem").click(function() {
if (maxAppend >= 10) return;
var task = $('#searchresults').val();
var sports = $('#sportsresults').val();
var interest = $('#interestresults').val();
var src = $('#searchresults').find(":selected").attr('data-src');
var $newLi = $("<li><div1><img src='" + src + "' id='logo" + counter + "' name='logo" + counter + "'/></div1><div2><input type='text' id='college" + counter + "' name='college" + counter + "' value='" + task + "' readonly/></div2><div4><input type='text' id='sports" + counter + "' name='sports" + counter + "' value='" + sports + "' readonly/></div4><div5><input type='text' id='interest" + counter + "' name='interest" + counter + "' value='" + interest + "' readonly/></div5></li>");
$newLi.attr("id", "newLi" + counter++);
maxAppend++;
$("#tasks").append($newLi);
$('#searchresults').find(":selected").remove();
$('#sportsresults option').prop('selected', function() {
return this.defaultSelected;
});
});
$('#deleteall').click(function(e) {
$('#tasks').children().last().remove();
});
});
Looks like you skipped documentation on <select> tag and its purpose.
The <select> tag is used to allow the user to select an <option> which sets the value of its parent <select> to it.
Add value attributes to your <option> elements and use $('#interestresults').val() to get the currently selected value. Here's an arbitrary example, based on what I could make of your current code:
$(document)
.on('click', '#addItem', function () {
var ul = $('#results'),
select = $('#interestresults'),
color = select.val(),
text = select.find('option:selected').text();
if (color && 10 > ul.find('li').length) {
ul.append($('<li />', {
text: text,
style: "background-color:" + color
}))
}
})
.on('click', '#reset', function () {
$('#results').html('');
})
#results {
list-style-type:none;
color: white;
padding: 0;
}
#results li {
padding: .5rem;
border: 1px solid rgba(0,0,0,.12);
border-top: 1px solid rgba(255,255,255,.21)
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<form name="newItem" id="newItem">
<select id="interestresults" required>
<option value="">Select Level of Interest...</option>
<option value="red">Low</option>
<option value="orange">Medium</option>
<option value="blue">High</option>
<option value="green">Extreme</option>
</select>
<button type="reset" id="reset">Reset</button>
<input type="button" id="addItem" value="Add" />
</form>
<ul id="results">
</ul>
Why i can't getElementByName?
<form class="form" action="#">
<p class="EmptySlot" hidden>
<input name="characters" type="radio" id="empty" disabled="disabled"/>
<label for="empty">Пустой слот</label>
</p>
</form>
Then:
$(".form").append('\
<p>\
<input name="character" type="radio" id="' + notformatname + '" value="' + notformatname + '"/>\
<label for="' + notformatname + '" id="charlabel">' + formatname + '</label>\
</p>');
And it's don't work:
var radios = document.getElementsByName('character');
The method will return a collection, not a single Element. You may try...
$(".form")[0].append('\
<p>\
<input name="character" type="radio" id="' + notformatname + '" value="' + notformatname + '"/>\
<label for="' + notformatname + '" id="charlabel">' + formatname + '</label>\
</p>');
Should get the first form that belongs to the "form" class.
The second should work, but remember that "radios" will be a collection too.
.getElementsByName might return more than one element if multiple elements have the name of 'character'.
To get the first item in the list of returned elements, try:
var radios = document.getElementsByName('character')[0];
I have table with dynamic rows like
<table>
for(int i=0;i<=Modal.Count;i++)
{
<tr class="trList">
<td class="tdEmpid><input type="button" value="Insert row" class="btnInsert"/></td>
<td><input type="text" id="Sun_Hrs' + i + '" value="' + data.GetTimeSheetDetails[i].SUN_HRS + '" style = "width:50px;border: 0px;background-color: white;text-align: left;" readonly="true"/></td>
<td><input type="text" id="Mon_Hrs' + i + '" value="' + data.GetTimeSheetDetails[i].MON_HRS + '" style = "width:50px;border: 0px;background-color: white;text-align: left;" readonly="true"/></td>
<td><input type="text" id="Tue_Hrs' + i + '" value="' + data.GetTimeSheetDetails[i].TUE_HRS + '" style = "width:50px;border: 0px;background-color: white;text-align: left;" readonly="true"/></td>;
..........
..........
</tr>
}
Now, I want to add row where the button dynamically exactly to next row where button is clicked , for that i have written jquery code
$(document).ready(function(){
$('.btnInsert').live('click',function(){
var html = '<tr class="trNeedTimesheet"><td></td><td></td></td><td><p style="background-color:white;">-- Need To Enter TImesheetHours</b> -------</p></td></tr>';
$("" + html + "").insertAfter($(this).parent('td.tdEmpId').parent('tr.trList'));
});
});
It is not only adding , but it should insert and work same like slidetoggle functionality.
How can I do that?
parent() don't accept argument but parents() do.
Change this line
$("" + html + "").insertAfter($(this).parent('td.tdEmpId').parent('tr.trList'));
to
$("" + html + "").insertAfter($(this).parents('tr.trList'));
Demo
Edit : updated toggle functionality.
jQuery :
$(document).on('click','.btnInsert', function(){
var $nextTr = $(this).parents('tr.trList').next();
var newTrExist =$nextTr.hasClass('newTr');
if(newTrExist)
{
$nextTr.toggle();
}
else
{
var html = '<tr class="newTr trNeedTimesheet"><td></td><td></td></td><td><p style="background-color:white;">-- Need To Enter TImesheetHours</b> -------</p></td></tr>';
$(html).insertAfter($(this).parents('tr.trList'));
}
});
Updated Demo :
Check this Working Fiddle
For insert .parents(),
$(html).insertAfter($(this).parents('tr.trList'));
For slideToggle(),
$(document).on('click','.trNeedTimesheet',function(){
$('p',this).slideToggle()
});