jQuery Field Not Being Removed After Appending it - javascript

I am running into an issue where I can't seem to get my jQuery script to remove fields after they have been added. I have tried a few changes, but nothing has worked.
$(function() {
var dataSourceField = $('#sign-up-organization-discovery-source');
var i = $('#sign-up-organization-discovery-source p').size() + 1;
$('#sign-up-add-discovery-source').on('click', function() {
$('<p><label for="discovery-source-field"><input type="text" id="discovery-source-field" size="20" name="discoverySource" value="" placeholder="Input Value" /></label> Remove</p>').appendTo(dataSourceField);
i++;
return false;
});
$('#remScnt').on('click', function() {
if (i > 2) {
$(this).parents('p').remove();
i--;
}
return false;
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="container">
<div class="col-md-6 col-md-offset-3">
<form action="/app/sign-up/organization" method="post">
<p>{{user.email}}</p>
<input type="hidden" name="admin" value="{{user.email}}">
<input type="hidden" name="organizationId">
<label for="sign-up-organization">Company/Organization Name</label>
<input type="text" class="form-control" id="sign-up-organization" name="organizationName" value="" placeholder="Company/Organization">
Add Another Discovery Source
<div id="sign-up-organization-discovery-source">
<input type="text" id="discovery-source-field" placeholder="Discovery Source" name="discoverySource">
</div>
<br />
<button type="submit">Submit</button>
</form>
Already have an account? Login here!
</div>
</div>

There are a couple problems here.
Firstly, an id is suppose to be unique! You are duplicating id attribute values each time you append the element.
Secondly, even if you were to use a class rather than an id, it still wouldn't work as expected because the clickable/removable a element doesn't exist in the DOM when you are attaching the event listeners.
You would either need to attach the event after appending the element, or you could use event delegation and attach the event to a common parent element that exists at the time.
Example Here
$('#sign-up-organization-discovery-source').on('click', '.remove', function() {
// ...
});
I changed Remove to: Remove.
Then I delegated the click event to the #sign-up-organization-discovery-source element.

$('##sign-up-organization-discovery-source').on('click', '#remScnt', function() {
if (i > 2) {
$(this).parents('p').remove();
i--;
}
return false;
});

Related

jquery find closest class and increase value

I have buttons to increase/decrease quantity in a cart
<div class="product-quantity">
<button class="qtyminus">-</button>
<input type="text" name="quantity" value="1" class="qty form-control">
<button class="qtyplus">+</button>
</div>
my javascript unfortunately doesn't work can't figure out why.
$('.qtyplus').on('click', function(e) {
e.preventDefault();
var num = Number($(this).closest('.qty').val());
$(this).closest('.qty').val(++num);
});
jQuery closest searches ancestors, but in this case, you're looking for the sibling element. Try siblings instead of closest
By the way, modern browsers have built-in debugging tools. It's easy to set a breakpoint and step through you code to see what's happening, and to use the console window to test things.
You should use siblings() instead of closest() as closest() searches for ancestors while siblings() searches for siblings of an element.
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="product-quantity">
<button class="qtyminus">-</button>
<input type="text" name="quantity" value="1" class="qty form-control">
<button class="qtyplus">+</button>
</div>
<script>
$('.qtyplus').on('click', function(e) {
e.preventDefault();
var num = Number($(this).siblings('.qty').val());
$(this).siblings('.qty').val(++num);
});
$('.qtyminus').on('click', function(e) {
e.preventDefault();
var num = Number($(this).siblings('.qty').val());
$(this).siblings('.qty').val(--num);
});
</script>
Your issue is because closest() looks up the DOM, yet .qty is a sibling to the clicked buttons, so you need to use siblings() instead.
Also note that you can use a single event handler for both buttons if you put a common class on them and provide the value to add in a data attribute. You can also negate the need to repeatedly select the same element by providing a function to val() which returns the new value based on its current one. Try this:
$('.amendqty').on('click', function(e) {
e.preventDefault();
var inc = $(this).data('inc');
$(this).siblings('.qty').val(function(i, v) {
return parseInt(v, 10) + inc;
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="product-quantity">
<button class="amendqty" data-inc="-1">-</button>
<input type="text" name="quantity" value="1" class="qty form-control">
<button class="amendqty" data-inc="1">+</button>
</div>

JS Auto select next input and detect last input

Im trying to auto jump to the next input once keypress is triggered but my code isnt working and I believe its todo with the next() select but can't seem to get it selected correctly.
HTML Form
<form method="POST" action="">
<div id="confirm-input">
#csrf
<div class="col-xs-1">
<input type="text" class="form-control input" maxlength="1"/>
</div>
<div class="col-xs-1">
<input type="text" class="form-control input" maxlength="1"/>
</div>
<div class="col-xs-1">
<input type="text" class="form-control input" maxlength="1"/>
</div>
<div class="col-xs-1">
<input type="text" class="form-control input" maxlength="1"/>
</div>
<div class="col-xs-1">
<input type="text" class="form-control input" maxlength="1"/>
</div>
<div class="col-xs-1">
<input type="text" class="form-control input" maxlength="1"/>
</div>
</div>
</form>
JS Code
$('.input').keyup(function (e) {
if (this.value.length == this.maxLength) {
var next = $(this).nextAll('input').first();
//Check if there is a next input.
if (next.length) {
next.focus();
} else {
$(this).blur
//AJAX CALL
}
}
});
Im using nextAll() as i believe it can look outside the div but not having any luck.
"Im using nextAll() as i believe it can look outside the div but not having any luck."
That's your problem right there. nextAll() only looks on the same tree level in the DOM. (Plunker here to demonstrate: http://plnkr.co/edit/u5t2Oy636xvl82WIgmvp?p=preview)
One possible solution would be to give your inputs successive ids, so that if your current input has an id of, say, "input-2", the look for "input-3" as the next input to focus on.
Update:
Here's a working Plunker that illustrates the above idea: http://plnkr.co/edit/UT5HydtxzyxkTIt5LBeZ?p=preview
$('.input').keyup(function (e) {
if (this.value.length == this.maxLength) {
var currId = $(this).attr('id');
var nextId = '#input-' + (Number(currId.split('-')[1]) + 1);
var next = $(nextId);
//Check if there is a next input.
if (next.length) {
next.focus();
} else {
$(this).blur
//AJAX CALL
}
}
}
My suggested solution is to determine how many elements match the selector then invoke .focus() using the index of each element, .blur() on the last element. You probably don't want to fire the AJAX call unless you've hit maxLength, hence the else if statement rather than just else.
var selector = "#confirm-input .input";
$(selector).keyup(function (e) {
var i = $(this).index(selector);
var len = $(selector).length - 1;
if (this.value.length == this.maxLength && i < len) {
$(selector).eq(i+1).focus();
}
else if(this.value.length == this.maxLength && i === len) {
$(this).blur();
//AJAX CALL
}
});

JQuery: how to check if checkbox is checked and add attributes to field

I'm trying to check whether a check box is checked, and if it is checked, then I want to add the "required" attribute to an adjacent text field. I've tried it two different ways with no success. Here are the form elements and my two JQuery attempts.
neither of those will actually trigger the event. My browser either does nothing at all or triggers an "Empty string passed to getElementById()." event
Form elements:
<div class="col-sm-5">
<label id="checkboxNumber-label" class="toplabel" for="checkboxNumber">Checkbox</label>
<g:textField name="checkboxNumber" value="${...checkboxNumber}" class="form-control" required="" aria-labelledby="checkboxNumber-label"/>
<label class="checkbox-inline">
<g:checkBox name="checkboxYesNo" id="checkboxYesNo" value="${...checkboxYesNo}" onclick="chkboxYesChecked()"/>
</label>
</div>
<div class="col-sm-5">
<label id="someTextField-label" class="toplabel" for="someTextField">Some Text Field Here</label>
<g:textField name="someTextField" id="someTextField" value="${...someTextField}" class="form-control" aria-labelledby="someTextField-label"/>
</div>
JQuery:
function chkboxYesChecked(){
if($('#checkboxYesNo').prop('checked')){
$('#someTextField').prop('required',true);
$('#someTextField').append('<span class="required-indicator">*</span>');
}else{
$('#someTextField').removeAttr('required');
}
}
$(document).ready(function() {
$('#checkboxYesNo').click(function() {
if($(this).is(":checked"))
{
$('#someTextField').prop('required',true);
$('#someTextField').append('<span class="required-indicator">*</span>');
} else {
$('#someTextField').removeAttr('required');
}
});
});
With your markup this becomes more convoluted than it needs to be.
$(document).on("click", ".checkbox-inline :checkbox", function () {
var $nextTextbox = $(this).closest("div").next("div").find(":text").first();
if (this.checked) {
$nextTextbox.prop("required", true).after('<span class="required-indicator">*</span>');
} else {
$nextTextbox.prop("required", false).next('.required-indicator').remove();
}
});
Notes
This approach uses event delegation.
There are no IDs involved, because I suppose you need the same thing more than once on your page. Tying it to a specific element ID is counter-productive.
This approach relies on the specific document structure from your sample Grails template. If you want something more flexible and easier-to-read, change your HTML.
This applies to all checkboxes that have a text field in the immediately following <div>. Use CSS classes on your elements to filter it/make it apply to specific ones only.
If there is no immediately following <div> with a text box, the function does nothing.
$(this).is(":checked") is superfluous. You don't need jQuery to find out if the current DOM element is checked. this.checked is a lot simpler and has the same effect.
Don't use inline event handlers (onclick="..."). Ever.
See it in action:
$(document).on("click", ".checkbox-inline :checkbox", function () {
var $nextTextbox = $(this).closest("div").next("div").find(":text").first();
if (this.checked) {
$nextTextbox.prop("required", true).after('<span class="required-indicator">*</span>');
} else {
$nextTextbox.prop("required", false).next('.required-indicator').remove();
}
});
input[required] {
background-color: #FFD1D1;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="col-sm-5">
<label id="checkboxNumber-label" class="toplabel" for="checkboxNumber">Checkbox</label>
<input type="text" name="checkboxNumber" value="${...checkboxNumber}" class="form-control" required="" aria-labelledby="checkboxNumber-label" />
<label class="checkbox-inline">
<input type="checkbox" name="checkboxYesNo" id="checkboxYesNo" value="${...checkboxYesNo}" />
</label>
</div>
<div class="col-sm-5">
<label id="someTextField-label" class="toplabel" for="someTextField">Some Text Field Here</label>
<input type="text" name="someTextField" id="someTextField" value="${...someTextField}" class="form-control" aria-labelledby="someTextField-label" />
</div>

Append and remove not working as they should

For some weird reason, my append is only adding but not removing.
Here is the HTML:
<div class="insert-links"></div>
<a href="#" id="button" onclick="return false;">
<img src="http://a.dryicons.com/images/icon_sets/blue_extended_icons_set/png/64x64/add.png" ">
</a>
and the jQuery is the following:
<script type='text/javascript'>//<![CDATA[
$(function() {
var i = 0;
$('#button').click(function() {
if (i < 10) {
$('.insert-links').append('<p style="display: none;" class="new-link"><input tabindex="1" placeholder="Command eg: give #user# 264" style="width:285px\;margin-top: 12px\;" type="text" name="fname" id="fname"/> <input tabindex="1" placeholder="Price" style="width:45px\;background-color:#f4faff\;" title="Price in points of this item" type="text" name="fname" id="fname"/><img src="http://c.dryicons.com/images/icon_sets/blue_extended_icons_set/png/128x128/remove.png" style="width: 20px;float: right;margin-top: 19px;margin-right: 19px;"></p>');
$('.insert-links').find(".new-link:last").slideDown("slow");
i++;
}
});
$('#buttonremove').click(function() {
if (i > 0) {
$('#buttonremove').parent('p').remove();
i--;
}
});
});//]]>
</script>
Could anyone please help me?
Use jQuery Event Delegation for this:
Fiddle Demo
$('.insert-links').on('click', '#buttonremove', function() {
if (i > 0) {
$('#buttonremove').parent('p').remove();
i--;
}
});
The problem is that you are binding the click event to the "buttonremove" when the page is loading , in that specific moment the paragraph containing all other elements does not exists yet. What you have to do is to move the binding code inside the click of the #button.

Jquery append() doesn't work on new <a>Add</a>

Append() working fine but it is working only on the first <a class="add">Add</a>. not able to add new input field with the latest <a class="add">Add</a>
Here is my code
$(document).ready(function(){
var scntDiv = $('#add_words');
$('.add').click(function() {
$("#add_words").append('<div class="line">Word is <input type="text" /><a class="add">Add</a></div>');
return false;
});
});
html code
<div id="add_words">
<div class="line">Word is 1<input class="input1" type="text" value="1" /><a class="add">Add</a></div>
</div>
That's because click only attaches the click event handler to existing DOM elements, not future ones. You need jQuery on:
$(document).ready(function() {
$("#add_words").on("click", ".add", function(e) {
// Do your append here
// e.delegateTarget is your <div id="add_words">
$(e.delegateTarget).append('<div class="line">Word is <input type="text" /><a class="add">Add</a></div>');
// Prevent default action (e.g. don't follow links)
e.preventDefault();
});
});
Use on() for event delegation instead of click():
$('#add_words').on('click', '.add', function(){
$("#add_words").append('<div class="line">Word is <input type="text" /><a class="add">Add</a></div>');
});
use Live like this: see this jsfiddle
$('.add').live("click", function(event) {
$("#add_words").append('<div class="line">Word is <input type="text" /><a class="add">Add</a></div>');
return false;
});

Categories