Append Form Fields with Javascript - javascript

When using Javascript to add additional form fields dyanamically that are contained in a single fieldset, I am running into the issue of the closing fieldset tag still be applying after the first form field. This is causing the layout to break and I need to figure out how I can work around that.
I tried to move the closing fieldset tag outside of the DIV where the additional fields are being appended to, but Firebug inspection still shows it as closing after the first item.
JAVASCRIPT
<script type="text/javascript">
$(function()
{
var template = $('#inventoryItems .inventory:first').clone(),
inventoryCount = 1;
var addInventory = function()
{
inventoryCount++;
var inventory = template.clone().find(':input').each(function()
{
var newId = this.id.substring(0, this.id.length-1) + inventoryCount;
$(this).prev().attr('for', newId); // update label for (assume prev sib is label)
this.name = this.id = newId; // update id and name (assume the same)
}).end() // back to .attendee
.attr('id', 'inv' + inventoryCount) // update attendee id
.appendTo('#inventoryItems'); // add to container
};
$('.btnAddInventory').click(addInventory); // attach event
});
</script>
HTML
<div id="inventoryItems" class="inventoryItems" style="margin:0; padding:0;">
<fieldset style="width:62%; float:left; margin-left: 19%;">
<div id="inv1" class="inventory">
<label>Inventory</label>
<select name="invItem" style="width:92%;">
<?php
$invItem_values = array("id", "name");
display_options_list($dp_conn, $invItem_values, "inventory", "id");
?>
</select>
<a class="btnAddInventory"><img src="images/icn_new_article.png"></a>
<img src="images/icn_trash.png">
</div>
</div>
</fieldset><div class="clear"></div>

You have an error in your HTML markup, an extra closing DIV tag, right before the closing FIELDSET tag. Move it after the .clear tag and you should be ok.
When parsing your HTML and encountering the closing DIV tag (which corresponds to #inventoryItems), it notices you still have a FIELDSET tag that is open so it inserts the close tag for it. Afterwards, when encountering the actual closing FIELDSET tag, it is simply ignored, because there are no open FIELDSET tags.
The original error is in your JS code. The following line adds to the DIV #inventoryItems instead of the FIELDSET.
.appendTo('#inventoryItems'); // add to container
Try replacing it with:
.appendTo('#inventoryItems > fieldset'); // add to fieldset

Related

Remove html element with javascript

When I press the Submit button if any error is generated then code create a span element.
My question is how I can clear the old error from the error container element, or if not possible then please sum up the errors.
$.each(err.responseJSON.errors, function (i, error) {
var el = $(document).find('[name="'+i+'"]');
el.after($('<span style="color: red;">'+error[0]+'</span>'));
});
I tried remove() but I cannot do it.
Thanks
you can remove the span with next().
next() finds the next sibling to the input field you are referring to.
it will give you the span:
el.next().remove();
you can use a class on the span f.e. class="validation-span"
el.next(".validation-span").remove();
this will make sure you only remove the span and no other element if existent :)
Add an span element after the input and set its HTML each time instead of using .after.
<input name="yourName">
<span class="errors"></span>
<script>
$(document).find('[name="'+i+'"] + .errors')
.html('<span style="color: red;">'+error[0]+'</span>');
</script>
I updated the both way you want, please pick which is more suitable to you
function logErrorCleanSpan(errorMessage){
$('#errorContainer').text(errorMessage);
}
logErrorCleanSpan("Hello");
logErrorCleanSpan("Jarvis");
function logErrorAppendSpan(errorMessage){
var span = $("<span>"+errorMessage+"</span>");
$('#errorContainerSpanAppend').append(span);
}
logErrorAppendSpan("1. Hello ");
logErrorAppendSpan("2. Jarvis ");
#errorContainerSpanAppend{
display:block;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<h3>Append Error and clean the previous error<h3>
<span id="errorContainer"></span>
<h3>Append Error and keep the older one<h3>
<span id="errorContainerSpanAppend"></span>
Assign a id with index to span after each click remove previous span using id
Use jquery remove
$.each(err.responseJSON.errors, function (i, error) {
var el = $(document).find('[name="'+i+'"]');
el.after($('<span id="error'+i+'" style="color: red;">'+error[0]+'</span>'));
if($(document).find('span#error+i - 1+')) {
$( "span#error+i - 1+" ).remove();
}
});
this is just an example code not correct code.

Image Being Appended and Removed But Text Not being Removed jQuery

So here's my code:
<input type = checkbox id = "kinch" name = "link" > Bunz </input>
<div id = bootypipe></div>
Here's the JavaScript:
$("#kinch").click(function(){
if ($("#kinch").is(":checked")) {
//Add image to div bootypipe
$("#bootypipe").append("<image id = 'chink' src = 'http://4.bp.blogspot.com/_TUdhYRa2Xm0/RsuDa4NvSEI/AAAAAAAAAQs/jr_r6v_SUgs/s320/New-England-Style-Hot-Dog-Buns_8A827671.jpg'>HA!</image>");
} else {
$("#chink").remove();
}
});
Here's the jsfiddle: http://jsfiddle.net/shrimpboyho/wUu34/13/
The image removes and appends, but when I remove the image the text Ha! still stays and builds up over time. How can I remove this?
Cant you just do :
$("#bootypipe").empty();
instead of removing image.
Because you only remove the image tag not the text. You could do like this
wrap the image and text with one div and then remove the div tag like
$("#kinch").click(function(){
if ($("#kinch").is(":checked")) {
//Add image to div bootypipe
$("#bootypipe").append("<div id='chink_outer'><img id = 'chink' src = 'http://4.bp.blogspot.com/_TUdhYRa2Xm0/RsuDa4NvSEI/AAAAAAAAAQs/jr_r6v_SUgs/s320/New-England-Style-Hot-Dog-Buns_8A827671.jpg'/>HA!</div>");
} else {
$("#chink_outer").remove();
}
});
Demo
<image id = 'chink' src = 'http://4.bp.blogspot.com/_TUdhYRa2Xm0/RsuDa4NvSEI/AAAAAAAAAQs/jr_r6v_SUgs/s320/New-England-Style-Hot-Dog-Buns_8A827671.jpg'>HA!</image>
is invalid HTML markup; the element can't actually contain text. And the correct tag is <img>. I suspect it is actually being interpreted as
<img id='chink' src='...' > HA!
meaning the text isn't part of the element, and isn't removed with it.
Instead of doing $('#chink').remove(), do $('#bootypipe').empty() to remove everything you added.
The <img> element is self closing, like <br> or <hr> (your demo code is invalid, as mentioned in another answer).
But your code works, if you just include a wrapper (<p>,<span>,<div>) around the image. Then remove the wrapper (ie $('p').remove();). Do not add additional ids, classes (you've already created a function around #kinch. why add to the code?). Just target the wrapper. $('#chink').parent().remove(); works too, and it's unbiased to what element is the parent.
$("#kinch").click(function(){
if ($("#kinch").is(":checked")) {
$("#bootypipe").append("<p><image id = 'chink' src = '...'>HA!</p>");
} else {
$('p').remove();
// or $('#chink').parent().remove(); // pick your poison
}
});

jQuery: How to assign the right ID to a button dynamically

I have a JS/jQuery script that adds our leads (web contacts) to the DOM in a for loop. Everything works fine except for one thing. I want the body of the lead to be hidden upon the initial display, and then have a slideToggle button to display or hide the details That means dynamically adding click events to each button as it is created. The entire HTML (HTML and a JSON object mixed into the HTML) of the lead and the slideToggle button are all appended to a node in the DOM in the for loop. Here is the pertinent part of the for loop:
// Hide the body of the lead; just show the title bar and the first line
var dataID = data[i].id
var div = $('#row' + dataID);
var more = $('#more' + dataID);
div.hide();
// Create click event for each "+" button
more.click(function() {
div.slideToggle();
});
But when I click on the "+" button to reveal the details, it opens the last div, not the div I am trying to open. This is true no matter how many leads I have on the page. How do I get the click event to open the right div. If I console.log "div" in the click event, it gives me the ID of the last div, not the one I am clicking on. But if I console.log(div) outside the click event, it has the right ID.
Also, I was unsure whether I needed the "vars" in the loop or if I should declare them outside the loop.
Here is the HTML. It's one lead plus the beginning of the next lead, which I left closed in Firebug
<div id="lead1115">
<div id="learnmore">
<a id="more1115" class="more" href="#">+</a>
</div>
<div id="lead-info">
<div id="leadID">Lead ID# Date: March 27, 2012 11:26 AM (Arizona time)</div>
<div id="company">No company given</div>
<div id="name">Meaghan Dee</div>
<div id="email">
meaghan.dee#gmail.com
</div>
<br class="clearall">
<div>
<div id="row1115" style="display: none;">
<div id="phone">No phone given</div>
<div id="source">www.ulsinc.com/misc/expert-contact/</div>
<div id="cp-name">No channel partner chosen</div>
<br class="clearall">
<div id="location">
No location given
<br>
<strong>IP Address:</strong>
198.82.10.87
<br>
<span>Approximate Location: Blacksburg, Virginia, United States</span>
<br>
</div>
<div id="details">
<strong>Questions/Comments</strong>
<br>
We have the Professional Series Universal Laser Systems (laser cutter), and I wondered how I would order a high power density 2.0 replacement lens.nnThank you
</div>
</div>
</div>
</div>
<div id="learnmore">
<a id="1115|send_message" class="verify" href="#">Verify</a>
<a id="1115|send_message" class="markAsSpam" href="#">Spam</a>
<a id="1115|send_message" class="markAsDuplicate" href="#">Duplicate</a>
</div>
</div>
<br class="clearall">
<div id="lead1116">
<br class="clearall">
Try using .bind (or .on for 1.7+) and the data parameter.
more.bind("click",{target:div},function(e){
e.data.target.show();
}
or
more.on("click",{target:div},function(e){
e.data.target.show();
}
I think your basic problem is that div is common as a variable to all items. You have to separate the div's from each other by, for example, creating a local function and call it for each item. Something like:
function buildMore(div) {
more.click(function() {
div.slideToggle();
});
}
and in the loop call:
addMore(div);
p.s.
Whether you declare your variables inside or outside the loop doesn't matter: you still get the same variables.
This is because div variable gets changed and settles with the last value set in the loop.
Try this:
...
funciton createClick(div) {
return function() { div.slidToggle();
}
more.click( createClick(div) );
...
The variable div doesn't stay frozen with your click handler so it's value will be what it was at the end of the for loop and all click handlers will use the same value (which is what you're seeing).
There are a number of different ways to approach this and I thought all would be educational. Any one of them should work.
Idea #1 - Manufacture the row id from the clicked on more id
Use the id value on the clicked on link to manufacture the matching row ID. Since you create them in pairs, this can be done programmatically like this:
// Hide the body of the lead; just show the title bar and the first line
var dataID = data[i].id
$('#row' + dataID).hide();
$('#more' + dataID).click(function() {
// manufacture the row ID value from the clicked on id
var id = this.id.replace("more", "#row");
$(id).slideToggle();
});
Idea #2 - Use a function closure to "freeze" the values you want
Another way to do that is to create a function and closure that will capture the current value of div:
// Hide the body of the lead; just show the title bar and the first line
var dataID = data[i].id
var div = $('#row' + dataID).hide();
var more = $('#more' + dataID);
function addClick(moreItem, divItem) {
// Create click event for each "+" button
moreItem.click(function() {
divItem.slideToggle();
});
}
addClick(more, div);
Idea #3 - Use the HTML spatial relationship to find the row associated with a more
To make this work, you need to put a common class=lead on the top level lead div like this:
<div id="lead1115" class="lead">
And, a common class on each row:
<div id="row1115" class="row" style="display: none;">
Then, you can use the position relationships to find the row object that is in the same parent lead object as the clicked on more link like this:
// Hide the body of the lead; just show the title bar and the first line
var dataID = data[i].id
$('#row' + dataID).hide();
$('#more' + dataID).click(function() {
// find out common parent, then find the row in that common parent
$(this).closest(".lead").find(".row").slideToggle();
});
Idea #4 - Put the row ID as data on the more link
// Hide the body of the lead; just show the title bar and the first line
var dataID = data[i].id
$('#row' + dataID).hide();
$('#more' + dataID).data("row", "#row" + dataID).click(function() {
// get the corresponding row from the data on the clicked link
var rowID = $(this).data("row");
$(rowID).slideToggle();
});

remove the hidden values and <br> when replacing via .html

I have a code which allows me to add certain "absentees", along with their ID's through a hidden form, to the absentees list when I click on them. When I click on it again, the "absentee" is removed from the absentees list. However, when I click on it again, the list seems to extend further because of a br
in my code plus the hidden form value doesn't seem to be removed. I need the hidden value removed so that the removed absentee from the list will not be recorded in the database. I need the br
so that the absentee listing will be presentable.
Here's my code: http://jsfiddle.net/gk5pV/8/
I wholeheartedly agree with #charlietfl, just use a block level element. Also, use a single hidden input to track your absentees. Example fiddle, code below:
$(function() {
$("td").click(function() {
var $this = $(this);
var user = $this.attr('id');
var p = $('<p />').attr('user', user).text($this.text());
var absentees = [];
if ($('#absentees').val().length > 0) {
absentees = $('#absentees').val().split(',')
}
if ($(this).hasClass('on')) {
//console.log("Already marked absent");
//remove from collection
$("#collect").children('p[user="' + user + '"]').remove();
absentees.splice(absentees.indexOf(user), 1);
}
else {
//console.log(user);
//add to collection
$("#collect").append(p);
absentees.push(user);
}
$this.toggleClass('on');
$('#absentees').val(absentees.join(','));
});
$("#clicky").click(function() {
$('td').removeClass('on');
$("#collect").empty();
$('#absentees').val('');
});
});​
Solution is fairly simple. Wrap the text you want to append and hidden input in a block level element ( div, p, li etc) and you won't need a <br tag. WHen you remove the absentee from list you remove the block element and the input will be part of it so it will no longer exist. If you give the new block level element a class name you can simply attach your event handler to the class

jQuery display html in textarea exclude an element

I have 4 divs in a container. I want to display the html of the container which contains the divs in the textarea. I'm able to do this. The issue is, i don't want to get all the html of the container. I don't want to get #iv #three. I want to copy all the html of the container except div #three. I could use $('#three').remove() but i don't want to remove the div, I just don't want to copy it's html value to textarea. Check jsfiddle http://jsfiddle.net/rzfPP/
<div id="container">
<div id="one">test 1 </div>
<div id="two">test 2 </div>
<div id="three">test 3 </div>
<div id="four">test 4 </div>
</div>
<textarea id="save"></textarea>
var x = $('#container').html();
$('#save').val(x);
Try this
$("#container").clone().find("#three").remove().end().html();
http://jsfiddle.net/rzfPP/21/
/*
var x = $('#container').html();
$('#save').val(x);
*/
var lol = $('#container').clone()
$(lol).find('#three').remove();
$('#save').val(lol.html());
$('#container').clone().find('#three').remove().end().html();
Technically this is illegal since you are duplicating IDs, but it works fine.
http://jsfiddle.net/rzfPP/33/
Edit: Someone beat me to it :( Oh well.
var text = "";
$('#container div').each( function() {
if ( this.id != "three" ) {
text += $(this).html();
}
});
$('#save').val( text );
http://jsfiddle.net/rzfPP/31/
Basically you check the divs inside #container one by one, and check their id. If it's one you want, add their html to a string. Then at the end give that string as your textarea value.

Categories

Resources