Create a cloned div that works separately in the same page - javascript

I have a div in my page which contains a table with inputs (with ids), I have some conditions and functions on the inputs written in the Javascript code. What I'm trying to do is to make a button (add new) that clones exactly the same div in the page but with same conditions and functions on the new elements and the submit button to work for each separately.
I tried this :
$('#button-add').bind({
click: function()
{
$("#repeat").clone().appendTo("#add");
}
});
the problem is that I get the same appearance for the div but the functions are not working (because the inputs have the same id) and i cannot submit only that block (new div).
Is there a simpler way to achieve that?

Just in case if you ignore making clones.
The way of doing it using a dynamic id.
Say if appending div with different id for every element using random function in javascript.
$('#add-item').on('click', function (e) {
var num = Math.floor(Math.random() * 90000) + 10000;
var numtd = Math.floor(Math.random() * 50000) + 10000;
$('<tr id="trowdynamic_' + num + '">' +
'<td>' +
'<div class="input-group">' +
'<input type="hidden" id="selected_item_' + numtd + '" name="selected_name" />' +
'<input type="text" name="Inv_Itemsdetail" value="" class="Itemsdetail-typeahead_' + numtd + ' input-search" autocomplete="off" data-provide="typeahead" />' +
'<input type="hidden" id="Inv_Itemsdetail_' + numtd + '" class="auto-complete" name="Itemxx[]" />' +
'<span class="input-group-btn">' +
'<i class="fa fa-plus"></i>' +
'</span>' +
'</div>' +
'</td>' +'</tr>').appendTo('#yourcontainer_id');
});
Now using jQuery call for same id elements-
Now Note this way I have every element starting with same id name plus a random number.
$('input[id^="selected_item_"]')

Since you're going to duplicate the div, you should not use IDs, because their uniqueness would be compromised. But you can use css class names ($('.className')) or custom data attributes ($('[data-my-id=xxx]')) to address your inputs because they do not need to be unique.
Second, you need to clone your div so that the events attached to your inputs are cloned as well. Check out the jQuery doc for .clone([withDataAndEvents] [,deepWithDataAndEvents]) (http://api.jquery.com/clone/).

Since the new div is created in new space ie, in #add, select the new div as
#add #repeat
{
} // in css
in jquery use next or siblings or children etc to select the new div
For example
see the FIDDLE

Related

HTML Element not being inserted

I'm working on a .NET Core project for my company where work orders are loaded from our SQL database using Entity Framework, filtered and then displayed as markers on a map through Google Maps API for our installers.
We have two types of filters: one that gets included in an Ajax POST, and one that filters locally to decrease load times and performance issues. What I'm trying to do is load the local filter items (lists that are included in the response when calling the initial Ajax POST). If the list of filter items exceeds 5 items, I want them to collapse to only 5 items and insert an anchor which expands (utilizes jQuery's toggle()) showing the rest of the items in that list.
This is the excerpt from the JavaScript function which takes care of that:
filterItems
.forEach((filterItem, i) => {
var localItem = '<label class="' + selectorContainerClass
+ ' selectorContainer" id="' + selectorContainerIdPrefix + filterItem.key
+ '"><input id="' + convertValToEng(filterItem.value)
+ '" type = "checkbox" class="filled-in navy" name="' + inputName
+ '" value="' + filterItem.key
+ '" onchange="localFilter(this, this.value)" /><span class="selector-value">'
+ filterItem.value
+ '</span> <span id="' + paramName + 'Cnt__' + filterItem.key
+ '" class="selector-count"></span></label ><br />';
document.querySelector("#" + colId).insertAdjacentHTML('beforeend', localItem);
if (i >= 5) {
$("#" + colId + " #" + selectorContainerIdPrefix + filterItem.key).addClass("collapse");
$("#" + colId + " #" + selectorContainerIdPrefix + filterItem.key).toggle(100);
$("#" + colId + " #" + selectorContainerIdPrefix + filterItem.key + " + br").toggle(100);
}
});
if (filterItems.length > 5) {
//TODO: Fix the bug here; the .filter-collapse element is not being inserted under local installers.
var newEl = '<a class="filter-collapse" onclick="toggleFilterExpand(false, this)";><i class="material-icons">expand_more</i></a>';
document.getElementById(colId).insertAdjacentHTML('beforeend', newEl);
}
I should be getting a newEl inserted under the "Installer" column (8 installers, 3 of them not being displayed), but I'm not. I've tried jQuery's after() and insertAfter() methods, but neither of those worked. newEl is being generated for the "Area" column, as it should, but for the "Installer" column it's not.
I've also tried inserting the element manually through the console window with the exact same code and it works.
Would appreciate some help with this as I feel lost regarding this issue.
Thanks.
It turned out to be a stupid mistake on my end where I was removing the element newEl from the all the other filter lists before inserting a new one to the currently iterated one.

Why jQuery append() removes words after first blank space in string

I'm trying to dynamically generate a form after an ajax request. Below is the relevant code sample :
for (var i in response.responseJSON[0].fields) {
var field = response.responseJSON[0].fields[i];
$('#properties_form').append('<label for=' + i + '>' + i + '</label>' +
'<input id=' + i + ' value=' + field + '>');
}
My problem is that, when var i and var field are strings with blank spaces like "Hello world", my label and inputs will be like <label id="Hello" world=""> and <input value="Hello" world="">. However, the label text will be displayed correctly i.e. <label>Hello world</label>.
I've no idea what kind of sorcery that is, but I'll be very grateful for any help. Thanks in advance.
There's a much more robust way of doing this.
for (var i in response.responseJSON[0].fields) {
var field = response.responseJSON[0].fields[i];
$('#properties_form')
.append($('<label>').attr('for', i).text(i))
.append($('<input>').attr('id', i).val(field));
}
You won't have to worry about the content of the strings as jQuery and the DOM will handle it for you. Not to mention this is much easier to read.
Use " to enclose the attributes.
$('#properties_form')
.append('<label for="' + i + '">' + i + '</label>' +
'<input id="' + i + '" value="' + field + '">');
EDIT
This will break for the cases where the value for i is something like This "works". Best solution is to append as jQuery or JS objects rather than using HTML string just like Daniel's answer.
Following snippet contains the correct fix for this. Updated based on the answer from Daniel.
i = 'Hello "World"';
field = 'Hello "World"s';
$('#properties_form')
.append($('<label>').attr('for', i).text(i))
.append($('<input>').attr('id', i).val(field));
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div id="properties_form"></div>

Unable to bind event

I am trying to bind an onchange event to a textarea, but this isnt working
$('#Que_dlist_ctl0' + sectionid + '_Inner_dlist tr:nth-child(' + (i + 1) + ')
#Que_dlist_ctl0' + sectionid + '_Inner_dlist_ctl0' + i + '_txtsuggest')
.addClass("clTxt_" + i)
.bind("change",function(){"Validate(this);"});
In the rendered html, I can see the 'class' added as desired, but not the event.
Also tried .attr instead of bind.
$('#Que_dlist_ctl0' + sectionid + '_Inner_dlist tr:nth-child(' + (i + 1) + ')
#Que_dlist_ctl0' + sectionid + '_Inner_dlist_ctl0' + i + '_txtsuggest')
.addClass("clTxt_" + i)
.attr("onchange","Validate(this);"});
It doesnt work in firefox, ie and chrome.
The rows in table and the controls, all are dynamically generated, and hence that weird id selector
<textarea class="clTxt_0" name="Que_dlist$ctl00$Inner_dlist$ctl00$txtsuggest"
rows="3" cols="20" id="Que_dlist_ctl00_Inner_dlist_ctl00_txtsuggest"
style="width:300px;"></textarea>
Use:
.change(function(){
Validate(this);
});
If you write $(selector).bind("change",function(){}); or $(selector).change(function(){});, this is going to bind only to those textareas which are already present in the DOM when the event gets bound to the textarea.
Since your rows are generated dynamically, you can just add a class to the textarea while generating
<textarea class="gridTextArea" class="clTxt_0"
name="Que_dlist$ctl00$Inner_dlist$ctl00$txtsuggest" rows="3" cols="20"
id="Que_dlist_ctl00_Inner_dlist_ctl00_txtsuggest" style="width:300px;" >
</textarea>
and bind it as below which will bind to all the newly created textareas with in the dynamically created rows.
$(document).on("change",".gridTextArea",function(){
//your logic goes here
});
Hope this helps :)

Browser window shows correct value in inspector but invalid in the document

I am dynamically generating the input box using jquery and then embedding it into the document. The problem I am having is, although the correct value is being shown in the inspector, the browser shows an invalid value.
To be further clear, here is the image:
You can see that, in the inspector
<input name="txtTblAmount" class="num" style="width:70px;" type="text" value="1000" tabindex="29">
the value is 1000 while that being shown in the browser window is 1500. Can anyone please have a look and tell me, what's the problem here?
P.S: Have tried it in firefox as well. But still the problem is same i.e. different value in the inspector.
Here is the JS code:
function addrow(itemName, itemid, godown, godownid, quantity, rate, amount, gstAmount) {
gstAmount = typeof gstAmount !== 'undefined' ? gstAmount : '0';
if (typeof dTable1 != 'undefined') {
// dTable1.fnClearTable();
//$('#ItemRows').find('a[name="btnDelItem"]').off();
dTable1.fnDestroy();
// $('#ItemRows').empty();
}
//alert($('#ItemRows tr').length);
var strRow = '<tr id="row' + ($('#ItemRows tr').length + 1) + '">' +
'<td class="">' +
(($('#ItemRows tr').length + 1)) +
'</td>' +
'<td class="tdItemName" style="widtd: 250px">' +
itemName +
'<input name="hfItemId" style="width:200px;" type="hidden" value="' + itemid + '"/>' +
'</td>' +
'<td class="" style="widtd: 200px">' +
godown +
'<input name="hfGodownid" style="width:200px;" type="hidden" value="' + godownid + '"/>' +
'</td>' +
'<td class="" style="widtd: 200px">' +
'<input name="txtTblQuantity" style="width:200px;" class="num" type="text" value="' + quantity + '"/>' +
'</td>' +
'<td class="" style="widtd: auto">' +
'<input name="txtTblRate" style="width:70px;" class="num" type="text" value="' + rate + '"/>' +
'</td>' +
'<td class="" style="widtd: auto">' +
'<input name="txtTblAmount" class="num" style="width:70px;" type="text" value="' + amount + '"/>' +
'</td>' +
'<td>' +
'<input name="txtTblGstAmount" class="num" style="width:70px;" type="text" value="' + gstAmount + '"/>' +
'</td>' +
'<td class="ms"><div class="btn-group1"> <a class="btn btn-small" rel="tooltip" data-placement="left" data-original-title=" edit " name="btnDelItem" data-id="' + ($('#ItemRows tr').length + 1) + '" ><i class="icon-remove"></i></a> </div></td>' +
'</tr>';
console.log(strRow);
console.log(amount);
$('#ItemRows').append(strRow);
//SaveNewParty($("#drpAccId option:selected").text());
bindGrid();
//dTable1.fnDraw();
PopulateTotal();
// $('#ItemRows').find('a[name="btnDelItem"]').off();
var insertedRow = $('#ItemRows tr')[$('#ItemRows tr').length - 1];
$(insertedRow).find('a[name="btnDelItem"]').on('click', function () {
var row = $(this).parents('tr');
dTable1.fnDeleteRow(dTable1.fnGetPosition(row[0]));
$('#ItemRows tr').each(function (index) {
$(this).find('td:nth(0)').text((index + 1));
});
PopulateTotal();
})
$('#datatable_Items').css('width', '100%');
Populate_Events();
}
I just had a look at your code and found that there was no problem in the code you have shown us here. I agree with Afzaal Ahmad Zeeshan but the way he has explained it, it's not always the case. I recently had the same issue and after hours of scratching my head I found out that the value was being changed by some other jquery code.
Also note that, it is not always the case that the value set by the jquery is shown in the inspector for example, if you try $("#inputel").val(4), you will note that the value will not be updated in the inspector but in the backend this value has been updated. Inspector only shows the value that was sent from the server, not the one you set by jquery or something else.
Hope you got my point!
Kamran, that's of no importance. You are setting this value NOT DYNAMICALLY. Yes, you can see here! You are either setting this value while loading the page, or you are using some other code, that you are not showing us! I am not sure of that. Ok here.
In my example you can see, I am writing a text in the input but there is no value update in the element's inspection.
Also, its maybe not the answer but you can see that you're using widtd which is not a correct CSS property. The correct one is width. You know that.
I am sure you won't get any problem while sending the form to the server, as the value will get updated by the value that you just wrote.
I have seen your code, you are writing the field as:
<input name="txtTblAmount" class="num"
style="width:70px;" type="text" value="' + amount + '"/>'
According to me, the issue is at amount. You are havin this field in the function too.
function addrow(itemName, itemid, godown,
godownid, quantity, rate, amount, gstAmount) {
Now what you can do to prevent that is to change the value of amount there. If you donot want to change it, then its OK. And also, once again you should not fear this value difference, as once you click submit the value that you have entered will be sent to the server instead of value of the field itself. The value is just because you have it written there. Nothing else, so don't worry! Its ok. You cannot change the value now, if you want to. Then here is the hell code, you will have to hard code it. Like this!
<div id="input">
<input type="text" id="text" value="" onkeyup="updateVal()" />
</div>
function updateVal() {
// start function..
var val = $('#text').val(); // the value of field..
// after getting the value, update the div..
$('#input').html("<input type='text' id='text' value='" +
val + "' onkeyup='updateVal()' />");
}
But note, after using this code, you will get the current value in the field! But you will loose the focus on the input field. As the div will get updated but the values will be the newest ones!
Now to keep in focus?
You can use this:
$('#text').focus();
But while using this, you will get only one ONLY ONE word in the field.
Why?
Because once if will focus on the field, it will (select all) select the words or value inside the field and when you press another word, it will replace the previous one with the latest one! This way you will not get any correct field I mean the field of your choice! But you issue will be fixed.
So kamran believe me, let it be the way it is! You donot want to hard-code it. If you still wanna give it a try, use the code I shared!
Example for the code I am sharing is as under:
Now when you right the value or some words, you will get the value auto updated when you see this Developer Tools. Like this:
That was all. I gave you two options for your work. And still I will love to go with the option of Not using a code, to just update the value on the field. Rest is upto you Kamran.
Edit:
You mentioed that you want to use the value 1000 not the value that the user would add to the input. Then use this:
$("name='txtTblAmount'").val() == "1000");
This will automatically override the value that user will add and replace it with the value that you want to get!

Attach event handlers to multiple textboxes (with similar patterned id)?

I have several textboxes that are generated dynamically based on some results I get from another source. I want to add some event handlers to these textboxes to catch any keypress, and ensure that anything entered is numeric.
I generate these textboxes based on the length of an array within a JSON response, like so:
for(i=0;i<data.routesout.length;i++)
{
content += '<label for="route' + i + '">' + data.routesout[i].name + '(%)</label>';
content += '<input type="text" name="route' + i + '" id="route' + i + '" value="' + data.routesout[i].percent>';
}
How can I attach a single event handler to all of these potential inputs?
You've tagged the question with jQuery, so I wonder why you're not using the library to build your content:
var content = [];
for (var i = 0; i < data.routesout.length; ++i) {
content.push($('<label/>', { 'for': 'route' + i, text: data.routesout[i].name }));
content.push($('<input/>', { change: yourEventHandler, type: 'text', name: 'route' + i, id: 'route' + i, value: date.routesout[i].percent, change: yourEventHandler }));
}
By doing it that way, you can bind the handler element by element as you construct them. (I used "change" as an example, but you could bind handlers for whatever event you want in the same way.)
At the end, you can append all the created elements however you want, or you could append them as you go instead of building an array.
You can use the starts with selector
$('input[id^="route"]').keyup(function(){...
Note that if you're creating these on the fly, you might need to attach the event using live:
$('input[id^="route"]').live('keyup', function(){...
What about this?
for(i=0;i<data.routesout.length;i++){
content += '<label for="route' + i + '">' + data.routesout[i].name + '(%)</label>';
content += '<input onkeypress="doSomething(this)" type="text" name="route' + i + '" id="route' + i + '" value="' + data.routesout[i].percent + '>';
}
function doSomething(element){
/* this function will be called when user presess key inside a textbox */
}

Categories

Resources