How can I combine 60 similar jquery functions into a single function? - javascript

I have a page which is essentially a giant checklist. If you hit the button to edit a checklist item, a modal pops up. On this modal, is a radio to select if problems were detected or not during the check. If yes is selected, a hidden div is displayed so that more information can be inserted before submitting.
Here is an example modal, currently, there are 60 on the page.
<!-- modal window for submiting check-->
<div id="edit3" class="text-left g-max-width-800 g-bg-white g-overflow-y-auto g-pa-20" style="display: none;">
<button type="button" class="close" onclick="Custombox.modal.close();"><i class="hs-icon hs-icon-close"></i></button>
<h4 class="g-mb-20">Update Record for Empirix->SIP:500 Baseline</h4>
<form action="actions.php" method="POST">
<!-- Checkbox -->
<div class="g-mb-15">
<label class="form-check-inline u-check g-pl-25 ml-0 g-mr-25">
<input class="g-hidden-xs-up g-pos-abs g-top-0 g-left-0" name="issue3" type="radio" value="0" checked="">
<div class="u-check-icon-radio-v4 g-absolute-centered--y g-left-0 g-width-18 g-height-18">
<i class="g-absolute-centered d-block g-width-10 g-height-10 g-bg-primary--checked"></i>
</div>
No Issues
</label>
<label class="form-check-inline u-check g-pl-25 ml-0 g-mr-25">
<input class="g-hidden-xs-up g-pos-abs g-top-0 g-left-0" name="issue3" type="radio" value="1">
<div class="u-check-icon-radio-v4 g-absolute-centered--y g-left-0 g-width-18 g-height-18">
<i class="g-absolute-centered d-block g-width-10 g-height-10 g-bg-primary--checked"></i>
</div>
Issue Found
</label>
</div>
<input type="hidden" name="action" value="subcheck">
<input type="hidden" name="id" value="3">
<div id="ifYes3" class="g-mb-15 desc3" style="display:none">
<div class="form-group g-mb-20">
<label class="g-mb-10" for="inputGroup1_1">INC Ticket</label>
<input id="inputGroup1_1" class="form-control form-control-md rounded-0" type="text" placeholder="INC Ticket #" name="inc_tick">
</div>
<div class="form-group g-mb-20">
<label class="g-mb-10" for="inputGroup2_1">Brief Description</label>
<textarea id="inputGroup2_1" class="form-control form-control-md g-resize-none rounded-0" rows="3" name="problem" placeholder="If you found an issue, please provide a short overview."></textarea>
</div>
</div>
<div align="right">
<button type="submit" class="btn u-btn-primary g-mr-20 g-mb-1">Submit</button>
</div>
</form>
</div>
<!-- End modal window -->
Then, I have this ajax code to perform the refresh, you'll notice I have a jq toggle for each of the 60 div's in here.
var interval = 10000; //number of mili seconds between each call
var refresh = function() {
$.ajax({
url: "ops_controller.php",
cache: false,
success: function(html) {
$("[name=issue1]").click(function(){
$('.desc1').toggle();
$("#ifYes1-"+$(this).val()).show('slow');
});
<!-- Cut out 58 similar functions -->
$("[name=issue59]").click(function(){
$('.desc59').toggle();
$("#ifYes59-"+$(this).val()).show('slow');
});
$("[name=issue60]").click(function(){
$('.desc60').toggle();
$("#ifYes60-"+$(this).val()).show('slow');
});
$('#table-refresh').html(html);
setTimeout(function() {
refresh();
}, interval);
}
});
};
refresh();
I then have the same code (60 jq functions) in another function
$( document ).ajaxStop(function() {
$.HSCore.components.HSModalWindow.init('[data-modal-target]');
$.HSCore.components.HSPopup.init('.js-fancybox', {
btnTpl: {
smallBtn: '<button data-fancybox-close class="btn g-pos-abs g-top-25 g-right-30 g-line-height-1 g-bg-transparent g-font-size-16 g-color-gray-light-v3 g-brd-none p-0" title=""><i class="hs-admin-close"></i></button>'
}
});
$('[data-toggle="tooltip-show"]').tooltip('show');
$("[name=issue1]").click(function(){
$('.desc1').toggle();
$("#ifYes1-"+$(this).val()).show('slow');
});
<!-- cut out 58 other items -->
$("[name=issue59]").click(function(){
$('.desc59').toggle();
$("#ifYes59-"+$(this).val()).show('slow');
});
$("[name=issue60]").click(function(){
$('.desc60').toggle();
$("#ifYes60-"+$(this).val()).show('slow');
});
});
});
The reason I've done it like this is so that this toggle will work on load and on ajax page refresh every 10 seconds. Im very new to jQuery/AJAX so forgive my ignorance. After two days, this is what I came up with to make it still work after the page refresh.
Surely, there has to be a cleaner method than what I'm doing here.

You can use a generic function in combination with event delegation¹ - see example below:
// [name^=issue] will target elements whose [name] attributes begins with "issue"
$(document).on("click", "[name^=issue]", function() {
var issueNo = this.name.replace("issue", "");
$(".desc" + issueNo).toggle();
$("#ifYes" + issueNo + "-" + $(this).val()).show("slow");
})
¹ https://learn.jquery.com/events/event-delegation/

You could set a data attribute in the HTML for each of the items you are wrapping - essentially you need a way to get the current ID for each then build up your jquery selector from that.
<div class="myrow" data-rowID="1">
<input class="g-hidden-xs-up g-pos-abs g-top-0 g-left-0" name="issue1" type="radio" value="1">
</div>
<div class="myrow" data-rowID="2">
<input class="g-hidden-xs-up g-pos-abs g-top-0 g-left-0" name="issue2" type="radio" value="1">
</div>
<div class="myrow" data-rowID="3">
<input class="g-hidden-xs-up g-pos-abs g-top-0 g-left-0" name="issue3" type="radio" value="1">
</div>
$(".myrow input[type=radio]").click(function(){
// ok what number is this row?
var myRowID = $(this).attr('data-rowID');
$('.desc'+ myRowID ).toggle();
$("#ifYes" + myRowID + "-"+$(this).val()).show('slow');
});
Something like that.

Related

insertAdjacentElement limitation

I have a form it has three boxes also I have a btn under it for the add page.
I wrote it as follows, but I do not want to add more than two boxes:
let matForm = document.querySelector('.mat-form');
document.querySelector('.btn-add-area').addEventListener('click', () => {
matForm.insertAdjacentElement("beforeend", `
<div class="mat-box">
<div class="mat-box-top">
<span>مواد</span>
<i class="fa fa-multiply"></i>
</div>
<div class="mat-box-body">
<input class="mat-equal sum3" type="text" name="sum_2" id="matvalue" placeholder="0">
<div class="rounded-green"><i class="fa fa-equals"></i></div>
<input class="mat-price price3" onchange="sumThree()" type="text" name="price_2"
id="matvalue" placeholder="مقدار تومان">
<div class="rounded-green"><i class="fa fa-plus"></i></div>
<input class="mat-kg kg3" type="text" name="kg_2" id="matvalue" placeholder="KGمقدار">
<div class="divide"><span>0%</span></div>
</div>
</div>
`);
})
How about creating a counter to store how many times it added, and using the counter in an if condition to avoid adding box if count is 2

Set checkbox label's text in modal

I have a modal for creating new post. I want to allow the user to select departments for sharing so I'm using checkboxes for choosing the audience.
HTML:
<div class="modal fade" id="createNewPostModal">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h4 class="modal-title">Create New Post</h4>
<button type="button" class="close" data-dismiss="modal">×</button>
</div>
<div class="modal-body">
<div class="container">
<form method="post" id="createNewPostForm">
<textarea rows="3" name="text" placeholder="Write something..."></textarea>
<div>
<p>Select audience to share</p>
<div>
<input type="checkbox" id="depACheckBox">
<label id="depACheckBoxLabel" for="depACheckBox"></label>
<input type="checkbox" id="depBCheckBox" >
<label id="depBCheckBoxLabel" for="depBCheckBox"></label>
<input type="checkbox" id="depCCheckBox">
<label id="depCCheckBoxLabel" for="CheckBox"></label>
</div>
</div>
<button type="submit" class="btn btn-success" onclick="return createNewPost(this.parentNode);" id="createNewPostButton" data-dismiss="modal">Share</button>
</form>
</div>
</div>
</div>
</div>
</div>
Different users have different departments to be shown and they are saved in mongoDB user document. I need to set the labels of the checkboxes on loading the modal.
I'm getting user's document on page load, so my attempt inside the getUser function:
$(document).ready(function() {
$("#createNewPostModal").on('load', function(){
document.getElementById('depACheckBoxLabel').innerText = window.user.depA.name;
document.getElementById('depBCheckBoxLabel').innerText = window.user.depB.name;
document.getElementById('depCCheckBoxLabel').innerText = window.user.depC.name;
});
});
I tried innerHTML as well but label still remains empty. How do I set the label text as or after the modal is shown?
If you call onload on anything other than window it will have no effect.
If you want to check for the #createNewPostModal div before running your function you can do something like the below example:
$(document).ready(checkModal);
function checkModal () {
if($('#createNewPostModal').is(':visible')){ //if the container is visible on the page
document.getElementById('depACheckBoxLabel').innerHTML = "this";
document.getElementById('depBCheckBoxLabel').innerHTML = "works";
document.getElementById('depCCheckBoxLabel').innerHTML = "now";
}
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="modal fade" id="createNewPostModal">
<p>Select audience to share</p>
<div>
<input type="checkbox" id="depACheckBox">
<label id="depACheckBoxLabel" for="depACheckBox"></label>
<input type="checkbox" id="depBCheckBox">
<label id="depBCheckBoxLabel" for="depBCheckBox"></label>
<input type="checkbox" id="depCCheckBox">
<label id="depCCheckBoxLabel" for="CheckBox"></label>
</div>
</div>
Feel free to adjust the check for :visible to something that suits your needs when referring to that container.
Additionally, as requested in your comment, if you want to call this function onclick you can do this:
$('button').click(checkModal);
function checkModal () {
if($('#createNewPostModal').is(':visible')){ //if the container is visible on the page
document.getElementById('depACheckBoxLabel').innerHTML = "this";
document.getElementById('depBCheckBoxLabel').innerHTML = "works";
document.getElementById('depCCheckBoxLabel').innerHTML = "now";
}
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="modal fade" id="createNewPostModal">
<p>Select audience to share</p>
<div>
<input type="checkbox" id="depACheckBox">
<label id="depACheckBoxLabel" for="depACheckBox"></label>
<input type="checkbox" id="depBCheckBox">
<label id="depBCheckBoxLabel" for="depBCheckBox"></label>
<input type="checkbox" id="depCCheckBox">
<label id="depCCheckBoxLabel" for="CheckBox"></label>
</div>
</div>
<button onclick="checkModal()">Click</button>
Just swap button for whatever element you want to trigger the function from.
Lastly, if it isn't necessary to wait for the #createNewPostModal div to load then just call your function like this and it should work:
$(document).ready(function() { document.getElementById('depACheckBoxLabel').innerHTML = window.user.depA.name; document.getElementById('depBCheckBoxLabel').innerHTML = window.user.depB.name; document.getElementById('depCCheckBoxLabel').innerHTML = window.user.depC.name; });

foreach loop, make the next input field required

I made a function, which should check whether my input field, with type checkbox has been checked or not... but whenever I check my input field the input fields I wish to make required do not get the required attributes.
I basically tried everything from this topic: jQuery add required to input fields
and read this topic in hopes of finding something: .prop() vs .attr()
but unfortunately none of the topics has helped me much further. So either I made a mistake somewhere in my code, or the required attribute is a bit buggy.
I call the function via my input field (onclick event).
I have already checked whether selectors were correct, and they are.
this is how my HTML looks like:
<div class="row" style="margin: auto;">
<div class="custom-control custom-checkbox col-md-4">
<input class="custom-control-input" onclick="is_required()" type="checkbox" id="fruittariër" value="fruittariër" name="vegetarisch[]">
<label class="custom-control-label" for="fruittariër"> fruittariër</label>
</div>
<div class="col-md-4 input-group leftVeganPadding">
<div class="input-group-prepend">
<span class="input-group-text" id="basic-addon1">€</span>
</div>
<input type="number" step="0.01" class="form-control" placeholder="Kosten" name="vegCosts[]">
</div>
<div class="input-group col-md-4 leftVeganPadding">
<div class="input-group-prepend">
<span class="input-group-text" id="veganDatePicker"><i class="fas fa-calendar-alt"></i></span>
</div>
<input type="text" class="form-control" name="veganEindDatum[]" id="shutDateFruittariër" placeholder="Sluit Datum" aria-label="veganDatePicker" aria-describedby="veganDatePicker">
</div>
</div>
this is how I call my function:
<input class="custom-control-input" onclick="is_required()" type="checkbox" value="vegan" name="vegetarisch[]">
function is_required() {
//check whether the checkbox has been checked or not
//if yes, make the other input fields inside the row required
// variable odin = the row wrapped around the cols
$('input[name="vegetarisch[]"]').each(function(index, thisElement) {
if($(thisElement).is(':checked')) {
let odin = $(thisElement).closest('.row');
odin.find('input[name="vegCosts[]"]').attr('required', true);
odin.find('input[name="veganEindDatum[]"]').attr('required', true);
} else {
odin = $(thisElement).closest('.row');
odin.find('input[name="vegCosts[]"]').attr('required', false);
odin.find('input[name="veganEindDatum[]"]').attr('required', false);
}
});
}
So what I wish to achieve: When the checkbox is checked I want to have the 2 other input fields inside the row to gain the attribute 'required'.
No need for an each you can pretty much do this in one line with an event handler.
Below, the closest .row is found for the button that was clicked. Then one selector is used to find both inputs that will be required. Then the required prop is set based on the status of the check button.
$(document).ready(function() {
//Handle events on the checkbox
$('input[name="vegetarisch[]"]').on('click', function() {
//get the nearst row
$(this).closest('.row')
//Find the check boxes
.find('input[name="vegCosts[]"],input[name="veganEindDatum[]"]')
//set the required propery if the checkbox is checked
.prop('required', $(this).is(":checked"));
});
});
:required {
border-color: red;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script>
<div class="row" style="margin: auto;">
<div class="custom-control custom-checkbox col-md-4">
<input class="custom-control-input" type="checkbox" id="fruittariër" value="fruittariër" name="vegetarisch[]">
<label class="custom-control-label" for="fruittariër"> fruittariër</label>
</div>
<div class="col-md-4 input-group leftVeganPadding">
<div class="input-group-prepend">
<span class="input-group-text" id="basic-addon1">€</span>
</div>
<input type="number" step="0.01" class="form-control" placeholder="Kosten" name="vegCosts[]">
</div>
<div class="input-group col-md-4 leftVeganPadding">
<div class="input-group-prepend">
<span class="input-group-text" id="veganDatePicker"><i class="fas fa-calendar-alt"></i></span>
</div>
<input type="text" class="form-control" name="veganEindDatum[]" id="shutDateFruittariër" placeholder="Sluit Datum" aria-label="veganDatePicker" aria-describedby="veganDatePicker">
</div>
</div>
You may want to try using the onchange event:
<input class="custom-control-input" id="myCheckbox" type="checkbox" value="vegan" name="vegetarisch[]">
$('#myCheckbox').change(function () {
is_required();
});
function is_required() {
let odin = $(thisElement).closest('.row');
$('input[name="vegetarisch[]"]').each(function (index, thisElement) {
if ($(thisElement).is(':checked')) {
odin.find('input[name="vegCosts[]"]').attr('required', true);
odin.find('input[name="veganEindDatum[]"]').attr('required', true);
} else {
odin.find('input[name="vegCosts[]"]').attr('required', false);
odin.find('input[name="veganEindDatum[]"]').attr('required', false);
}
});
}

cloning elements with eventlistener

im trying to clone elements when I click the button. So far, I don't know, what the problem is about my code. I think it looks kinda right, could you please look over, and tell/describe me the problem? I mean, I read a lot of documentation about clonenode, and I just do the same. And when I look over my code, it does make sense to me, but it doest want to work... D:
The button should clone the whole field(inputCar)
Here is my fiddle https://jsfiddle.net/7k1sb7w0/
This is the html code:
<button id="buttonBtn">Clone Field</button>
<div id="inputCar">
<div class="column">
<label class="heading">Invite Persons</label>
</div>
<div class="medium-6 column">
<label for="ext-name">Name</label>
<input id="ext-name" type="text">
<input type="checkbox">
<label for="check7"></label>
<label>BMW</label>
<input type="checkbox" checked="true">
<label for="check8"></label>
<label>Ford</label>
</div>
<div class="medium-6 column">
<label for="ext-mail">E-Mail</label>
<input id="e-mail" type="email">
<datalist id="members"></datalist>
<button class="deletePerson">delete</button>
<label class="delete_btn">delete Field</label>
</div>
<br>
</div>
and this is my jsfile:
var clickBtn = document.querySelector('#buttonBtn');
var field = document.querySelector('#inputCar');
var i = 0;
clickBtn.addEventlistener('click', function(e) {
var cloneField = field.cloneNode(true);
cloneField.id = "inputCar" + i++;
field.parentNode.appentChild(cloneField);
}
Thank you in advance,
mark

Javascript: .reset is causing page to refresh

HTML
<form class="controls" id="Filters">
<fieldset>
<div id="sample-showcase" class="noUi-target noUi-ltr noUi-horizontal noUi-background"></div>
<div id="rangespan-container">
<span id="min-value-span" class="range-spans"></span>
<input type="hidden" class="min-value-span">
<span class="range-spans">g</span>
<span id="max" class="range-spans"> - </span>
<span id="max-value-span" class="range-spans"></span>
<input type="hidden" class="min-value-span">
<span class="range-spans">g</span>
</div>
<div class="range-button checkbox">
<input type="checkbox" class="rangecheck"/></div>
</fieldset>
<fieldset>
<h3 class="sidetitle">Filter</h3>
<div class="breakfast-filter checkbox">
<input type="checkbox" class="checkbox1" value=".category-breakfast"/>
<label>Breakfast</label></div>
<div class="lunch-filter checkbox">
<input type="checkbox" class="checkbox2" value=".category-lunch"/>
<label>Lunch</label></div>
<div class="dinner-filter checkbox">
<input type="checkbox" class="checkbox3" value=".category-dinner"/>
<label>Dinner</label></div>
<div class="snacks-filter checkbox">
<input type="checkbox" class="checkbox4" value=".category-snacks"/>
<label>Snacks</label></div>
</fieldset>
<fieldset>
<h3 class="sidetitle">Sort</h3>
<div class="sort" data-sort="protein:asc">Low to High</div>
<div class="sort" data-sort="protein:desc">High to Low</div>
<div class="sort" data-sort="random">Random</div>
</fieldset>
<button id="Reset">Clear Filters</button>
</form>
Snippet of JS
bindHandlers: function(){
var self = this;
self.$filters.on('change', function(){
self.parseFilters();
});
self.$reset.on('click', function(){
self.$filters[0].reset();
self.parseFilters();
});
}
self.$reset = jQuery('#Reset'); it is defined higher in the code. Not sure if this is enough info.
Here is the link to the full code: Click Here
If you go to the home page click on some filters then try resetting. You should see it work like it's suppose to then take you to domain.com/?
Not sure why
Help please
button elements are submit buttons by default. You have to set type="button" if you to make them "dummy" buttons, i.e. they don't have a any default behavior:
type="button": The button has no default behavior. It can have client-side scripts associated with the element's events, which are triggered when the events occur.
<button type="button" id="Reset">Clear Filters</button>
Of course you could also set it to type="reset" and let the browser take care of resetting the form elements for you:
type="reset": The button resets all the controls to their initial values.
Then you could simplify your event handler to:
self.$reset.on('click', function(){
self.parseFilters();
});
It's not a huge change, but if the browser already offers this feature, why not make use of it?
Because you are using a button within the form and it is not prevented its default behavior.
Hence after resetting the form, the form is getting submitted.
You either have to return false after the function or preventDefault(). Try this.
self.$reset.on('click', function(e){
e.preventDefault();
self.$filters[0].reset();
self.parseFilters();
});
Or you need to set the type="button" for the button tag to make sure they are of type button and not submit.
<button id="Reset" type="button">Clear Filters</button>

Categories

Resources