How can I consolidate pickadate initializer for multiple inputs on one page? - pickadate

I have a page that has multiple inputs for pickadate and pickatime. How can I consilidate the jquery to where I have one call for pickadate and one call for pickatime?
Here is the markup.
<div class="container">
<div class="row">
<div class="col-xs-3">
<div class="form-group">
<label><span class="required">*</span> Display Start Date</label>
<input type="text" class="form-control select-date display-start-date" required>
<i id="trigger1" class="calendar-icon"></i>
</div>
</div>
<div class="col-xs-3">
<div class="form-group">
<label><span class="required">*</span> Display Start Time</label>
<input type="text" class="form-control select-time display-start-time" required>
<i id="trigger2" class="fa fa-clock-o fa-2x"></i>
</div>
</div>
<div class="col=xs-6"></div>
</div>
<div class="row">
<div class="col-xs-3">
<div class="form-group">
<label><span class="required">*</span> Display End Date</label>
<input type="text" class="form-control select-date display-end-date" required>
<i id="trigger3" class="calendar-icon"></i>
</div>
</div>
<div class="col-xs-3">
<div class="form-group">
<label><span class="required">*</span> Display End Time</label>
<input type="text" class="form-control select-time display-end-time" required>
<i id="trigger4" class="fa fa-clock-o fa-2x"></i>
</div>
</div>
<div class="col-xs-6"></div>
</div>
<div class="row">
<div class="col-xs-3">
<div class="form-group">
<label><span class="required">NEW!</span> Start Date</label>
<input type="text" class="form-control select-date new-start-date">
<i id="trigger5" class="calendar-icon"></i>
</div>
</div>
<div class="col-xs-3">
<div class="form-group">
<label><span class="required">NEW!</span> Start Time</label>
<input type="text" class="form-control select-time new-start-time" required>
<i id="trigger6" class="fa fa-clock-o fa-2x"></i>
</div>
</div>
<div class="col-xs-6"></div>
</div>
<div class="row">
<div class="col-xs-3">
<div class="form-group">
<label><span class="required">NEW!</span> End Date</label>
<input type="text" class="form-control select-date new-end-date">
<i id="trigger7" class="calendar-icon"></i>
</div>
</div>
<div class="col-xs-3">
<div class="form-group">
<label><span class="required">NEW!</span> End Time</label>
<input type="text" class="form-control select-time new-end-time" required>
<i id="trigger8" class="fa fa-clock-o fa-2x"></i>
</div>
</div>
<div class="col-xs-6"></div>
</div>
</div>
And here is the jquery.
// Initialize datepicker.
// Add Video - Display Start Date
var $input1 = $('.display-start-date').pickadate({
format: 'mm/dd/yyyy',
editable: true
});
var picker1 = $input1.data('pickadate');
$('#trigger1').click( function( e ) {
e.stopPropagation();
e.preventDefault();
picker1.open();
});
// Add Video - Display Start Time
var $input2 = $('.display-start-time').pickatime({
interval: 15,
editable: true
});
var picker2 = $input2.data('pickatime');
$('#trigger2').click( function( e ) {
e.stopPropagation();
e.preventDefault();
picker2.open();
});
// Add Video - Display End Date
var $input3 = $('.display-end-date').pickadate({
format: 'mm/dd/yyyy',
editable: true
});
var picker3 = $input3.data('pickadate');
$('#trigger3').click( function( e ) {
e.stopPropagation();
e.preventDefault();
picker3.open();
});
// Add Video - Display End Time
var $input4 = $('.display-end-time').pickatime({
interval: 15,
editable: true
});
var picker4 = $input4.data('pickatime');
$('#trigger4').click( function( e ) {
e.stopPropagation();
e.preventDefault();
picker4.open();
});
// Add Video - New! Start Date
var $input5 = $('.new-start-date').pickadate({
format: 'mm/dd/yyyy',
editable: true
});
var picker5 = $input5.data('pickadate');
$('#trigger5').click( function( e ) {
e.stopPropagation();
e.preventDefault();
picker5.open();
});
// Add Video - NEW! Start Time
var $input6 = $('.new-start-time').pickatime({
interval: 15,
editable: true
});
var picker6 = $input6.data('pickatime');
$('#trigger6').click( function( e ) {
e.stopPropagation();
e.preventDefault();
picker6.open();
});
// Add Video - New! End Date
var $input7 = $('.new-end-date').pickadate({
format: 'mm/dd/yyyy',
editable: true
});
var picker7 = $input7.data('pickadate');
$('#trigger7').click( function( e ) {
e.stopPropagation();
e.preventDefault();
picker7.open();
});
// Add Video - NEW! End Time
var $input8 = $('.new-end-time').pickatime({
interval: 15,
editable: true
});
var picker8 = $input8.data('pickatime');
$('#trigger8').click( function( e ) {
e.stopPropagation();
e.preventDefault();
picker8.open();
});
Thanks in advance!

Here's something that is a little cleaner. It deals with the date pickers and the time pickers separately.
$('.select-date').pickadate({
format: 'mm/dd/yyyy',
editable: true
});
$('.calendar-icon').each( function() {
// find the date picker element in this form-group
$picker = $(this).closest('.form-group').find('.select-date');
$picker.on('click', function(ev) {
ev.stopPropagation();
ev.preventDefault();
picker = $picker.data('pickadate')
picker.open();
});
$('.select-time').pickatime({
interval: 15,
editable: true
});
$('.fa-clock-o').each( function() {
// find the date picker element in this form-group
$picker = $(this).closest('.form-group').find('.select-time');
$picker.on('click', function(ev) {
ev.stopPropagation();
ev.preventDefault();
picker = $picker.data('pickatime')
picker.open();
});
And if you gave all your icon triggers a class (like date-trigger and time-trigger, then you could change:
$('.calendar-icon').each( function() {
to
$('.date-trigger').each( function() {
and the same for the timepickers. This makes the selector less dependent on the particular icon you are using.
And this should set things up for the whole page.

Related

How do I add an option from a select class to a list when chosen by the user?

I am trying to allow a user to add an option from a select class after pressing submit. As of now, it is adding the whole list. How do I go about allowing the user to select the specific option that they have chosen?
<div class="col alert alert-dark">
<h1 class="text-center">To Do App</h1>
</div>
<form class="form text-center col-8 ml-auto mr-auto alert alert-primary" id="newTaskForm">
<label for="toDo" class="toDo">What Color Do You Want To Add?</label>
<div class="row">
<select class="form-control col-8 mr-2" id="colorToAdd">
<option>Red</option>
<option>Yellow</option>
<option>Orange</option>
<option>Green</option>
<option>Blue</option>
</select>
<button type="submit" class="btn btn-success col-2" id="taskSubmit">Submit</button>
</div>
</form>
<hr class="col-8 ml-auto mr-auto mb-3">
<section class="text-center col-8 ml-auto mr-auto alert alert-dark" id="toDoList">
<h2>Tasks</h2>
<div id="colors">
</div>
window.addEventListener("load", () => {
const form = document.querySelector("#newTaskForm");
const input = document.querySelector("#colorToAdd");
const list_el = document.querySelector("#colors");
form.addEventListener("submit", (e) => {
e.preventDefault();
const colorElement = document.createElement("div");
colorElement.classList.add("newColor");
colorElement.type = "text";
colorElement.innerHTML = input.innerHTML;
list_el.appendChild(colorElement);
});
});

Bootstrap 5 form validation - required & disabled

I currently have a disabled input box. I use the box to display the sum of two range sliders, where I update the value of the box via JavaScript.
I currently require that the value of the box equals 100 before allowing the form to be submitted. Is there a work-around where I can still disable the box, where it will still adopt the same Bootstrap style formatting (change color from red to green, etc) as a non-disabled box with the 'require' option?
Following a suggestion here, I've updated the code snippet below to almost be what I want. The only thing that I'd like to change, is to make 'rSum', the box that displays the sum, disabled (while still keeping all the validation formatting features). Ideally, I want this sum to adopt the validation feedback rather than the sliders, or other mutable input objects.
function checkSum() {
let currSum = parseInt(document.getElementById('rSum').value);
if (currSum != 100) {
document.getElementById('rSum').setCustomValidity('Must sum to 100%');
return false
} else {
document.getElementById('rSum').setCustomValidity('');
return true
}
}
function updateBoxes() {
const s1 = document.getElementById('range1');
const s2 = document.getElementById('range2');
let currSum = parseInt(s1.value) + parseInt(s2.value);
document.getElementById('rangeValue1').value = (s1.value)+"%";
document.getElementById('rangeValue2').value = (s2.value)+"%";
document.getElementById('rSum').value = (currSum)+"%";
}
// This last function is the original bootstrap validation example, modified to call 'checkSum()' instead
(function () {
'use strict'
// Fetch all the forms we want to apply custom Bootstrap validation styles to
var forms = document.querySelectorAll('.custom-validation')
// Loop over them and prevent submission
Array.prototype.slice.call(forms)
.forEach(function (form) {
form.addEventListener('submit', function (event) {
if (!checkSum()) {
event.preventDefault()
event.stopPropagation()
}
form.classList.add('was-validated')
}, false)
})
})()
<!-- CSS only -->
<link href="https://cdn.jsdelivr.net/npm/bootstrap#5.2.2/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-Zenh87qX5JnK2Jl0vWa8Ck2rdkQ2Bzep5IDxbcnCeuOxjzrPF/et3URy9Bv1WTRi" crossorigin="anonymous">
<!-- JavaScript Bundle with Popper -->
<script src="https://cdn.jsdelivr.net/npm/bootstrap#5.2.2/dist/js/bootstrap.bundle.min.js" integrity="sha384-OERcA2EqjJCMA+/3y+gxIOqMEjwtxJY7qPCqsdltbNJuaOe923+mo//f6V8Qbsw3" crossorigin="anonymous"></script>
<form class="custom-validation" novalidate>
<div class="mb-3 row">
<div class="form-group col-md-1">
<input class="form-control" type="text" id="rangeValue1" disabled>
</div>
<div class="form-group col-md-4 col-form-label">
<input type="range" class="form-range" min="0" max="100" step="5" id="range1" value="0" onchange="updateBoxes()" >
</div>
</div>
<div class="mb-3 row">
<div class="form-group col-md-1">
<input class="form-control" type="text" id="rangeValue2" disabled>
</div>
<div class="form-group col-md-4 col-form-label">
<input type="range" class="form-range" min="0" max="100" step="5" id="range2" value="0" onchange="updateBoxes()" >
</div>
</div>
<div class="mb-3 row">
<div class="form-group">
<input type="text" class="form-control text-center" id="rSum" placeholder="100%" required>
<div class="valid-feedback">
Looks good!
</div>
<div class="invalid-feedback">
Probabilities must add up to 100%
</div>
</div>
</div>
<div class="mb-3 row">
<div class="col-sm-6 offset-md-1">
<button type="submit" class="btn btn-primary">Submit</button>
</div>
</div>
</form>
A couple of ways to do this. Here I use an example form with some inputs that can be used in the slider validation (one is a range slider but could be a simple number input also).
I set an event handler for those elements, associate them using data attributes and then; very verbosely and a bit ugly for clarity, use them in a function.
function checkSum(event) {
const fearRequird = this.fearNeed;
const myFear = event.target;
const associated = document.querySelector(myFear.dataset.related);
const result = this.sumEl;
const thisValue = parseInt(myFear.value);
const associatedValue = parseInt(associated.value);
let currSum = thisValue + associatedValue;
result.value = currSum;
let isValidSlider = currSum >= fearRequird;
result.classList.toggle("is-valid", isValidSlider);
result.classList.toggle("is-invalid", !isValidSlider);
let t = isValidSlider ? '' : `You Fear ${thisValue} and ${associatedValue} total ${currSum}. You need total ${fearRequird} fear`;
result.setCustomValidity(t);
result.closest('.form-group').querySelector('.invalid-feedback').textContent = t;
return isValidSlider;
}
(function() {
'use strict'
// Fetch all the forms we want to apply custom Bootstrap validation styles to
let forms = document.querySelectorAll('.needs-validation');
// Loop over them and prevent submission
Array.prototype.slice.call(forms)
.forEach(function(form) {
form.addEventListener('submit', function(event) {
if (!form.checkValidity()) {
event.preventDefault();
event.stopPropagation();
}
form.classList.add('was-validated');
}, false)
});
const fearNeed = 100;
const myFears = document.querySelectorAll('.fear-factor');
const needs = {
fearNeed: fearNeed,
sumEl: document.querySelector('#rSum')
};
myFears.forEach((fearElement) => {
fearElement.addEventListener('change', checkSum.bind(needs), false);
});
})();
<!-- CSS only -->
<link href="https://cdn.jsdelivr.net/npm/bootstrap#5.2.2/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-Zenh87qX5JnK2Jl0vWa8Ck2rdkQ2Bzep5IDxbcnCeuOxjzrPF/et3URy9Bv1WTRi" crossorigin="anonymous">
<!-- JavaScript Bundle with Popper -->
<script src="https://cdn.jsdelivr.net/npm/bootstrap#5.2.2/dist/js/bootstrap.bundle.min.js" integrity="sha384-OERcA2EqjJCMA+/3y+gxIOqMEjwtxJY7qPCqsdltbNJuaOe923+mo//f6V8Qbsw3" crossorigin="anonymous"></script>
<form class="row g-3 needs-validation mx-1 my-2" novalidate>
<div class="form-group">
<input type="text" class="form-control text-center" id="rSum" placeholder="100%" required>
<div class="valid-feedback">
Looks good!
</div>
<div class="invalid-feedback">
Fears must add up to 100%
</div>
</div>
<div class="col-md-4">
<label for="validationCustomUsername" class="form-label">Fish Name</label>
<div class="input-group has-validation">
<span class="input-group-text" id="inputGroupPrepend">Fish</span>
<input type="text" class="form-control" id="validationCustomFishname" aria-describedby="inputGroupPrepend" required>
<div class="invalid-feedback">
Must catch a fish.
</div>
<div class="valid-feedback">
Looks like an good catch!
</div>
</div>
</div>
<div class="col-md-3">
<label for="validationCustomFearMet" class="form-label">Scary cats fear</label>
<div class="input-group has-validation">
<input type="number" class="form-control fear-factor" min="0" max="100" step="1" value="13" id="validationCustomFearMet" data-related="#customRange3" required />
<span class="input-group-text" id="inputGroupPrepend">%</span>
<div class="invalid-feedback">
Please provide scary cats fear as a percent 0-100.
</div>
<div class="invalid-feedback">
Please provide scary cats fear as a percent 0-100.
</div>
</div>
</div>
<div class="mx-1">
<label for="customRange3" class="form-label">Fear range</label>
<input type="range" class="form-range fear-factor" min="0" max="100" step="1" value="0" data-related="#validationCustomFearMet" id="customRange3">
</div>
<div class="col-12">
<button class="btn btn-primary" type="submit">Submit form</button>
</div>
</form>

want to turn the datepicker on and off in both input datepicker

friends, I want to turn the datepicker on and off in both input and icon clicks in this code structure, but I couldn't succeed, can you help?
<div class="container">
<div class="col-sm-6" style="height:130px;">
<div class="form-group">
<div class='input-group datetimepicker'>
<input type='text' class="form-control" />
<span class="input-group-addon">
<span class="glyphicon glyphicon-calendar">
</span>
</span>
</div>
</div>
</div>
<script type="text/javascript">
$(function () {
$('.datetimepicker').datetimepicker({
viewMode: 'years'
});
});
</script>
</div>

fire function ng-click automatically when ng-model is filled

I want to fire my function Automatically when i complete my typing in ng-model.
I applied 2 different technique but nothing work
1. Approch
<div class="col-sm-6">
<input type="text" class="form-control" ng-model="testing" placeholder="Name" maxlength="50" /></div>
<span ng-if="testing.length != null " ng-show="Add()"></span>
Approach
<div class="col-sm-6">
<input type="text" class="form-control" ng-model="testing" placeholder="Name" maxlength="50" /></div>
<span ng-show="testing && Add()"></span>
Both fire my function with single character. I want to fire Add() function when my typing is completed. I do not want to use button.
Try following 2 sample codes.
I hope following sample code could help you solve the problem you were facing
var app = angular.module('app', []);
app.controller('myCtrl', function($scope) {
$scope.testing = "";
$scope.Add = function() {
console.log("Hope this Helps!!")
}
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.5/angular.min.js"></script>
<div ng-app="app" ng-controller="myCtrl">
<div class="col-sm-6">
<input type="text" class="form-control" ng-model="testing" placeholder="Name" maxlength="50" />
</div>
<span ng-if="testing.length >=1 " ng-show="Add()"></span>
<div>
or you could do like this
var app = angular.module('app', []);
app.controller('myCtrl', function($scope) {
$scope.testing = ""; //model scope variable initialization
$scope.testFun=function(a){ //function to check whether length of variable is greater than 0
if (a>=1) return true;
else return false;
}
$scope.Add = function() { //function to be exucuted when ng-if gets true value
console.log("Hope this Helps!!")
}
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.5/angular.min.js"></script>
<div ng-app="app" ng-controller="myCtrl">
<div class="col-sm-6">
<input type="text" class="form-control" ng-model="testing" placeholder="Name" maxlength="50" />
</div>
<span ng-if="testFun(testing.length)" ng-show="Add()"></span>
<div>

Angular refresh page after disable DOM field form

I click Buy radio button, images upload field will be removed, but when i click submit, the page refresh. It works normally when I don't affect DOM
Please, explain me what happened ?
Here is my code
onSubmitPost() {
this.progress = true;
const fileList: FileList = this.event.target.files;
if (fileList.length > 0) {
const fileListLength = fileList.length;
const formData: FormData = new FormData();
formData.append('title', this.title);
formData.append('telephone', this.telephone);
formData.append('description', this.description);
formData.append('city', this.city);
if (this.isSell === true) {
for (let x = 0; x < fileListLength; x++) {
formData.append('thumbnail', fileList[x]);
}
}
const headers = new Headers();
headers.append('Accept', 'application/json');
headers.append('Authorization', 'clientId 7702919f7e72965');
this.http
.post('http://localhost:3000/api/post', formData, {
headers: headers
})
.map(res => res.json())
.subscribe(
data => {
this.Notificationervice.success('Success');
this.progress = false;
},
error => this.Notificationervice.error('Something wrong')
);
}
}
}
HTML Code
<div id="new-post" class="modal" materialize="modal">
<div class="modal-content">
<div class="row">
<form class="col s12" (submit)="onSubmitPost()" enctype="multipart/form-data">
<div class="row">
<div class="input-field col s12">
<i class="material-icons prefix">web</i>
<input id="icon_prefix" type="text" class="validate" name="title" [(ngModel)]="title">
<label for="icon_prefix">Title</label>
</div>
</div>
<div class="row">
<div class="input-field col s12">
<i class="material-icons prefix">phone</i>
<input id="icon_telephone" type="tel" class="validate" name="telephone" [(ngModel)]="telephone">
<label for="icon_telephone">Telephone</label>
</div>
</div>
<div class="row">
<div class="input-field col s12">
<i class="material-icons prefix">mode_edit</i>
<textarea id="icon_prefix2" class="materialize-textarea" [(ngModel)]="description" name="description"></textarea>
<label for="icon_prefix2">Description</label>
</div>
</div>
<div class="row">
<div class="input-field col s12">
<i class="material-icons prefix">location_on</i>
<input type="text" id="autocomplete-input" class="autocomplete" materialize="autocomplete" [materializeParams]="[{'data': {'houston': null, 'Cali': null}}]"
[(ngModel)]="city" name="city">
<label for="autocomplete-input">City</label>
</div>
</div>
<div class="row">
<div class="col s6">
<p>
<input name="isSell" type="radio" id="buy" (change)="isSell = !isSell" [checked]="!isSell" />
<label for="buy">Buy</label>
</p>
</div>
<div class="col s6">
<p>
<input name="isSell" type="radio" id="sell" (change)="isSell = !isSell" [checked]="isSell" />
<label for="sell">Sell</label>
</p>
</div>
</div>
<div class="file-field input-field" *ngIf="isSell">
<div class="btn">
<span>Images</span>
<input type="file" multiple accept='image/*' name="post" (change)="onChange($event)">
</div>
<div class="file-path-wrapper">
<input class="file-path validate" type="text" placeholder="Upload one or more files">
</div>
</div>
<div class="modal-footer">
<input type="submit" class="modal-action modal-close waves-effect waves-green btn-flat" value="Submit">
</div>
</form>
</div>
</div>
</div>