I have a HTML snippet as follows, I want to take the 'article-form' div, clone it, and increment the numbers for the attributes for, id, and name.
<div class="article-form">
<label for="id_form-0-section">Section:</label>
<select id="id_form-0-section" name="form-0-section">
<option selected="selected" value="">---------</option>
<option value="1">News</option>
<option value="2">Originals</option>
</select>
<label for="id_form-0-slug">Slug:</label>
<input type="text" maxlength="255" name="form-0-slug" id="id_form-0-slug">
<input type="hidden" id="id_form-0-collection" name="form-0-collection">
<input type="hidden" id="id_form-0-order" name="form-0-order">
<input type="hidden" id="id_form-0-id" name="form-0-id">
</div>
I have the cloning part so far, but I need to take what I have cloned an traverse the elements inside have the attribute for, id, and name.
var $articeForm = $('.article-form').clone();
Let me add, the increment part isn't the problem. I plan on doing the following. I am not sure what is the best way to traverse by attribute.
var newNumber = parseInt($('#id_form-0-id').attr('id').split('-')[1]) + 1;
One more thing, the fact that this started at 0 is meaningless, in some situations it could start with 5 and then the next fields that follow should be 6.
You could grab a little regex and parseInt() for this. E.g.
element.attr('name', element.attr('name').replace(/(.*form\-)(\d+)(\-.*)/, function(f, p1, p2, p3) {
return p1 + (parseInt(p2) + 1) + p3;
}));
There's however only one huge caveat: Changing name attr of cloned input element in jQuery doesn’t work in IE6/7
var counter = 0;
$('myElement').each (function(index)) {
$(this).attr('id'+counter);
counter++;
});
You may want to keep a variable that tells you how many clones you made so far.
var count = 0;
Then every time you make a clone you increment the count.
count++;
$articleForm.children().each(function(){
newId = $(this).attr("id") + count;
$(this).attr("id", newId);
});
Assuming you have an area of your page that will hold these cloned divs:
<div id="articles"></div>
Start with a page-wide counter variable:
<script type="text/javascript">
var articleFormCount = 0;
<script>
Create a function that builds the HTML for you:
<script type="text/javascript">
function buildArticleFormDiv()
{
var html = "<div class=\"article-form\">" +
"<label for=\"id_form-" + articleFormCount + "-section\">Section:</label>" +
"<select id=\"id_form-" + articleFormCount + "-section\" name=\"form-" + articleFormCount + "-section\">" +
"<option selected=\"selected\" value=\"\">---------</option>" +
"<option value=\"1\">News</option>" +
"<option value=\"2\">Originals</option>" +
"</select>" +
"<label for=\"id_form-" + articleFormCount + "-slug\">Slug:</label>" +
"<input type=\"text\" maxlength=\"255\" name=\"form-" + articleFormCount + "-slug\" id=\"id_form-" + articleFormCount + "-slug\">" +
"<input type=\"hidden\" id=\"id_form-" + articleFormCount + "-collection\" name=\"form-" + articleFormCount + "-collection\">" +
"<input type=\"hidden\" id=\"id_form-" + articleFormCount + "-order\" name=\"form-" + articleFormCount + "-order\">" +
"<input type=\"hidden\" id=\"id_form-" + articleFormCount + "-id\" name=\"form-" + articleFormCount + "-id\">" +
"</div>";
articleFormCount++;
$("div#articles").append(html);
}
</script>
Call the function on page load:
<script type="text/javascript">
$(document).ready(function()
{
buildArticleFormDiv();
});
</script>
Then, whatever mechanism you use to add the new div (say, a hyperlink click event), call the buildArticleFormDiv() function.
Here is the solution I have come up with so far. Anything look horribly wrong with it?
function incAttrName(name) {
return name.replace(/(.*form\-)(\d+)(\-.*)/, function(f, form, number, label) {
return form + (parseInt(number) + 1) + label;
});
};
$articleForm.find('[for]').attr('for', function() {
var name = $(this).attr('for');
return incAttrName(name);
});
$articleForm.find('[id]').attr('id', function() {
var name = $(this).attr('id');
return incAttrName(name);
});
$articleForm.find('[name]').attr('name', function() {
var name = $(this).attr('name');
return incAttrName(name);
});
Related
This question already has answers here:
Event binding on dynamically created elements?
(23 answers)
Closed 7 years ago.
I am creating group of check boxes dynamically and one extra check box also for selecting all group at once that one too is generated dynamically
this is html output
<input type="checkbox" id="all">all
<br>
<input type="checkbox" name="question">a
<br>
<input type="checkbox" name="question">b
<br>
<input type="checkbox" name="question">c
<br>
<input type="checkbox" name="question">d
this is jquery
$("document").ready(function() {
$("#all").on('change', function() {
if ($(this).is(":checked")) {
$("input[type=checkbox][name=question]").prop('checked', true);
} else {
$("input[type=checkbox][name=question]").prop('checked', false);
}
});
});
this is implementation.
It works fine when checkboxes are not generated dynamically
But when they are generated dynamically code has bug
I am able to check whole group but
I am not able to check single checkbox
This is dynamically generated code
$('#demo3').on('change', function() {
if ($('input[type=checkbox]:checked')) {
var value = $('input[type=checkbox]:checked').val();
alert(value);
$("#demo3").hide();
$.getJSON("json/question.json", function(jd) {
var size = jd.length;
var table = "<table><tr><th><input id=\"" + "selectall" + "\" type=\"" + "checkbox" + "\"/>" +
"</th><th>Question</th><th>Option A</th>" + "<th>Option B</th><th>Option C</th>" +
"<th>Option D</th><th>Answer</th></tr>";
for (var n = 0; n < size; n++) {
table += "<tr><td>" + "<input name=\"" + "question" + "\" type=\"" + "checkbox" + "\" value=\"" + jd[n].questionid + "\"/>" +
"</td><td>" + jd[n].question + "</td>" + "<td>" + jd[n].a + "</td><td>" + jd[n].b + "</td>" + "<td>" + jd[n].c + "</td>" +
"<td>" + jd[n].d + "</td>" + "<td>" + jd[n].ans + "</td></tr>";
}
table += "</table>";
$('#demo4').html(table);
});
}
});
$('#demo4').on('change', function() {
if ($("input[type=checkbox][id=selectall]").is(":checked")) {
$("input[type=checkbox][name=question]").prop('checked', true);
} else {
$("input[type=checkbox][name=question]").prop('checked',false);
}
});
As far as I understand demo4 and demo3 are container elements like div in which you are adding a table which has dynamic HTML.
You could try
$('#demo4').on('change','#<checkboxid>',function() {
checkboxid will be the id that you want to track.
Hope that helps!
Here is my dropdownlist:
<div id="addCam"></div>
<div id="addDiv">
<select id="type1">
<option value="">- Kiểu áo -</option>
#foreach (var item in Model.teetypes)
{
<option value="#item.Image">#item.Name</option>
}
</select>
<a class="btn btn-info btn-default" id="addBtnH" style="text-align:center" title="Thêm sản phẩm"><i class="fa fa-plus"></i></a>
</div>
And here is my javascript .append():
$(document).ready(function () {
var count = 2;
var maxAppend = 0;
$("#addBtnH").click(function () {
var name = $("#type1 option:selected").val();
var name1 = $("#type1 option:selected").text();
if (name == '') return;
if (maxAppend >= 5) {
$("#addDiv").hide();
return;
}
$("#addDiv").show();
$("#type1 option:selected").attr('disabled', 'disabled');
$("#type1").val('');
$("#addCam").append("<div class='widget' id='del" + count + "'><div class='widget-body'><div class='col-md-3'><span style='display:block'><img src='" + name + "' id='tee" + count + "' height='75'/></span></div>" +
"<div class='col-md-1'><select id='color" + count + "' onchange='changeColor" + count + "()'>#foreach (var item in Model.teecolors){<option value='#item.Color' style='background-color: ##item.Color'></option>}</select></div><div id='dis" + count + "'>" + name1 + "</div>" +
"<hr class='wide'><input type='text' name='input'><a class='btn btn-info btn-default' rel='"+name+"' id='delete" + count + "' style='text-align:center' title='Xóa sản phẩm'><i class='fa fa-trash'></i></a>" + #*str +*#
"<script>$('#delete" + count + "').click(function(){var images = $(this).attr('rel'); $('#type1 option[value = "+"images"+"]').removeAttr('disabled');$('#del" + count + "').remove();});" + "<" + "/script>" +
"<script type='text/javascript'>function changeColor" + count + "(){var eID = document.getElementById('color" + count + "'); var colorVal = eID.options[eID.selectedIndex].value; document.getElementById('tee" + count + "').style.background = '#' + colorVal;}" + "<" + "/script>" +
"</div></div>");
count = count + 1;
maxAppend++;
});
});
My problem is, when I click button add, it will add div as content in append, and the value has been add will be disabled in dropdownlist. In the added div, there is a button delete, when i click it, the div will disappear, and the disabled attribute value will be remove. I create 'images' to get attr('rel') of that button, but i don't know how to let $("#type1 option[value=images]") understand that 'images' is a value, not a string? Please help me!
It is not the best practice to write the scirpts elements into the code to be evaluated.
The technique you are looking for is to continuously use jquery selector to get the appended node and set the attributes dynamically.
Consider this solution:
$("#addCam").append($('<ul>').attr('class', 'some-class')
.append($('<li>').attr('class', 'some-other-class')
.append($('<img>').attr('src', 'somePath'))
.on('click', liClickedHandler)));
I need to create a web application where the user drags and drops a task name, then the corresponding task name has to appear in a table.
When this happens a new row has to be added when the drop occurs.
I have used javascript for drag and drop and to add the new row.
My code works in chrome and firefox but not in IE. Why?
here is a sample of my code.
<script type = "text/javascript">
var trNumber = 1;
function addTimeSheetRow(){
var timeSheetBody = document.getElementById("timeSheetBody");
var trow = document.createElement("tr");
trow.innerHTML = "<th ondragstart='return false;' ondrop='return false;'></th>" +
"<th ondrop='drop(event)' ondragover='allowDrop(event)' value='' class='dropTexts'></th>" +
"<td><input name=" + getTrDayNames("Mon") + " type='text' value='' size='2'/></td>" +
"<td><input name=" + getTrDayNames("Tue") + " type='text' value='' size='2'/></td>" +
"<td><input name=" + getTrDayNames("Wed") + " type='text' value='' size='2'/></td>" +
"<td><input name=" + getTrDayNames("Thu") + " type='text' value='' size='2'/></td>" +
"<td><input name=" + getTrDayNames("Fri") + " type='text' value='' size='2'/></td>" +
"<td><input name=" + getTrDayNames("Sat") + " type='text' value='' size='2'/></td>" +
"<td><input name=" + getTrDayNames("Sun") + " type='text' value='' size='2'/></td>" +
"<td class='total'><input type='text' value='0' size='2' readonly='readonly'/></td>";
timeSheetBody.appendChild(trow);
$("tbody#timeSheetBody td input:not(.intial)").each(function() {
$(this).keyup(function(){
newSum.call(this);
colSum.call(this);
});
});
document.getElementsByName("trNumber")[0].value = trNumber;
}
function allowDrop(ev)
{
//ev.preventDefault();
ev.preventDefault ? ev.preventDefault() : ev.returnValue = false;
}
function drag(ev)
{
ev.dataTransfer.setData("Text",ev.target.id);
//var projectElement = ev.target.parentNode;
//ev.dataTransfer.setData("Text", projectElement.getAttribute("id"));
//alert(projectElement.getAttribute("id"));
}
function drop(ev)
{
//ev.preventDefault();
ev.preventDefault ? ev.preventDefault() : ev.returnValue = false;
var data = ev.dataTransfer.getData("Text");
var taskName =document.getElementById(data).innerHTML;
//alert(taskName);
var trTaskName = "tr" + trNumber + "TaskName";
ev.target.innerHTML = taskName + "<input name=" + trTaskName + " type='hidden' value='" + taskName + "' size='2' class='intial'/>";
var projectName = document.getElementById(data).parentNode.getAttribute("id");
//alert(projectName);
var projectTextBox = ev.target.parentNode.children[0];
var trProjectName = "tr" + trNumber + "ProjectName";
projectTextBox.innerHTML = projectName + "<input name=" + trProjectName + " type='hidden' value='" + projectName + "' size='2' class='intial'/>";
trNumber = trNumber + 1;
addTimeSheetRow();
}
You can solve this by making a custom .innerHTML (yes it's a lot of work) or otherwise modifying the .innerHTML property/function. I made this code to make sure that still-referenced child element data is preserved when clearing the .innerHTML (another problem with IE's .innerHTML), but it can be adapted to solve the IE tables problem.
if (/(msie|trident)/i.test(navigator.userAgent)) {
var innerhtml_get = Object.getOwnPropertyDescriptor(HTMLElement.prototype, "innerHTML").get
var innerhtml_set = Object.getOwnPropertyDescriptor(HTMLElement.prototype, "innerHTML").set
Object.defineProperty(HTMLElement.prototype, "innerHTML", {
get: function () {return innerhtml_get.call (this)},
set: function(new_html) {
var childNodes = this.childNodes
for (var curlen = childNodes.length, i = curlen; i > 0; i--) {
this.removeChild (childNodes[0])
}
innerhtml_set.call (this, new_html)
}
})
}
var mydiv = document.createElement ('div')
mydiv.innerHTML = "test"
document.body.appendChild (mydiv)
document.body.innerHTML = ""
console.log (mydiv.innerHTML)
http://jsfiddle.net/DLLbc/9/
http://jsfiddle.net/DLLbc/12/
It's a known bug: You can set the innerHTML of tables only when you create the table in IE. But document.createElement and other dom manipulations should work fine. Alternatively you could use a js lib for compatibility.
FOR NORMAL JS:
A known and no so hard to do fix is to create all elements, not to create a string with all content and add it.
The same way you created the tr, create tds, etc.
In your case might not be so nice to do because of the large structure but...
FOR A BETTER WAY OF LIVING:
Use jQuery/prototype/mootools or whatever other lib you like.
I am facing an issue with my jquery. I have used jQuery to add controls to table, along with a remove button to remove that particular row in table. here is my code on how i am creating controls in table.
HTML
<table id="controls" cellpadding="10" cellspacing="10">
</table>
<input id="btnAdd" type="button" value="Add" />
my jquery code looks like this
jquery
$(document).ready(function() {
$("#btnAdd").click(function() {
var field = $("#field").val();
var year = new Date().getFullYear()
var DDL_fromProfession = "<select name='ParametersFromProf' id='DDL_FromProYear'>";
for (var i = 1950; i <= year; i++) {
DDL_fromProfession += "<option text='" + i + "' value='" + i + "'>" + i + "</option>";
}
DDL_fromProfession += "</select>";
var DDL_ToProfession = "<select name='ParametersToProf' id='DDL_ToProYear'>";
for (var i = 1950; i <= year; i++) {
DDL_ToProfession += "<option text='" + i + "' value='" + i + "'>" + i + "</option>";
}
DDL_ToProfession += "</select>";
var newRow1 = "<tr><td align='center' style='font-size: large; color: #212121;' height='35px'>from"
+ DDL_fromProfession + " to " + DDL_ToProfession + "</td></tr>"
+ "<tr><td align='center' style='font-size:large;color:#212121;' height'35px'>"
+ "<input type='checkbox' name='chkbx_CurrPro' value='" + k + "'>I currently work here</input>";
newRow1 += "<br/><button id='btn_rmv'>Remove</button>";
var input = "<input name='parameters' id='field' type='text' />";
var input1 = "<input name='parametersCompany' id='field' type='text'/>"
//var inputCurrent="<input name='Current' id='Currfield' type='hidden'/>"
var newRow = "<tr><td align='center' style='font-size: x-large; color: #212121;' height='35px'>"
+ input + " at " + input1 + "</td></tr>";
$('#controls').append(newRow);
$('#controls').append(newRow1);
});
});
to remove last row i am using.
jquery
$(document).ready(function() {
$("#controls").delegate("#btn_rmv", "click", function() {
$(this).closest("tr").remove();
return false;
});
});
clicking on remove button refresh the page and remove all the rows that i have added instead of last one.
NOTE: What i ahve digged out is .delegate is server side and it refresh the page. i am unable to remove last row with $("#btn_rmv").click(function() on my page
Please point me to right direction.
Thanks in advance
The code in question does not work as k is not defined, as used in the line
value='" + k + "'
If this error is corrected then the next problem is that you are creating multiple elements with the same id, as seen here
newRow1 += "<br/><button id='btn_rmv'>Remove</button>";
which in invalid HTML and will cause problems for jQuery in finding the element with the unique id.
By changing k for 0 and changing the id to a class, the remove code will only remove the current row with the button on. I assume that you really want to remove that row and also the preceding 2 rows.
$('#controls').delegate('.btn_rmv', 'click', function() {
var index = $(this).closest('tr').index() + 1 // as nth-child is 1-based indexing
$('#controls tr:nth-child(n+' + (index - 2) + '):nth-child(-n+' + index + ')').remove(); // remove 3 rows
return false
});
See demo
Please note that since jQuery 1.7, .delegate() is superseded by .on() so the updated function is:
$('#controls').on('click', '.btn_rmv', function() {
var index = $(this).closest('tr').index() + 1
$('#controls tr:nth-child(n+' + (index - 2) + '):nth-child(-n+' + index + ')').remove();
return false
});
I had a similar experience: I was using Google Chrome and it would refresh the page everytime I called a function. You will have to return false. My problem was when I called a function from an element using "onclick". When I called the function from onclick I had to include the "return false;":
onclick="return false; functionName()"
Try this and see if it works:
$(document).ready(function() {
$("#btnAdd").click(function() {
/* YOUR CODE */
return false;
});
});
Or this and see if it works:
$(document).ready(function() {
$("#btnAdd").click(function() {
/* YOUR CODE */
});
return false;
});
Sorry my Javascript is not very good :(
You can do it in this way..
var RowCount = 0;
$(document).ready(function() {
$("#btnAdd").click(function() {
RowCount = RowCount + 1;
var newRow1 = "<tr id='tr" + RowCount + "'><td align='center' style='font-size: large; color: #212121;' height='35px'>from"
+ DDL_fromProfession + " to " + DDL_ToProfession + "</td></tr>"
+ "<tr><td align='center' style='font-size:large;color:#212121;' height'35px'>"
+ "<input type='checkbox' name='chkbx_CurrPro' value='" + k + "'>I currently work here</input>";
newRow1 += "<br/><button id='btn_rmv' onclick='RemoveRow(" + RowCount + ")'>Remove</button>";
});
});
function RemoveRow(RowID) {
$('#RemoveRow' + RowID).remove();
}
It looks like you are hooking up the remove click handler on $(document).ready.
On document.ready, the remove buttons do not yet exist (since they are generated dynamically when clicking 'Add', after the document.ready code has run). That's why $("#btn_rmv").click(function()... is not working.
So, after dynamically inserting a remove button in the $("#btnAdd").click event, you explicitly have to add a click handler to it.
EDIT:
If you generate your remove buttons with a unique id (eg. btn_rmv_1, btn_rmv_2, etc), you can add the following to your Add-handler (after appending the new button to the DOM):
$('#btn_rmv_1').click(removeButtonFunction);
I have an ajax function that loads my inbox messages and each of the messages has a user_type and read field.
I'm looping over the messages and generating the html for them.
function initializeMailbox() {
// get all mailbox data
user.GetInboxMessages(function (response) {
if (response) {
inboxMessages['inbox'] = response;
$("#inbox-table").fadeIn();
loadInboxTable();
inboxDataTable = $("#inboxTable").dataTable();
$("#inbox-count").html(inbox_msg_count);
displayMessage(first_msg_id);
}
});
}
function loadInboxTable() {
for (var i = 0; i < inboxMessages['inbox'].length - 1; i++) {
first_msg_id = inboxMessages['inbox'][0].message_id;
var user_type = "";
if (inboxMessages['inbox'][i].user_type = 1)
user_type = "DONOR";
else if (inboxMessages['inbox'][i].user_type = 0)
user_type = "CANDIDATE";
else if (inboxMessages['inbox'][i].user_type = 2)
user_type = "GROUP";
$("#inbox-table-body").append(
"<tr class='data-row' style='height: 75px;'> " +
"<td>" +
"<input type='hidden' id='user_type' value='" + inboxMessages['inbox'][i].user_type + "'/>" +
"<input type='hidden' id='read' value='" + inboxMessages['inbox'][i].read + "'/>" +
"<input type='checkbox' id='" + inboxMessages['inbox'][i].message_id + "'></input></td>" +
"<td>" +
"<p class='left'>" +
"<img class='td-avatar' style='margin-top: 0px !important;' src='/uploads/profile-pictures/" + inboxMessages['inbox'][i].image + "' alt='avatar'/>" +
"<br/>" +
"<span class='user-type'>" + user_type + "</span>" +
"</p></td><td>" +
"<h2 onclick='displayMessage(" + inboxMessages['inbox'][i].message_id + ");'>" + inboxMessages['inbox'][i].firstname + " " + inboxMessages['inbox'][i].lastname + "</h2><br/>" +
"<h3 class='message-subject' onclick='displayMessage(" + inboxMessages['inbox'][i].message_id + ");'>" + inboxMessages['inbox'][i].subject + "</h3><br/><br/>" +
"<h3 style='font-size: 0.7em; margin-top: -25px; float:left;'><span>" + inboxMessages['inbox'][i].datesent.toString().split(" ")[0] + "</span></h3>" +
"</td>" +
"<td><button class='delete-item' onclick='deleteMessage(" + inboxMessages['inbox'][i].message_id + ");' src='/images/delete-item.gif' alt='Delete Message' title='Delete Message' style='cursor: pointer; float:left; margin-left: 5px; margin-top:-3px;'></button></td>" +
"</tr>"
);
// check if the message has been read
if (inboxMessages['inbox'][i].read == 0) {
// not read
$("#message-subject").addClass('read-message');
} else {
// read
$("#message-subject").removeClass('read-message');
}
inbox_msg_count++;
}
}
Now if I alert out the values of user_type and read, I get the correct values, based on the message it's iterating over. But when it outputs, it's only using the value of the first message.
I need to be able to dynamically style the messages with jquery, based on these values. Can someone please tell me why this isn't working...
Well, for one thing, you are using an ID selector:
$("#message-subject").addClass('read-message');
When you actually have a class:
<h3 class='message-subject'...
Use:
$(".message-subject").addClass('read-message');
Secondly, you are making an assignment (=) instead of doing a comparison (==) on user_type.
Might I suggest a different approach instead of a big if..then..else?
Use an array to index your user_types:
var user_type_labels = [ 'CANDIDATE', 'DONOR', 'GROUP' ];
function loadInboxTable() {
for (var i = 0; i < inboxMessages['inbox'].length - 1; i++) {
first_msg_id = inboxMessages['inbox'][0].message_id;
// One line instead of an if/then/else
var user_type = user_type_labels[ inboxMessages['inbox'][i].user_type ];
...
Third, you are adding multiple items with the same ID to your DOM. This is not legal and has undefined consequences.
<input type='hidden' id='user_type' value='...
<input type='hidden' id='read' value='...
You need to use classes for this.
<input type='hidden' class='user_type' value='...
<input type='hidden' class='read' value='...
In your code I think you meant to do the following
if (inboxMessages['inbox'][i].user_type === 1)
Notice the equal signs. What you currently have will always be true and user_type will always be assigned to DONOR