Remove element from outside its container - javascript

I am trying to create an election simulator. I have a form field and a link to add more fields. Whatever I write in the fields shows up below the fields. When I click on "Remove" it removes the form field but not it's corresponding text below. This is what I want to fix.
html
<h2>Add new party</h2>
<div id="partiesDiv">
<p>
<label for="parties"><input type="text" id="party" size="20" name="party" value="" placeholder="Party name" onkeyup="updateTxt('party','txt');"></label>
</p>
</div>
<div id="text">
<p>
<span id="txt"></span>
</p>
</div>
javascript
$(function() {
var partyDiv = $('#partiesDiv');
var textDiv = $('#text');
var i = $('#partiesDiv p').size() + 1;
$('#addParty').live('click', function() {
$('<p><label for="parties"><input type="text" id="party_' + i +'" size="20" name="party" value="" placeholder="Party name" onkeyup="updateTxt(\'party_' + i +'\',\'txt' + i +'\');"/></label> Remove</p>').appendTo(partyDiv);
$('<p><span id="txt' + i +'"></span></p>').appendTo(textDiv);
i++;
return false;
});
$('#remParty').live('click', function() {
if( i > 2 ) {
$(this).parents('p').remove();
i--;
}
return false;
});
});
function updateTxt(field,toField){
var field = document.getElementById(field);
var toField = document.getElementById(toField);
toField.innerHTML=field.value;
}
When I've added a few fields the html looks like this:
<div id="partiesDiv">
<p>
<label for="parties"><input type="text" id="party" size="20" name="party"
value="" placeholder="Party name" onkeyup="updateTxt('party','txt');">
</label>
</p>
<p>
<label for="parties"><input type="text" id="party_2" size="20" name="party"
value="" placeholder="Party name" onkeyup="updateTxt('party','txt');">
</label> Remove <--- WHEN I CLICK HERE
</p>
</div>
<div id="text">
<p>
<span id="txt"></span>
</p>
<p>
<span id="txt2"></span>
</p> <--- I WANT THIS <p> TO BE REMOVED
</div>
What I'm guessing is that I should add a line below $(this).parents('p').remove(); that removes the p within div id="text". The problem is that I don't know how to make it know which p to remove.
I'm new to JavaScript and this might be over my head, so please let me know if I should clarify anything!
Thanks

You can remove the closest element to the parent element of your field by using this code:
$(this).parent.closest('p').remove();
Here is more you can read about 'closest' method http://api.jquery.com/closest/

My not so pretty solution:
$('#addParty').live('click', function() {
$('<p><label for="party"><input type="text" id="party_' + i +'" size="20"
name="party" value="" placeholder="Skriv partinamn"
onkeyup="updateTxt(\'party_' + i +'\',\'txt' + i +'\');"/></label>
<a href="#" *****class="remParty' + i +'"*****>Remove</a></p>')
.appendTo(partyDiv);
$('<p><span id="txt' + i +'"></span></p>').appendTo(textDiv);
i++;
return false;
});
So that the class="remParty" gets i appended to it for every new field that is created.
Then I just add
$('.remParty2').live('click', function() { $(this).parents('p').remove();
$("p:has(#txt2)").remove(); if(i==2){i--;} return false; });
as many times as I want the maximum number of parties allowed to be.

Dude, you have to update your jquery methods.
The .size() method is deprecated as of jQuery 1.8. Use the .length property instead.
As of jQuery 1.7, the .live() method is deprecated. Use .on() to attach event handlers.
Use .closest() to call the closest parent, as the <p> tag you want.
Remember to use a class '.remParty' instead of an id '#remParty', because if you have more than one element with the same id it will not work.
Demo:
http://jsfiddle.net/EhjM7/
I rewrited it for you:
$(function() {
var i = $('#partiesDiv p').length + 1;
$(document).on('click','#addParty',function(e) {
e.preventDefault();
$('#partiesDiv').append('<p><label for="parties"><input type="text" id="party_' + i +'" size="20" name="party" value="" placeholder="Party name" onkeyup="updateTxt(\'party_' + i +'\',\'txt' + i +'\');"/></label> Remove</p>');
$('#text').append('<p><span id="txt' + i +'"></span></p>');
i++;
return false;
});
$(document).on('click','.remParty',function(){
$(this).closest('p').remove();
i--;
return false;
});
});
function updateTxt(field,toField){
var field = document.getElementById(field);
var toField = document.getElementById(toField);
toField.innerHTML=field.value;
}

First of all, you should NOT use the id attribute when you are using it more than once. there may be only one id with the same value within the page!
if you want to remove an upper element selecting it by its child you can use the :has() selector.
$("p:has(#txt2)").remove();
So lets begin again :)
$('#addParty').live('click', function() {
$('<p>Remove</p>').appendTo(partyDiv);
$('<p><span data-party-id="'+i+'"></span></p>').appendTo(textDiv);
});
I do assing data-party-id to both elements, as we can later easily refer to them.
Now lets do the magic to remove it.
$('.remParty').live('click', function() {
// learn something about data attributes and data()
var partyId = $(this).data("party-id");
$('p:has([data-party-id="' + partyId + '"])').remove();
});
But it would be much easier, if you would assign the identification to the p and not to the span. Then you do not need the :has() selector

Related

How do I repeat the piece of html code 10 times by clicking on the same button using JS/Jquery?

I want to be able to display the same piece of html code 10 times under the div called: <div id="add_remove_product_name"> By clicking on the button called: <button id="add_another_product_name">. I think I need some kind of a for loop for the job but are not sure. Any suggestion will be helpful, thanks.
My HTML code:
<div id="product_name">
<input id="skriv_produktnavn" placeholder="Skriv Produktnavn her" required></label>
<button id="add_another_product_name">Tilføj endnu et produktnavn</button>
<div id="add_remove_product_name">
<input id="added_product_name" placeholder="Skriv Produktnavn her" required></label>
<button id="remove_product_name">X</button>
</div>
Use a for loop to concatenate 10 copies of the HTML code. Then use .after() to put this after the DIV.
$("#add_another_product_name").click(function() {
var html = '';
for (var i = 0; i < 10; i++) {
html += 'html code that you want to repeat';
}
$("#add_remove_product_name").after(html);
}
You can use jQuery clone() however when cloning an element all the attributes will be the same. Fo example they will all have the same id attribute which will cause problems and it is not valid html
So in order to do the clone correctly you have fix the cloned element
DEMO: http://jsfiddle.net/rpyt445e/
var $tpl = $('#product_name').clone();
var num = 0
$('#clone').click(function () {
num++;
var $cloned = $tpl.clone();
$cloned.attr('id', $tpl.attr('id') + '_' + num);
$(':not([id=""])', $cloned).each(function(){
$(this).attr('id', $(this).attr('id') + '_'+num);
});
$cloned.appendTo('#wrapper');
});
HTML:
<div id="wrapper">
<div id="product_name">
<input id="skriv_produktnavn" placeholder="Skriv Produktnavn her" required />
<button id="add_another_product_name">Tilføj endnu et produktnavn</button>
<div id="add_remove_product_name">
<input id="added_product_name" placeholder="Skriv Produktnavn her" required />
<button id="remove_product_name">X</button>
</div>
</div>
</div>
<button id="clone">Clone</button>
A technique for adding the additional elements without having to create ugly strings of html in the JavaScript is to start with one hidden set of the elements in the html. At page load time, you remove that set, but keep a reference to it. Then when you want to add a set to the page, you clone the set you removed. All of this is easier if you add a container div around the additional inputs.
You also need to make sure id attribute values are unique. In the case of the remove buttons, you can replace the id with a class. As for the input id values, if you really need them, you can add an index value to them.
Since the remove buttons are dynamically added, I suggest using event delegation when binding the click-handler.
HTML:
<div id="product_name">
<input id="skriv_produktnavn" placeholder="Skriv Produktnavn her" required="required"/>
<button id="add_another_product_name">Tilføj endnu et produktnavn</button>
<div id="additional_product_names">
<div class="add_remove_product_name" style="display: none;">
<input id="added_product_name" placeholder="Skriv Produktnavn her" required="required"/>
<button class="remove_product_name">X</button>
</div>
</div>
</div>
JavaScript:
$(function() {
var MAX = 10;
var $addBtn = $('#add_another_product_name'),
$additionalContainer = $('#additional_product_names');
$TEMPLATE = $additionalContainer.children(':first').remove();
function update() {
var $additonalDivs = $additionalContainer.children();
// Enable/disable the add button.
$addBtn.prop('disabled', $additonalDivs.length >= MAX);
// Re-index the "id" attributes.
$additonalDivs.find('input').attr('id', function(i) {
return 'added_product_name[' + i + ']';
});
}
$addBtn.click(function() {
$TEMPLATE.clone().appendTo($additionalContainer).show();
update();
});
$('#product_name').on('click', '.remove_product_name', function() {
$(this).closest('.add_remove_product_name').remove();
update();
});
});
jsfiddle

Issue with creating clones of HTML div using JQuery

I am trying to create clones of a HTML div. The div has a label and two text boxes inside it. I need to change the label value of the newly created div. Here is my code.
<body>
<div id="PayDiv2">
<label id="PayLbl2">Payment No 2: </label>
<input type="text" />
<input type="text" />
</div>
<div id ="totPayForm" >
<label id="totPayLbl">Total Payment: </label>
<input type="text" />
<input type="text" />
<input type="submit" value="Add new one" onclick="addNewField();
return false;">
</div>
<input type="button" value="Clone box" id="btn" />
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>
<script>
var i=3;
//When DOM loaded we attach click event to button
$(document).ready(function() {
$('#btn').click(function() {
var cloned = $('#PayDiv2').clone();
cloned.insertBefore("#totPayForm");
$('#PayLbl2').html("Payment No "+ i++ + ':');
});
});
</script>
</body>
The problem is the place the newly created clones placed. First clone get placed before everything(even though I need to place it after the original div which I used to create divs. )
divs generated after that also get placed at first and, early divs goes down. It is hard to describe here. If you can be kind enough to run my code you will see what the issue is.
I have an another requirement to generate unique ids to cloned divs. Since I am new in JQuery, I found it difficult to generate id's.
I am pleased if you can help me in this case. Thank you all.
The problem is $('#PayLbl2').html("Payment No "+ i++ + ':'); it always changes the first element's label instead of the clone(because of the duplicated ids)...
so use class instead of id
<div class="PayDiv2">
<label class="PayLbl2">Payment No 2:</label>
<input type="text" />
<input type="text" />
</div>
then
var i = 3;
//When DOM loaded we attach click event to button
$(document).ready(function () {
$('#btn').click(function () {
var cloned = $('.PayDiv2').first().clone();
cloned.insertBefore("#totPayForm");
cloned.find('.PayLbl2').html("Payment No " + i+++':');
});
});
Demo: Fiddle
Here it is.
Demo
Make your HTML like below
<div id="PayDiv0" class="PayDiv0">
<label id="PayLbl0" class="PayLbl2">Payment No 2:</label>
<input type="text" />
<input type="text" />
</div>
<div id="totPayForm">
<label id="totPayLbl">Total Payment:</label>
<input type="text" />
<input type="text" />
<input type="submit" value="Add new one" onclick="addNewField();
return false;">
</div>
<input type="button" value="Clone box" id="btn" />
And JS should be like this
var i = 3;
$(document).ready(function () {
$('#btn').click(function () {
var cloned = $('.PayDiv0').first().clone();
var noOfDivs = $('.PayDiv0').length;
cloned.insertBefore("#totPayForm");
cloned.attr('id', 'PayDiv' + noOfDivs);
cloned.find('label').attr('id', 'PayLbl' + noOfDivs);
cloned.find('.PayLbl2').html("Payment No " + i+++':');
});
});
As mentioned in the answer by #Arun P Johny, set the div id PayDiv0
$('#btn').click(function () {
var cloned = $('.PayDiv2').first().clone();
// find total divs with class PayDiv2
var noOfDivs = $('.PayDiv2').length;
cloned.insertBefore("#totPayForm");
// add new id to the cloned div
cloned.attr('id', 'PayDiv' + noOfDivs);
// find the label element inside new div and add the new id to it
cloned.find('label').attr('id', 'PayLbl' + noOfDivs);
cloned.find('.PayLbl2').html("Payment No " + i+++':');
});
this way you can add the dynamic ids to your elements.

use link to add content to input box

What is the simplest way to use a link to populate a input text box with the link content?
I have these links - quite few like these
P3030-6
P3030-6
this text box
<input type="text" name="code" value="" size="40" class="wpcf7-form-control wpcf7-text sidebarInput" id="code" aria-invalid="false">
When someone clicks on the link I want the P3030-6 etc to be added to the text box.
I have a great little script that uses jquery 1.7, but my site needed 1.10.2 - and adding the 1.7 scrip stopped some of the funcitonality of the site.
Any ideas on the best process greatly received!
Thanks
Well, you could add a class on the links
P3030-6
then something like
$('.forinput').click(function(e) {
e.preventDefault();
$('#code').val($(this).text());
});
see jsFiddle
EDIT
to add
$('.forinput').click(function(e) {
e.preventDefault();
var $code = $('code');
$code.val($code.val() + $(this).text());
});
see jsFiddle
You can do it may ways. it depends on your anchor tag position. you can get anchor tag by its parents elements. (e.g i have used a div with class content as parent).
Demo:
http://jsfiddle.net/a6NJk/597/
<div class="content">
P3030-61
P3030-62
<input type="text" name="code" value="" size="40" class="wpcf7-form-control wpcf7-text sidebarInput" id="code" aria-invalid="false">
</div>
Jquery:
$(".content a").click(function(e){
e.preventDefault();
$('#code').val($(this).text());
console.log("fddsf");
})
If you want to add all anchor clicked text:
Demo : http://jsfiddle.net/a6NJk/598/
then replace
$('#code').val($(this).text());
by
$('#code').val($('#code').val()+$(this).text());
if you don't want duplicate values :
demo: http://jsfiddle.net/a6NJk/600/
$(".content a").click(function(e){
e.preventDefault();
var out = $('#code').val();
if(out.indexOf($(this).text()) == -1) {
$('#code').val(out+$(this).text());
}
})
you can add , like this:
http://jsfiddle.net/a6NJk/607/
$(".content a").click(function(e){
e.preventDefault();
var out = $('#code').val();
if(out.indexOf($(this).text()) == -1) {
out = out == '' ? out: out+',';
$('#code').val(out+$(this).text());
}
})
href="" onclick="document.getElementById('code').value=this.innerHTML;return false;"
That should be in each link. Or you can do it systemically through Javascript but someone did that already so I'm gonna be different and lame.
onclick="var code = document.getElementById('code');code.value=(code.value.indexOf(this.innerHTML) < 0) ? code.value + ', ' + this.innerHTML : code.value;return false;"

Using Jquery how do I select all input text elements after currently selected input element?

I have been trying to use nextAll() and siblings() but those functions never return anything and I can only presume that it has to do with the form inputs being nested in other html elements (table cells).
// This works like I would expect but obviously returns all the input elements
$("input.tbDate").each( function(index) {
alert('class selector : Index=' + index + ' id=' + $(this).attr("id") );
});
// these next ones do not work, I only need elements after currently selected input
$(obj).siblings().each( function(index) {
alert('sibings() : Index=' + index + ' id=' + $(this).attr("id") );
});
$(obj).nextAll().each( function(index) {
alert('nextAll() : Index=' + index + ' id=' + $(this).attr("id") );
});
So I want to get all of the sibling elements that are after the currently selected element
UPDATE :
So this would work in my specific situation - see answer below
$(this).parent().parent().nextAll().find('input')...
But this is what I had already done to get my page working
$("input.tbDate").each( function(index) {
if (endDate != null)
{
if ( $(this).attr("id").indexOf("StartDate") != -1 )
{
endDate.setDate( endDate.getDate() + 1);
var dayOfTheWeek = endDate.getDay();
if (dayOfTheWeek==6)
{
endDate.setDate(endDate.getDate()+2);
}
else if (dayOfTheWeek==0)
{
endDate.setDate(endDate.getDate()+1);
}
}
endDateString = endDate.getMonth() + 1 + "/" + endDate.getDate() + "/" + endDate.getFullYear();
$(this).val( endDateString );
}
// Found input text box and grabbing
if ( $(this).attr("id") == $(obj).attr("id"))
{
endDate = new Date( $(obj).val() );
}
});
Is there a gotcha doing it the way I did it? Is one way of selecting elements preferred (faster/better) than another?
If the inputs are inside <td> wrappers you'd need to first grab the parent <td> then grab all the next sibling <td>'s and traverse into them:
$('input.tbDate').parent().nextAll().find('input').css('border','3px solid red');
Try that to put a border around the elements you seek and you'll know if JQuery is acknowledging them.
Test case HTML:
<table>
<tr>
<td>
<input type="text" class="test" />
<input type="text" class="test" />
<input type="text" class="test" />
</td>
<td>
<input type="text" class="test" />
<input type="text" class="test" />
<input type="text" class="test" />
</td>
<td>
<input type="text" class="test" />
<input type="text" class="test" />
<input type="text" class="test" />
</td>
</tr>
</table>
Test case CSS:
.red {
border:2px solid red;
}
Test case JQuery:
$(function(){
$('.test').click(function(){
$('.test').removeClass('red');
$(this).nextAll().addClass('red');
$(this).parent().nextAll().find('input').addClass('red');
});
});
Test case demo: http://jsfiddle.net/AlienWebguy/EnYdd/
Siblings() look for all the elements at the same level at both up and down the element. nextAll look for all the elements below the element but again at the same level.
I think your markup is not supporting to use these methods to find the next elements. You might have to use something else or change the markup to support these methods.

IP Range From and IP Range To - Dynamic Text Box

I want to add two dynamic text box to enter "IP Range From" to "IP Range To" and one add more button to insert new IP Range plus validations to test those ranges.
Please suggest the code.
Waiting for your early response.
Thanks in Advance
Tanu
Asuming you use jQuery, if i were you, i would create a DIV with the "textbox-list" and just after the div, a button to add new textbox in the above div.
Here is the part of code :
<div id="iprange_list">
</div>
<img src="images/plus.png" alt="new ip range image"/>
Then just add a .click() event on the id new_iprange to dynamically add a line which contains 2 input with unique ID (static text + increment a var). I suggest you to define general span with a class for each line, such as "linecontainer", and then just add a "title" property to your span with the increment var used above.
After few clicks, your div would look like that :
<div id="iprange_list">
<span class="linecontainer" title="1"><input type="text" id="tbxfrom1" /><input type="text" id="tbxto1" /></span>
<span class="linecontainer" title="2"><input type="text" id="tbxfrom2" /><input type="text" id="tbxto2" /></span>
<span class="linecontainer" title="3"><input type="text" id="tbxfrom3" /><input type="text" id="tbxto3" /></span>
</div>
<img src="images/plus.png" alt="new ip range image"/>
Finally when you validate your form just use the jquery selecter to retrieve every line in your Div, and use a .each() to iterate between your lines :
$.each($( "#iprange_list .linecontainer" ), function(i, item) {
var currentID = $(item).attr("title");
alert( $( "#tbxfrom" + currentID ).val() );
alert( $( "#tbxto" + currentID ).val() );
});
That's just an idea, i let you do the rest ;) !
To validate the IpAddress you need a regular expression to do this.
See here sample regular expression to validate the IpAddress.
Then to check the range you need to compare the two textbox value
if(textbox1.value > textbox2.value){...
To add additional IpRange, you need to create new element using DOM.
var newField = document.createElement('input');
To summarize all this see a working sample here in jsfiddle
Note: This might not be the exact things you want, its your part to do the rest.
UPDATE CODE:
SCRIPT
var ipIndex = 1;
var validIp = /^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])$/;
function addIpRange(){
var ipDiv = document.getElementById('ipRange');
var newDiv = document.createElement('div');
ipIndex++;
newDiv.innerHTML = ipIndex + '. From: <input type="text" name="ipfrom" /> To: <input type="text" name="ipto" /><input type="button" onClick="validate(\'ipRange' + ipIndex + '\');" value="Validate">'
newDiv.setAttribute('id', "ipRange" + ipIndex);
ipDiv.appendChild(newDiv);
}
function validate(id){
var divToCheck = document.getElementById(id);
var ipAdress = divToCheck.getElementsByTagName('input');
var ipFrom = document.getElementById(id).childNodes[1].value;
var ipTo = document.getElementById(id).childNodes[3].value;
if(validIp.test(ipFrom)){
if(validIp.test(ipTo)){
if(ipFrom > ipTo){
alert("Invalid Ip Range");
} else {
alert("Valid Ip Range");
}
} else {
alert("Invalid Ip Address [To]");
}
} else {
alert("Invalid Ip Address [From]");
}
}
HTML
<form name="ipAddress">
<div id="ipRange">
<div id="ipRange1">
1. From: <input type="text" name="ipfrom" /> To: <input type="text" name="ipto" /><input type="button" onClick="validate('ipRange1');" value="Validate">
</div>
</div>
<input type="button" value="Add" onClick="addIpRange();"/>
</form>

Categories

Resources