jQuery .on() issue, console.log() works but element interaction doesn't - javascript

I am using this code inside $(document).ready(function(){ ... }):
$('#flavours').on('click', '.toggle-quantity', function(e){
e.preventDefault();
var $quantity_percent = $(this).parent().find('.quantity_percent');
if($quantity_percent.is(':hidden')){
console.log("is hidden");
$quantity_percent.show();
}else{
console.log("is not hidden");
$quantity_percent.hide();
}
});
What's happening is the console.log() is working, but the $quantity_percent is not showing/hiding.
Additionally, if I add an alert('test') to the beginning of the function (just after e.preventDefault) this also doesn't work, but the console.log() continues to work (it correctly logs 'is not hidden').
EDIT: Relevant HTML markup:
<div id="flavours">
<div class="row flavour" id="flavour_1" style="display: block;">
<div class="form-group">
<div class="col-xs-12">
<fieldset>
<legend>Flavour 1</legend>
<div class="col-sm-4">
<label>Flavour Name</label>
<input type="text" value="" name="flavour_name[]" data-flavour-id="1" id="flavour_name_1" class="form-control autocomp" placeholder="Flavour name">
<input type="hidden" value="" name="flavour_id[]" id="flavour_id_1" class="form-control flavour_id">
<p class="flavour_info"></p>
</div>
<div class="col-sm-6">
<label>Flavour Quantity <span class="fa fa-filter"></span> <span class="hidden-sm">Switch to </span>drops per ml</label>
<div class="input-group" id="quantity_percent">
<input type="text" class="form-control" id="flavour_percentage_1" name="flavour_percentage[]" placeholder="Flavour Quantity">
<span class="input-group-addon">%</span>
</div>
<div class="input-group" id="quantity_drops" style="display: none;">
<input type="text" class="form-control" id="flavour_drops_1" name="flavour_drops[]" placeholder="Flavour Quantity">
<span class="input-group-addon">drops/ml</span>
</div>
<p class="flavour_recommended_percentage"></p>
</div>
<div class="col-sm-2">
<label> </label>
<button class="btn btn-danger btn-block remove-flavour"><span class="glyphicon glyphicon-remove"></span> Remove</button>
</div>
</fieldset>
</div>
</div>
</div>

$(this).parent() is a label element which doesn't have a child with .quantity_percent
Also quantity_percent is an id and not a class. Use the ID selector
So use
var $quantity_percent = $('#quantity_percent');
instead of
var $quantity_percent = $(this).parent().find('.quantity_percent');
Note: IDs must be unique in HTML
EDIT: as per OPs comments
I updated it to a class rather than ID (as it's on a dynamically growing list)
Usage
var $quantity_percent = $(this).closest('.col-sm-6').find('.quantity_percent');

The .parent() targets the <label> therefore it can't find .quantity_percent

Related

How to control the disability state of HTML inputs using Javascript

I have been trying to cycle between the disability states of two inputs on my website by using a button attached to some JavaScript. My current code has two buttons in use which both disable one input and enable the other, however this is not very practical. I wanted to know how I can use one button and one script to cycle between the disability states of my inputs, this is my current code:
<script>
function switch_monthlyexpense()
{
document.getElementById("monthlyexpenses").disabled=false;
document.getElementById("monthlypexpenses").disabled=true;
}
</script>
<script>
function switch_monthlypexpense()
{
document.getElementById("monthlyexpenses").disabled=true;
document.getElementById("monthlypexpenses").disabled=false;
}
</script>
<button class="btn btn-primary" onclick="switch_monthlyexpense()" id="monthlyexpensestoggle">Expenses</button>
<button class="btn btn-primary" onclick="switch_monthlypexpense()" id="monthlypexpensestoggle">P Expenses</button>
<form id="expenses_form" style="visibility:visible;">
<div class="form-group">
<div class="form-group col-md-1">
<label for="monthlyexpenses" id="monthlyexpenseslabel">Monthly Expenses</label>
<input type="number" class="form-control" id="monthlyexpenses" placeholder="0" disabled>
</div>
<span class="input-group-text" id="dsign5">$</span>
</form>
<form id="pexpenses_form" style="visibility:visible;">
<div class="form-group">
<div class="form-group col-md-1">
<label for="monthlypexpenses" id="monthlypexpenseslabel">Monthly P Expenses</label>
<input type="number" class="form-control" id="monthlypexpenses" placeholder="0">
</div>
<span class="input-group-text" id="psign4">%</span>
</form>
<script>
// use a variable to note which one is disabled
let selected = "monthlyexpenses"
function switchDisabled () {
// toggle the from "monthlyexpenses" to "monthlypexpenses" or vice versa
selected = selected === "monthlyexpenses" ? "monthlypexpenses" : "monthlyexpenses"
// check if the DOM disabled state is the same as the selected
document.getElementById("monthlyexpenses").disabled = selected === "monthlyexpenses";
document.getElementById("monthlypexpenses").disabled = selected === "monthlypexpenses";
}
</script>
<button class="btn btn-primary" onclick="switchDisabled()" id="switch-button">Switch</button>
<form id="expenses_form" style="visibility:visible;">
<div class="form-group">
<div class="form-group col-md-1">
<label for="monthlyexpenses" id="monthlyexpenseslabel">Monthly Expenses</label>
<input type="number" class="form-control" id="monthlyexpenses" placeholder="0" disabled>
</div>
<span class="input-group-text" id="dsign5">$</span>
</form>
<form id="pexpenses_form" style="visibility:visible;">
<div class="form-group">
<div class="form-group col-md-1">
<label for="monthlypexpenses" id="monthlypexpenseslabel">Monthly P Expenses</label>
<input type="number" class="form-control" id="monthlypexpenses" placeholder="0">
</div>
<span class="input-group-text" id="psign4">%</span>
</form>
disabled is an attribute so you can set it by:
document.getElementById("myId").setAttribute('disabled', '');
And to enable the element:
document.getElementById("myId").removeAttribute('disabled');
Your first function will look like:
function switch_monthlyexpense()
{
document.getElementById("monthlyexpenses").removeAttribute('disabled');
document.getElementById("monthlypexpenses").setAttribute('disabled', '');
}

Second Time Checkbox Not Working

I have created a two javascript.
1.When i click the checkbox the input field is appeared and when i unchecked input field is disappeared.
2.Second is when i click the add more items the all fields are created one more time.
Now the problem is when is created a second and more items the checkbox is not working.
HTML Code:
<div class="container">
<div class="row">
<div class="col-lg-12 col-md-12">
<div data-role="dynamic-fields">
<div class="form-inline">
<div class="row">
<div class="col-md-3">
<div class="form-group">
<input type="text" class="form-control" id="Name1" placeholder="Food Name" name="Name1" style="width:120%;" required data-rule-minlength="2">
<label class="sr-only" for="field-name">Name</label>
</div>
</div>
<div class="col-md-3">
<div class="form-group">
<input type="text" class="form-control" id="field-value" placeholder="Description" style="width:120%;" required>
<label class="sr-only" for="field-value">Description</label>
</div>
</div>
<div class="col-md-2">
<div class="form-group">
<select id="select1" name="select1" style="width:130%;" class="form-control" required>
<option value=""></option>
<option value="1">Food Type 1</option>
<option value="2">Food Type 2</option>
<select>
<label for="select1">Food Type</label>
</div>
</div>
<div class="col-md-4">
<div class="form-group">
<input type="text" value="" class="form-control" data-role="tagsinput" placeholder="Tags" />
<label class="sr-only" for="field-tags">Tags</label>
</div>
</div>
</div>
<div class="row">
<div class="form-inline">
<div class="col-md-3">
<div class="form-group">
<input type="text" class="form-control" id="Name1" placeholder="Price" name="price" style="width:120%;" required data-rule-minlength="2">
<label class="sr-only" for="field-name">Price</label>
</div>
</div>
<div class="col-md-2">
<div class="checkbox checkbox-styled">
<label><em>Half Plate Price</em>
<input type="checkbox" value="" id="trigger2" name="question"> </label>
</div>
</div>
<div class="col-md-1">
<div id="hidden_fields2">
<input type="text" id="hidden_field2" name="hidden" placeholder="Price" class="form-control" style="width:140%;margin-left:-35px;height: 29px;margin-top: 24px;font-weight: 380;font-size: 16px;line-height: 1.5;"> </div>
</div>
<div class="col-md-3">
<div class="checkbox checkbox-styled">
<label><em>Quarter Plate Price</em>
<input type="checkbox" value="" id="trigger" name="question"> </label>
</div>
</div>
<div class="col-md-1">
<div id="hidden_fields">
<input type="text" id="hidden_field" name="hidden" placeholder="Price" class="form-control" style="width:140%;margin-left:-100px;height: 29px;margin-top: 24px;font-weight: 380;font-size: 16px;line-height: 1.5;"> </div>
</div>
</div>
</div>
<button class="btn btn-icon-toggle btn-delete" data-toggle="tooltip" data-placement="bottom" title="Delete Field" data-role="remove"> <span class="md md-delete"></span> </button>
<button class="btn btn-primary" data-toggle="tooltip" data-placement="bottom" title="Add More Field" data-role="add"> Add More Items </button>
</div>
<!-- /div.form-inline -->
</div>
<!-- /div[data-role="dynamic-fields"] -->
</div>
<!-- /div.col-md-12 -->
</div>
<div class="form-group">
<button type="button" name="submit" href="#" class="btn ink-reaction btn-raised btn-primary">Submit Items</button>
</div>
<!--end .form-group -->
</div>
Checkbox Js:
<script type="text/javascript">
$(function() {
// Get the form fields and hidden div
var checkbox = $("#trigger");
var hidden = $("#hidden_fields");
hidden.hide();
checkbox.change(function() {
if (checkbox.is(':checked')) {
// Show the hidden fields.
hidden.show();
} else {
// Make sure that the hidden fields are indeed
// hidden.
hidden.hide();
$("#hidden_field").val("");
}
});
});
$(function() {
var checkbox = $("#trigger2");
var hidden = $("#hidden_fields2");
hidden.hide();
checkbox.change(function() {
if (checkbox.is(':checked')) {
// Show the hidden fields.
hidden.show();
} else {
hidden.hide();
$("#hidden_field2").val("");
}
});
});
</script>
Add more items JS:
$(function() {
// Remove button
$(document).on('click', '[data-role="dynamic-fields"] > .form-inline [data-role="remove"]', function(e) {
e.preventDefault();
$(this).closest('.form-inline').remove();
});
// Add button
$(document).on('click', '[data-role="dynamic-fields"] > .form-inline [data-role="add"]', function(e) {
e.preventDefault();
var container = $(this).closest('[data-role="dynamic-fields"]');
new_field_group = container.children().filter('.form-inline:first-child').clone();
new_field_group.find('input').each(function() {
$(this).val('');
});
container.append(new_field_group);
});
});
page Screenshot:
There are a couple of problems here:
You are cloning elements and then trying to access them via the same ID (you should use class)
Your functions don't target just clicked element but any element with the selector.
You are cloning elements so you need bind the click event to a non-cloned element: e.g. via $(document).on
I've updated some of your code to demonstrate what I'm talking about. In the html, I've added classes in the trigger2 and hidden_fields2 elements and display:none style to the hidden fields so they are hidden by default.:
<div class="col-md-2">
<div class="checkbox checkbox-styled">
<label><em>Half Plate Price</em>
<input type="checkbox" value="" class="trigger2" id="trigger2" name="question"> </label>
</div>
</div>
<div class="col-md-1">
<div id="hidden_fields2" class="hidden_fields2" style="display:none;">
<input type="text" id="hidden_field2" name="hidden" placeholder="Price" class="form-control" style="width:140%;margin-left:-35px;height: 29px;margin-top: 24px;font-weight: 380;font-size: 16px;line-height: 1.5;"> </div>
</div>
In the javascript, I've changed the function to run from a $(document).on event bind and used the element class instead of the id. I've also changed the code so it only effects the checkbox you change and the closest hidden elements:
$(function() {
$(document).on('change', '.trigger2', function(){
var checkbox = $(this);
var parent = checkbox.closest('.form-inline');
var hidden = parent.find(".hidden_fields2");
hidden.hide();
if (checkbox.is(':checked')) {
// Show the hidden fields.
hidden.show();
} else {
hidden.hide();
$(".hidden_field2").val("");
}
});
});
You need to use the same logic on your other functions and inputs.

Clone is duplicating multiple times, when I just want one

When I click duplicate it duplicates the row fine, but when I click it again I get another 2, then 4 etc, how can I stop this from happening and just clone one div on each click...
Jquery:
<script>
$(".clonable-button").bind('click', function(e){
e.preventDefault();
var section = $(this).data('clone');
var parent = $('[data-id="' + section + '"]');
var sequence = 0;
if(!$(this).data('last')) {
sequence = $(parent).find('.cloneable').last().data('id');
} else {
sequence = $(this).data('last');
}
$(this).data('last', ++sequence);
$(parent).append(parent.html());
});
$('.clone-wrapper').on('click', '.clone-remove',function(){
var parent = $(this).parents('.cloneable');
$(parent).remove();
});
</script>
html:
<div class="clone-wrapper" data-id="skill">
<div class="row cloneable" data-id="0">
<div class="col-md-9">
<div class="form-group">
<label for="skill_name_0">Skills and Qualifications Titles </label>
<input id="skill_name_0" placeholder="ex : PHP, WordPress" name="skill[0][name]" type="text" class="form-control" value="">
</div>
</div>
<div class="col-md-3">
<div class="form-group">
<label for="skill_percentage_0">Job Position </label>
<input id="skill_percentage_0" placeholder="ex : 90" name="skill[0][percentage]" type="text" class="form-control" value="">
</div>
</div>
<div class="col-md-12 text-right clone-remove" data-last="">
<div class="btn btn-danger btn-sm" data-clone="skill">
<i class="fa fa-times"></i> Remove Skill </div>
</div>
</div>
</div>
<div class="white-space-20"></div>
<div class="row text-right">
<div class="col-md-12">
<div class="btn btn-default btn-sm clonable-button" id="skill">
<i class="fa fa-plus"></i> Add Skill </div>
</div>
</div>
I just want the following code duplicated once on each click
<div class="row cloneable" data-id="0">
<div class="col-md-9">
<div class="form-group">
<label for="skill_name_0">Skills and Qualifications Titles </label>
<input id="skill_name_0" placeholder="ex : PHP, WordPress" name="skill[0][name]" type="text" class="form-control" value="">
</div>
</div>
<div class="col-md-3">
<div class="form-group">
<label for="skill_percentage_0">Job Position </label>
<input id="skill_percentage_0" placeholder="ex : 90" name="skill[0][percentage]" type="text" class="form-control" value="">
</div>
</div>
<div class="col-md-12 text-right clone-remove" data-last="">
<div class="btn btn-danger btn-sm" data-clone="skill">
<i class="fa fa-times"></i> Remove Skill </div>
</div>
</div>
The problem is in this line:
var parent = $('[data-id="' + section + '"]');
Each time you append new block with the same data-id number of elements that match this selector increases. So to avoid this you have make the selector more specific. Like:
var parent = $('[data-id="' + section + '"]:last');
Also there is a jQuery method to clone the element. So change your line from:
$(parent).append(parent.html());
to:
parent.append(parent.clone());
That will fix the issue.
You are binding the click event multiple times somehow, You should either use a delegated event handler or use the off method like below.
$(".clonable-button").off('click').on('click', function(e){

Setting focus inside textarea doesn't work

I have the following code:
<div class="modal-body">
<div class="form-group" id="checkDiv_0">
<div class="col-md-2 control-label">
#Translations.ReportCopy
</div>
<div class="col-md-10">
<div class="col-md-1">
<button class="btn btn-primary pull-right"><span class="glyphicon glyphicon-remove"></span></button>
</div>
<div class="col-md-11">
<textarea id="textarea_0" name="Copies" class="form-control textarea-resize"></textarea>
</div>
</div>
</div>
<div class="form-group" id="checkDiv_1">
<div class="col-md-2 control-label">
#Translations.ReportCopy
</div>
<div class="col-md-10">
<div class="col-md-1">
<button class="btn btn-primary pull-right"><span class="glyphicon glyphicon-remove"></span></button>
</div>
<div class="col-md-11">
<textarea id="textarea_1" name="Copies" class="form-control textarea-resize"></textarea>
</div>
</div>
</div>
I want to set focus on textare with the id textarea_1. Without the focus the user must left-click insisde the textarea and than can start writting inside it.
I tried with $('#textarea_1').focus(), but without success.
SOLUTION:
I solved the problem this way:
$(document).ready(function () {
$('#modal').on('shown.bs.modal',
function () {
var element = document.getElementById("textarea_0");
element.focus();
});
});
You need to wrap your jQuery code inside the .ready() function:
$(document).ready(function(){
$("#textarea_1").focus();
});
You do not need javascript for this question, since you can just do:
<textarea id="textarea_1" name="Copies" class="form-control textarea-resize" autofocus></textarea>
The autofocus attribute focuses the text area as default on the DOM.
You can use this page as reference:
http://www.w3schools.com/tags/att_textarea_autofocus.asp
Two examples without jQuery:
window.onload = function() { document.getElementById('textarea_1').focus(); };
or
window.addEventListener('load', function() { document.getElementById('textarea_1').focus(); }, false);
The second one allows you to assign multiple 'onload' events to single DOM element.
The code necessary really depends on when you need to give it focus. If you need to give it focus when the page loads, you should do what #David Li suggested.
Otherwise, you can do something like this.
document.getElementById('focusButton').onclick = function(){
document.getElementById('textarea_1').focus();
};
<div class="modal-body">
<div class="form-group" id="checkDiv_0">
<div class="col-md-2 control-label">
#Translations.ReportCopy
</div>
<div class="col-md-10">
<div class="col-md-1">
<button class="btn btn-primary pull-right"><span class="glyphicon glyphicon-remove"></span></button>
</div>
<div class="col-md-11">
<textarea id="textarea_0" name="Copies" class="form-control textarea-resize"></textarea>
</div>
</div>
</div>
<div class="form-group" id="checkDiv_1">
<div class="col-md-2 control-label">
#Translations.ReportCopy
</div>
<div class="col-md-10">
<div class="col-md-1">
<button class="btn btn-primary pull-right"><span class="glyphicon glyphicon-remove"></span></button>
</div>
<div class="col-md-11">
<textarea id="textarea_1" name="Copies" class="form-control textarea-resize"></textarea>
</div>
</div>
</div>
<input type="button" id="focusButton" value="give element focus">

Dynamic form addition/subtraction with angularjs

I am trying to get my dynamic form additions/subtractions to work correctly. The situation is that I am able to get the form block to add or remove, however, when I click the remove button it removes the most recently added block rather than the one I click on.
For example, if I add two new form blocks for a total of 3 blocks (block1, block2, block3) and I click remove on block2, instead of removing block 2 it removes block3.
I have created a plunker that demonstrates this, but it ONLY works when you launch the preview side in a separate window (otherwise the add button is inactive for some reason).
Working Example (must open in popup preview in plunker to function): plunker
<form class="form-horizontal" name="cpdForm" novalidate="" ng-submit="processForm()" ng-show="!message">
<h2>Subcontractor Performance</h2>
<hr />
<div ng-repeat="subcontractor in subcontractors">
<div class="well well-sm">Subcontractor #{{subcontractor.id}} <span id="subCounter"></span>
<button type="button" ng-click="removeSub()" class="close" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
<div class="form-group">
<div class="col-md-6">
<label for="subName">Subcontractor Name</label>
<input type="text" class="form-control" id="subName" name="subName" placeholder="Subcontractor" ng-model="formData.subName['subName'+($index+1)]" />
</div>
<div class="col-md-3">
<label for="mwbeCert">Disadvantaged Certification</label>
<select class="form-control" name="mwbeCert" ng-model="formData.mwbeCert" required="">
<option value="">Select MWBE Certification...</option>
<option ng-repeat="item in dropdownpoll['mwbecert']" value="{{item.mwbeid}}">{{item.mwbe}}</option>
</select>
</div>
<div class="col-md-3">
<label for="subAmount">Contracted Amount</label>
<div class="inner-addon left-addon">
<i class="glyphicon glyphicon-usd"></i>
<input type="text" class="form-control" id="subAmount" name="subAmount" placeholder="Contracted Amount" ng-model="formData.subAmount" />
</div>
</div>
</div>
<div class="form-group">
<div class="col-md-4">
<label for="subContactName">Contact Name</label>
<input type="text" class="form-control" id="subContactName" name="subContactName" placeholder="Contact Name" ng-model="formData.subContactName" />
</div>
<div class="col-md-4">
<label for="subContactPhone">Contact Phone</label>
<input type="text" class="form-control" id="subContactPhone" name="subContactPhone" placeholder="Contact Phone" ng-model="formData.subContactPhone" />
</div>
<div class="col-md-4">
<label for="subContactEmail">Contact Email</label>
<input type="text" class="form-control" id="subContactEmail" name="subContactEmail" placeholder="Contact Email" ng-model="formData.subContactEmail" />
</div>
</div>
<div class="form-group">
<div class="col-md-3">
<label for="subRating">Subcontractor Rating</label>
<select class="form-control" name="subRating" ng-model="formData.subRating" required="">
<option value="">Select Subcontractor Rating...</option>
<option ng-repeat="item in dropdownpoll['subrating']" value="{{item.subratingid}}">{{item.rating}}</option>
</select>
</div>
<div class="col-md-9">
<label for="subComment">Comments</label>
<input type="text" class="form-control" id="subComment" name="subComment" placeholder="Comments" ng-model="formData.subComment" />
</div>
</div>
<hr />
<button type="button" class="btn btn-info btn-sm pull-right" ng-show="showAddSub(subcontractor)" ng-click="addNewSub()">[+] Add New Sub</button>
</div>
<input type="hidden" style="display:none;" ng-model="formData.subCount" value="{{subcontractor.id}}" />
<div class="form-group">
<div class="col-sm-12">
<button class="btn btn-primary" id="submit" ng-click="submitting()" ng-disabled="buttonDisabled">{{submit}}</button>
</div>
</div>
</form>
<pre>{{formData}}</pre>
you are splicing $scope.subcontractors-1 which only behaves like it does, ie, removes the last one.
try using $event.currentTarget as a general rule, it will indicate the clicked item exactly, and don't forget to pass $event as a parameter for the remove function.
I hope this helps you
You need to pass an index to the function removeSub
I modified your fn to accept an index
$scope.removeSub = function(ind) {
var newItemNo = $scope.subcontractors.length-1;
$scope.subcontractors.splice(ind-1, 1);
};
and in your HTML you just pass the currently iterated $index
<button type="button" ng-click="removeSub($index)" class="close" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
Hope this works. But be careful your formdata and subcontrators array are not in sync after this, thats a programming logic I guess you have to fix.
Happy coding
Cheers.
Joy
Not a full answer but your not telling the function in your script.js which one to remove your just telling it to chop one off the end. Try setting it up so that you pass the current subContractor id like ng-click="removeSub({{subcontractor.subContractorId}})" (not sure what your data model is) you could also reference the index but I believe that would be harder.

Categories

Resources