Show / Hide Elements within the same parent div - javascript

I'm having trouble getting a div ('.option-other') within a parent group ('.other-row') to show/hide when the corresponding option of the select element ('.select-toggle') is selected. Right now if "other" is selected from either question set 1 or 2 it will show both of the '.option-other' divs. I tried using .parent() and .closest() as described in this solution, but can't seem to figure out the proper way to utilize it for this use case.
$(".select-toggle").change(function() {
var oth = false;
$(".select-toggle option:selected").each(function() {
if ($(this).val() == "other") oth = true;
});
if (oth) $('.option-other').show();
else $('.option-other').hide();
// tried this method as well but still doesnt work
// if (oth) $(this).closest('.other-row').children('.option-other').show();
// else $(this).closest('.other-row').children('.option-other').hide();
}).change();
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<!-- Question set 1 -->
<div class="wrapper other-row">
<div class="col">
<div class="form-group">
<label>What stuff do you eat?</label>
<select class="select-toggle" multiple>
<option>Pizza</option>
<option>Cake</option>
<option value="other">Other</option>
</select>
</div>
</div>
<div class="col">
<div class="form-group option-other">
<label>Other</label>
<input type="text" placeholder="what other stuff do you like" />
</div>
</div>
</div>
<!-- Question set 2 -->
<div class="wrapper other-row">
<div class="col">
<div class="form-group">
<label>What stuff do you drink?</label>
<select class="select-toggle" multiple>
<option>Water</option>
<option>Soda</option>
<option value="other">Other</option>
</select>
</div>
</div>
<div class="col">
<div class="form-group option-other">
<label>Other</label>
<input type="text" placeholder="what other stuff do you like" />
</div>
</div>
</div>

// you wrote:
// tried this method as well but still doesnt work
// if (oth) $(this).closest('.other-row').children('.option-other').show();
// else $(this).closest('.other-row').children('.option-other').hide();
You're close, but $.children only selects direct children of each .other-row. Since .option-other is inside .col inside .other-row, $.children can't see it. Use $.find instead.
// your original code:
var oth = false;
$(".select-toggle option:selected").each(function() {
if ($(this).val() == "other") oth = true;
});
This sets one visibility value for the entire page: if at least one "other" option is selected, anywhere, show all the text inputs. The change event is fired for the <select> that actually changed, so focus your efforts there:
var oth = false;
$(this).children("option:selected").each(function() {
if ($(this).val() == "other") oth = true;
});
if (oth) $(this).closest('.other-row').find('.option-other').show();
else $(this).closest('.other-row').find('.option-other').hide();
This works, but it could be cleaner. Showing or hiding an element based on a boolean is a common enough requirement that jQuery has a function for it: $.toggle. You can replace the if/else lines with
$(this).closest('.other-row').find('.option-other').toggle(oth);
Your $.each loop does one thing: set oth if there exists at least one selected <option> with a value of "other". You can get the same logic as a one-liner by using an attribute selector:
var oth = ($(this).find('option:checked[value="other"]').length !== 0);
(I changed :selected to :checked because you're already filtering on option elements, and :selected has a performance penalty.)
The final version:
$(".select-toggle").change(function() {
var oth = ($(this).find('option:checked[value="other"]').length !== 0);
$(this).closest('.other-row').find('.option-other').toggle(oth);
}).change();
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<!-- Question set 1 -->
<div class="wrapper other-row">
<div class="col">
<div class="form-group">
<label>What stuff do you eat?</label>
<select class="select-toggle" multiple>
<option>Pizza</option>
<option>Cake</option>
<option value="other">Other</option>
</select>
</div>
</div>
<div class="col">
<div class="form-group option-other">
<label>Other</label>
<input type="text" placeholder="what other stuff do you like" />
</div>
</div>
</div>
<!-- Question set 2 -->
<div class="wrapper other-row">
<div class="col">
<div class="form-group">
<label>What stuff do you drink?</label>
<select class="select-toggle" multiple>
<option>Water</option>
<option>Soda</option>
<option value="other">Other</option>
</select>
</div>
</div>
<div class="col">
<div class="form-group option-other">
<label>Other</label>
<input type="text" placeholder="what other stuff do you like" />
</div>
</div>
</div>
Vanilla JS version:
document.querySelectorAll('.select-toggle').forEach(el => {
el.addEventListener('change', evt => {
const oth = evt.target.querySelector('option:checked[value="other"]');
evt.target
.closest('.other-row')
.querySelector('.option-other')
.style.display = (oth ? '' : 'none');
});
// trigger change event programmatically
const event = document.createEvent('HTMLEvents');
event.initEvent('change', true, false);
el.dispatchEvent(event);
});

Here is a solution that is a little clunky but I did it relatively quick. It's kind of a work around for having to know which of your two selectors with the same class had been selected.
Here is a working example using your code.
$(".select-toggle").change(function () {
var oth = false;
$(".select-toggle option:selected").each(function () {
if ($(this).val() == "otherFood") {
oth = true;
$('.option-other-food').show();
} else {
$('.option-other-food').hide();
};
if ($(this).val() == "otherDrink") {
oth = true;
$('.option-other-drink').show();
} else {
$('.option-other-drink').hide();
};
});
}).change();
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<!-- Question set 1 -->
<div class="wrapper other-row">
<div class="col">
<div class="form-group">
<label>What stuff do you eat?</label>
<select class="select-toggle" multiple>
<option>Pizza</option>
<option>Cake</option>
<option value="otherFood">Other</option>
</select>
</div>
</div>
<div class="col">
<div class="form-group option-other-food">
<label>Other</label>
<input type="text" placeholder="what other stuff do you like"/>
</div>
</div>
</div>
<!-- Question set 2 -->
<div class="wrapper other-row">
<div class="col">
<div class="form-group">
<label>What stuff do you drink?</label>
<select class="select-toggle" multiple>
<option>Water</option>
<option>Soda</option>
<option value="otherDrink">Other</option>
</select>
</div>
</div>
<div class="col">
<div class="form-group option-other-drink">
<label>Other</label>
<input type="text" placeholder="what other stuff do you like"/>
</div>
</div>
</div>
Cheers!

Related

Removing html input array elements

Take the following code for example:
<div id="instructor_trainers">
<div id="trainer-1" class="trainer-group form-group row">
<div class="col-md-6">
<select class="form-control" id="trainers[1][trainer]" name="trainers[1][trainer]">
<option value="">-- Select --</option>
</select>
</div>
<div class="col-md-6">
<input type="text" class="trainer-expiration form-control" placeholder="Expiration" id="trainers[1][expiration]" name="trainers[1][expiration]" value="">
</div>
<div class="col-xs-12">
<textarea class="trainer-comments form-control" placeholder="Comments" id="trainers[1][comments]" name="trainers[1][comments]"></textarea>
</div>
</div>
<div id="trainer-2" class="trainer-group form-group row">
<div class="col-md-6">
<select class="form-control" id="trainers[2][trainer]" name="trainers[2][trainer]">
<option value="">-- Select --</option>
</select>
</div>
<div class="col-md-6">
<input type="text" class="trainer-expiration form-control" placeholder="Expiration" id="trainers[2][expiration]" name="trainers[2][expiration]" value="">
</div>
<div class="col-xs-12">
<textarea class="trainer-comments form-control" placeholder="Comments" id="trainers[2][comments]" name="trainers[2][comments]"></textarea>
</div>
</div>
<div id="trainer-3" class="trainer-group form-group row">
<div class="col-md-6">
<select class="form-control" id="trainers[3][trainer]" name="trainers[3][trainer]">
<option value="">-- Select --</option>
</select>
</div>
<div class="col-md-6">
<input type="text" class="trainer-expiration form-control" placeholder="Expiration" id="trainers[3][expiration]" name="trainers[3][expiration]" value="">
</div>
<div class="col-xs-12">
<textarea class="trainer-comments form-control" placeholder="Comments" id="trainers[3][comments]" name="trainers[3][comments]"></textarea>
</div>
</div>
</div>
Each trainer element inside of div instructor_trainers consists of three input fields, which are all contained inside of a trainers array. Whenever a new element is created, the index is found by incrementing the existing number of elements by one. When an element is removed, this value is decremented by one, and elements are only able to be removed in the order they were added (so if I were to click on my remove button trainer-3 would be removed, then trainer-2, and finally trainer-1).
Is there a way to update the array indexes automatically if an element is removed out of order. For example, if I changed my remove function to remove a specific id (such as trainer-2) is there a way to shift the index values of all elements after the removed element? So if trainer-2 is removed, then the three inputs in trainer-3 would have their index values shifted to 2?
This could be done by rebuilding each element after the deleted element, but it just feels like I'm missing something, like there's an easier way to go about it.
For the time being until I familiarize myself with vue.js or react.js frontend frameworks, I am calling the following function which re-indexes all of the elements:
function reindexTrainerElements(){
$(".trainer-group").each(function(index) {
var prefix = "trainers[" + index + "]";
$(this).find("select").each(function() {
this.id = this.id.replace(/trainers\[\d+\]/, prefix);
this.name = this.name.replace(/trainers\[\d+\]/, prefix);
});
$(this).find("input").each(function() {
this.id = this.id.replace(/trainers\[\d+\]/, prefix);
this.name = this.name.replace(/trainers\[\d+\]/, prefix);
});
$(this).find("textarea").each(function() {
this.id = this.id.replace(/trainers\[\d+\]/, prefix);
this.name = this.name.replace(/trainers\[\d+\]/, prefix);
});
});
}
This is a variation of Shawns answer in this question

How to get the ID of the Current element clicked

I want to get the Value of the Current Element to be clicked.
I have a list of Checkboxes and selection of each I want to get the ID of it which is hidden.
My Code goes as follows:
$("#ModelListView").on("click", ".ModelCheckBox", function (element) {
var AnalysisID = $("#AnalysisID").val();
var ModelID = '';
});
HTML:
<div id="ModelListView"></div>
<script type="text/x-kendo-template" id="Modeltemplate">
<div class="section group fr">
<div class="col span_2_of_12">
#if(ACTIVE_MODELS_COUNT > 0){# <input class="ModelCheckBox" type="checkbox" checked/>#} else {# <input class="ModelCheckBox" type="checkbox" unchecked/> #}#
</div>
<div class="col span_4_of_12"><label>#:MODEL#</label></div>
<input id="Model_ID" type="hidden" value=#:MODEL_ID#/>
</div>
</script>
I want to get the Value of Model_ID that is kept hidden.
You can use $(this) and get the closest.
$(this) will be the element that's clicked.
.closest('.section.group') will return the "section group"-div. You might want to use #ModelListView instead of .section.group.
.find('#Model_ID').val() will return the value of the hidden field.
$("#ModelListView").on("click", ".ModelCheckBox", function (element) {
var AnalysisID = $("#AnalysisID").val();
var ModelID = $(this).closest('.section.group').find('#Model_ID').val();
alert(ModelID);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="ModelListView">
<div class="section group fr">
<div class="col span_2_of_12">
<input class="ModelCheckBox" type="checkbox" checked/>
</div>
<div class="col span_4_of_12"><label>Label</label></div>
<input id="Model_ID" type="hidden" value="someValue"/>
</div>
</div>
Sidenote: be aware of using an ID in a template.

How to enable disable a select drop down list using radio buttons with angularjs?

I have been searching all over for the internet looking on how to enable or disable this drop down list using radio buttons specifically when the radio button value is equal to prof the drop down list should be disabled, but with no help. I did come up with an example but didn't work. Any help would be appreciated.
registration.html
<div class="form-group">
<label class="col-lg-2 col-md-3 control-label">Qualification</label>
<div class="col-lg-10 col-md-9">
<div class="radio-custom radio-inline">
<input type="radio" ng-model="QualificationDetails.qualification_type" value="edu" name="radio1" id="radio4">
<label for="radio4">Educational</label>
</div>
<div class="radio-custom radio-inline">
<input type="radio" ng-model="QualificationDetails.qualification_type" value="prof" name="radio1" id="radio5">
<label for="radio5">professional</label>
</div>
</div>
</div>
//This is the drop down that I need to diable
<div class="form-group">
<label class="col-sm-2 control-label" for="Qulitype">Qualification type</label>
<div class="col-sm-10">
<select name="repeatSelect" id="repeatSelect" ng-disabled="QualificationDetails.qualification_type == 'prof'" ng-model="QualificationDetails.qualification" class="form-control">
<option ng-repeat="quali in qualiLevel" value="{{quali.qualification_id}}">{{quali.quali_level}}</option>
</select>
</div>
</div>
This is the code I implemented to work above scenario. But didn't work :(
regController.js
$scope.$watch('QualificationDetails.qualicication_type', function (QualiType) {
if (angular.isUndefined($scope.QualificationDetails)) {
return;
}
if (QualiType === 'prof') {
$scope.QualificationDetails.qualification_type = $scope.QualiType;
}
else {
if ($scope.QualificationDetails.qualification_type !== null) {
$scope.QualiType = $scope.QualificationDetails.qualification_type;
$scope.QualificationDetails.qualification_type = null;
}
}
});
the above scenario is that when it comes to qualifications if qualification type is equal to professional (prof) drop down list is disabled and when it is educational the drop down list should be enabled. Any idea on how to achieve this.
This is the Quality level json. I get it through the qualitylevel.service.
(function initController() {
deptService.getdepts(function (res) {
$scope.depts = JSON.parse(res.data);
});
qualiService.getquali(function (res) {
console.log("inside ");
$scope.qualiLevel = JSON.parse(res.data);
});
console.log("inside service");
})();
It seems to me, that your code works fine without watcher you have added. I hope I understood what you want correctly. Try this snippet:
angular
.module('app', [])
.controller('Ctrl', function($scope) {
$scope.qualiLevel = [
{quali_level: 'A', qualification_id: 1},
{quali_level: 'B', qualification_id: 2}
];
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.7/angular.min.js"></script>
<div ng-app="app">
<div ng-controller="Ctrl">
<div class="form-group">
<label class="col-lg-2 col-md-3 control-label">Qualification</label>
<div class="col-lg-10 col-md-9">
<div class="radio-custom radio-inline">
<input type="radio" ng-model="QualificationDetails.qualification_type" value="edu" name="radio1" id="radio4">
<label for="radio4">Educational</label>
</div>
<div class="radio-custom radio-inline">
<input type="radio" ng-model="QualificationDetails.qualification_type" value="prof" name="radio1" id="radio5">
<label for="radio5">professional</label>
</div>
</div>
</div>
<div class="form-group">
<label class="col-sm-2 control-label" for="Qulitype">Qualification type</label>
<div class="col-sm-10">
<select name="repeatSelect" id="repeatSelect" ng-disabled="QualificationDetails.qualification_type == 'prof'" ng-model="QualificationDetails.qualification" class="form-control">
<option ng-repeat="quali in qualiLevel" value="{{quali.qualification_id}}">{{quali.quali_level}}</option>
</select>
</div>
</div>
</div>
</div>
As the control is radiobutton, your QualificationDetails.qualification_type value will be set to 1 or 0 and not to the label value. You have to have different variables for two radio buttons. Based on their value you have to set QualificationDetails.qualification_type = 'prof' or something
You can also try $parent.QualificationDetails.qualification_type instead as answered in How can I get the value of the checked radio button when submitting a form using angularjs?
Thanks everyone for helping me out. Just felt wanted to show I implemented it correctly and other programmers to increase their knowledge. Using $watch to temporaly hide the drop down list details).
the registrationController.js
$scope.$watch('QualificationDetails.qualification_type', function (Val) {
if (angular.isUndefined($scope.QualificationDetails))
return;
if (Val !== 'prof') {
$scope.QualificationDetails.qualification = $scope.tempValue;
}
else {
if ($scope.QualificationDetails.qualification !== null) {
$scope.tempValue = $scope.QualificationDetails.qualification;
$scope.QualificationDetails.qualification = null;
}
}
});
Implemented through this example.

How to clear old value from checkbox before next try?

I wrote my JavaScript code to get a value with JSON function to show in a checkbox, but every time I try with new options the old values still exist in the check box. I want to clear the checkbox before the next try. I marked the problem area in the code below:
HTML:
<div class="panel-body">
<div class="form-group">
<label for="field-1" class="col-sm-3 control-label" >Select Group</label>
<div class="col-md-2">
<select class="form-control" name="perms" onchange="OnSelectionChange(this)">
<option>Choice your group</option>
{foreach $perms as $perm}
<option value="{$perm.pID}">{$perm.title}</option>
{/foreach}
</select>
</div>
</div>
<div class="panel-body">
<div class="row">
<div class="col-md-12">
<strong>Edite Permisions:</strong>
<br />
<br />
</div>
<div class="col-sm-6" style="width:100%;">
<ul class="icheck-list">
{foreach $rps as $rp}
<li>
<input type="checkbox" name="updatePERM[]" id="{$rp.id}" value="{$rp.id}">
<label style="padding-left: 5px;vertical-align: middle;" >{$rp.rname}</label> <pre>{$rp.rdes}</pre>
</li>
{/foreach}
</ul>
</div>
</div>
</div>
</div>
JS:
function OnSelectionChange (select) {
var selectedOption = select.options[select.selectedIndex];
var url = "./include/getPerms.php?key="+selectedOption.value+"";
$.getJSON(url, function(data) {
$.each(data.rules, function(i, rule) {
// MY PROBLEM LINE: HOW I CAN DO THIS ?
if input:checkbox.val() != rule.id => set attr('checked', false)
else if input:checkbox.val() == rule.id => set attr('checked', true)
// HOW I CAN DO THIS ?
});
});
}
function OnSelectionChange(select) {
var selectedOption = select.options[select.selectedIndex];
var url = "./include/getPerms.php?key=" + selectedOption.value + "";
$.getJSON(url, function (data) {
// Default make all checkbox un-checked.
$("input:checkbox").prop("checked", false)
$.each(data.rules, function (i, rule) {
// If rule.id matches with the checkbox values then make those checkbox checked
$(":checkbox[value="+rule.id+"]").prop("checked",true);
});
});

option in form field hides option in next field

I am trying to get the "10.30am" option to dissapear in the Workshop Time field when "Monday 13th April" is selected in the Workshop date field. Failing that I would be happy if the option just disabled.
<div class="form-group">
<form action="ksmail.php" method="POST">
<div class="form-group">
<div class="row">
<p class="control-label blue">Workshop Date:</p>
<select name="date" class="finput" id="wdate">
<option value="11th_APR">Saturday 11th April</option>
<option value="13th_APR" id="dt">Monday 13th April</option>
<option value="18th_APR">Saturday 18th April</option>
</select>
</div>
</div>
<div class="form-group">
<div class="row">
<p class="control-label blue">Workshop Time:</p>
<select name="time" class="finput" id="wtime">
<option value="9am" id="tn">9am</option>
<option value="10_30am" id="tt">10.30am</option>
</select>
</div>
</div>
<div class="row">
<input type="submit" value="Send" class="btn btn-default">
</div>
</div>
</form>
</div>
javascript
$('#wtime') .show();
$('#wdate').bind('change', function (e) {
if( $('#wdate').val() == "#dt") {
$('#tt').hide();
}
css
#wtime{display: none;}
I have tried many variations of this none of which work. Sorry, I am a jquery newbie/moron. Any help would be greatly appreciated.
if you want to disable the option
$('#wdate').on('change', function (e) {
if( $(this).val() == "13th_APR") {
$("#wtime option[value='10_30am']").attr('disabled','disabled');
}
});
or if you want to remove the option
$('#wdate').on('change', function (e) {
if( $(this).val() == "13th_APR") {
$("#wdate option[value='10_30am']").remove();
}
});
Hope this helps
Your condition seem wrong. Try this one, hope this helped :
$('#wtime').show();
$('#wdate').on('change', function (e) {
if( $(this).val() == "13th_APR") {
$('#tt').hide();
}
else
{
$('#tt').show();
}
});

Categories