so I'm having a problem with my .js, basically it doesn't work and i have no idea why.
else {
var dateOfBirth = new Date(formObject.dateOfBirth);
var timestamp = new Date(formObject.timestamp);
var timestampMonth = timestamp.getMonth();
var dateOfBirthMonth = dateOfBirth.getMonth();
var timestampYear = timestamp.getFullYear();
var dateOfBirthYear = dateOfBirth.getFullYear();
if (((timestampYear - dateOfBirthYear) === 1) && (timestampMonth === (dateOfBirthMonth -1))) {
Swal.fire({
title: 'Błąd!',
text: 'LAZY PO',
icon: 'error',
confirmButtonText: 'Close'
});
} else {
google.script.run.processForm(formObject);
Swal.fire({
title: 'Udało się!',
text: 'Dane zostały przekazane do działu DELIVERY SUPPORT.',
icon: 'success',
confirmButtonText: 'Close'
});
document.getElementById("myForm").reset();
}
}
Script should check if date input by user in my form is later than 1 month from now.
If it is - an error should appear:
Swal.fire({
title: 'Błąd!',
text: 'LAZY PO',
icon: 'error',
confirmButtonText: 'Close'
});
But it seems like the script is ignoring the date and accepts basically anything...
You can isolate a function to calculate difference between dates.
In my opinion, the easiest way is to calculate the time in millisecond you want and check if the difference between those two dates match.
Here is an example of implementation.
const ONE_MONTH_IN_MILLISEC = 1000*60*60*24*31
function checkDateOneMonth(date1, date2) {
return ONE_MONTH_IN_MILLISEC > Math.abs(new Date(date1) - new Date(date2))
}
console.log(checkDateOneMonth('2023-01-01','2022-12-15')) // true
console.log(checkDateOneMonth('2023-01-01','2023-02-10')) // false
Note : Here the difference is based on 31-days months.
Related
I'm trying to add a bootstrap card inside a div called [itemscontainer] using javascript
by document.getElementById("itemscontainer").innerHTML so i want the cards to be inserted inside the itemscontainer only one time like this :-
but the problem is the items cards keeps reapet them salves more than one time like:-
what i want is to clear the itemscontainer first before adding the cards and this is what i have tried so that the items will be only one cards for each item
// clear function
function clear(){
document.getElementById("ssst").innerHTML = ""
}
// listener append all items to the inventory
window.addEventListener('message', (event) => {
let data = event.data
if(data.action == 'insertItem') {
let name = data.items.name
let count = data.items.count
let icon = data.items.icon
if(document.getElementById("ssst").innerHTML == ""){
clear()
}else{
document.getElementById("ssst").innerHTML +=
"<div class='card holder'>"+
'<div class="card-body">'+
'<img src="icons\\'+icon+'" style="position:absolute;left:15%;width:40px; height:36px;" alt="">'+
'<h4 id="counter">'+count+'</h4>'+
'</div>'+
'<span class="itemname">'+name+'</span>'+
'</div>";'
}
}
})
The real solution is to figure out why you are getting the items more than once. With the information you provided that is impossible for me to answer. So the only thing we can recommend is how to prevent items from being added more than once.
If your messaging system returns duplicates you can determine if you have seen it. If you do, replace it. Otherwise add it.
window.addEventListener('message', (event) => {
const data = event.data;
console.log(data)
if (data.action == 'insertItem') {
let name = data.items.name
let count = data.items.count
let icon = data.items.icon
const html = `
<div class='card holder' data-name="${name}">
<div class="card-body">
<img src="icons/${icon}" style="position:absolute;left:15%;width:40px; height:36px;" alt="${icon}">
<h4 id="counter">${count}</h4>
</div>
<span class="itemname">${name}</span>
</div>`;
const elemExists = document.querySelector(`[data-name="${name}"]`);
if (elemExists) {
const parser = new DOMParser();
const doc = parser.parseFromString(html, 'text/html');
elemExists.replaceWith(doc.body);
} else {
document.getElementById("ssst").insertAdjacentHTML("beforeend", html);
}
}
});
window.postMessage({
action: 'insertItem',
items: {
name: 'foo',
count: 1,
icon: 'foo'
}
});
window.postMessage({
action: 'insertItem',
items: {
name: 'bar',
count: 40,
icon: 'barrrrrr'
}
});
window.postMessage({
action: 'insertItem',
items: {
name: 'foo',
count: 1000,
icon: 'foo'
}
});
<div id="ssst"></div>
Why are you using the if statement, what are you checking for?
remove the if statement, I can't see the reason for it to be used here.
clear()
and the rest of your code.
I have a datepicker input and a timepicker input that I'd like to use to schedule a person for appointments.
When the user clicks on the input to open the datepicker menu, I'd like to grey out specific datetimes. I've got a php function that returns this array of datetimes in in 'Y-m-d H:i:s' string format. But I dont' know how to use that function's return value to give the javascript function what it needs to disable a range of dates in datepicker.
In the onSelect event of my datepicker, I want it to enable/disable time options in my timepicker according to which timeslots are booked for that day. But I don't know how.
Datepicker uses beforeshowDay: to disable booked dates
user selects date from datepicker
Datepicker enables/disables times in the timepicker
I did find out how to disable timeranges in the timepicker Here. the code example is this:
$('input.timepicker').timepicker({
'disableTimeRanges': [
['1am', '2am'],
['3am', '4:01am']
]
});
But that's how I'd disable the time ranges from within the scope of the timepicker. I don't know how to disable them from BeforeShowDay in datepicker?
<script type="text/javascript">
$(document).ready(function(){
$( "#datepickerListAppointments" ).datepicker(
{
minDate:'0',
beforeShowDay:
function(dt)
{ // need to disable days other than tuesday and wednesday too.
return [dt.getDay() === 2 || dt.getDay() === 3, ""];
},
onSelect : function(){
should disable/enable timepicker times from here?
}
});
$('input.timepicker').timepicker({
timeFormat: 'h:mm p',
interval: 90,
minTime: '9',
maxTime: '10:30am',
defaultTime: '9',
startTime: '9:00',
dynamic: false,
dropdown: true,
scrollbar: false
});
});
This is the function that gives the datetimes, in case it helps to know.
function get_next_open_appointments($numAppointments, $timeSlotToExclude = "")
{
global $db;
$whereCondition = "WHERE FirstName = :null ";
if ($timeSlotToExclude != "")
{
$whereCondition .= "AND AppointmentTime != '$timeSlotToExclude' ";
}
$query = "SELECT DISTINCT AppointmentTime FROM appointments
$whereCondition
ORDER BY AppointmentTime ASC LIMIT $numAppointments";
$statement = $db->prepare($query);
$statement->bindValue(':null', "");
$statement->execute();
$datesArray = array();
while ($row = $statement->fetch())
{
array_push($datesArray, $row['AppointmentTime']);
}
$statement->closeCursor();
return $datesArray;
}
UPDATE:
Hugo De Carmo pointed me in the right direction and I got the dates to disable/enable appropriately. However, I don't know how to use the datetimes that I pulled in code below to disable/enable times in the timepicker.
Here is the new code:
<script type="text/javascript">
$(document).ready(function(){
// uses php to get open appointments, and put them in a javascript array
<?php $datetime_openings = get_next_open_appointments(200);
$date_openings = array();
foreach ($datetime_openings as $dt)
{
array_push($date_openings, substr($dt,0,10)); // just the date part
}
$json_date_openings = json_encode($date_openings);
echo "var arr_Openings = ". $json_date_openings . ";\n";
?>
$( "#datepickerOpenAppointments" ).datepicker(
{
minDate:'0',
beforeShowDay:
function(dt)
{
var string = jQuery.datepicker.formatDate('yy-mm-dd', dt);
var bFound = (arr_Openings.indexOf(string) != -1);
return [ bFound ];
},
onSelect : function(){
// Should disable/enable time ranges here?
});
$('input.timepicker').timepicker({
timeFormat: 'h:mm p',
interval: 90,
minTime: '9',
maxTime: '10:30am',
defaultTime: '9',
startTime: '9:00',
dynamic: false,
dropdown: true,
scrollbar: false
});
});
Try this,
sorry i didn't use beforeshowDay
select date 2017-7-14 and 2017-7-17 and see
var disabledDateTime = {
'2017-7-14':[
['2:30am','3:00am'],
['6:30am','9:00am']
],
'2017-7-17':[
['1:00am','3:00am'],
['5:30am','7:00am'],
['11:30am','2:00pm']
]
};
$(function() {
$('#pickTime').timepicker();
$('#pickDate').datepicker({
'format': 'yyyy-m-d',
'autoclose': true
}).on('changeDate',function(e){
var ts = new Date(e.date);
var m = ts.getMonth()+1;
var dt = ts.getFullYear() + '-' + m + '-' + ts.getDate();
var opt = {'disableTimeRanges': []}
if(typeof(disabledDateTime[dt])!='undefined'){
$('#pickTime').timepicker('setTime', '');
opt = {'disableTimeRanges': disabledDateTime[dt]}
}
$('#pickTime').timepicker('option',opt);
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<link href="https://jonthornton.github.io/jquery-timepicker/lib/bootstrap-datepicker.css" rel="stylesheet"/>
<script src="https://jonthornton.github.io/jquery-timepicker/lib/bootstrap-datepicker.js"></script>
<link href="https://jonthornton.github.io/jquery-timepicker/jquery.timepicker.css" rel="stylesheet"/>
<script src="https://jonthornton.github.io/jquery-timepicker/jquery.timepicker.js"></script>
<input id="pickDate" type="text" class="date" />
<input id="pickTime" type="text" class="time" />
Someone already answered this question here.
Anyway, the following code should give you an insight on how to solve the problem.
// supose your script return a json similar to the following
{
"data": [
// ...
"17-07-11"
]
}
$(function() {
$.getJSON("/path/to/script", function(response){
$('#datepickerListAppointments').datepicker({
beforeShowDay: function(dt) {
var config = [];
config[1] = 'class';
if ((dt.getDay() === 2) || (dt.getDay() === 3)) {
config[0] = false;
return config;
}
var string = jQuery.datepicker.formatDate('yy-mm-dd', dt);
config[0] = (response.data.indexOf(string) === -1);
return config;
}
});
});
});
I've assumed that you're exchanging data with the server using some kind of API, hence the use of getJSON, if you want to handle server errors then I suggest you to use ajax combining with Promise.
Edit 1
You can extract everything from your date using the class DateTime, here is a snippet:
$openings = array();
$date = DateTime::createFromFormat("y/m/d H:i", "17/07/15 08:30");
if (!isset($openings[$date->format("y-m-d")])) {
$openings[$date->format("y-m-d")] = array();
}
$openings[$date->format("y-m-d")][] = array(
"hour" => $date->format("Ha"),
"minute" => $date->format("i")
);
/* result
array(1) {
["17-07-15"]=>
array(1) {
[0]=>
array(2) {
["hour"]=>
string(4) "08am"
["minute"]=>
string(2) "30"
}
}
}
*/
Then you can disable the time in timepicker based on date, you'll probably need to register a callback function in your datepicker to update the timepicker based on the chosen date or you'll have to override the timepicker with new settings.
Yes, you can dinamically update timepicker disableTimeRanges inside the onSelect function using the option method of the timepicker component.
I'm supposing that:
You are using jQuery UI datepicker (since you didn't tag your question with twitter-bootstrap and bootstrap-datepicker has no minDate option)
You are using the first version of get_next_open_appointments that returns an array of datetimes (like ['2017-07-25 09:30:00', ...] see fakeDisabledTimes in the snippet)
I'm using momentjs in order to simplify dates managment. In the following code, I've used moment parsing functions (moment(String) and moment(String, String)), isSame, add and format. Note that moment tokens are different from PHP tokens.
Here a complete working sample:
var fakeDisabledTimes = [
'2017-07-25 09:30:00', '2017-07-26 10:00:00',
'2017-08-01 09:00:00', '2017-08-02 09:30:00',
'2017-08-08 10:30:00', '2017-08-09 10:00:00',
'2017-07-15 09:30:00', '2017-07-16 10:00:00'
];
$(document).ready(function(){
$( "#datepickerListAppointments" ).datepicker({
minDate:'0',
beforeShowDay:
function(dt){
// need to disable days other than tuesday and wednesday too.
return [dt.getDay() === 2 || dt.getDay() === 3, ""];
},
onSelect : function(dateText){
//should disable/enable timepicker times from here!
// parse selected date into moment object
var selDate = moment(dateText, 'MM/DD/YYYY');
// init array of disabled times
var disabledTimes = [];
// for each appoinment returned by the server
for(var i=0; i<fakeDisabledTimes.length; i++){
// parse appoinment datetime into moment object
var m = moment(fakeDisabledTimes[i]);
// check if appointment is in the selected day
if( selDate.isSame(m, 'day') ){
// create a 30 minutes range of disabled time
var entry = [
m.format('h:mm a'),
m.clone().add(30, 'm').format('h:mm a')
];
// add the range to disabled times array
disabledTimes.push(entry);
}
}
// dinamically update disableTimeRanges option
$('input.timepicker').timepicker('option', 'disableTimeRanges', disabledTimes);
}
});
$('input.timepicker').timepicker({
timeFormat: 'h:i a',
interval: 90,
minTime: '9',
maxTime: '10:30am',
defaultTime: '9',
startTime: '9:00',
dynamic: false,
dropdown: true,
scrollbar: false
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.18.1/moment.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jqueryui/1.11.4/jquery-ui.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery-timepicker/1.10.0/jquery.timepicker.js"></script>
<link href="https://cdnjs.cloudflare.com/ajax/libs/jqueryui/1.11.4/jquery-ui.css" rel="stylesheet"/>
<link href="https://cdnjs.cloudflare.com/ajax/libs/jquery-timepicker/1.10.0/jquery.timepicker.css" rel="stylesheet"/>
<input id="datepickerListAppointments" type="text">
<input class="timepicker" type="text">
I understand that 2000 options in a select box is going to bring along some performance issues, but it works fine on Chrome and Firefox and Safari.
Basically, I am calling a web service which populates a select box. This is fairly quick and performance is fine on initial load. The issue is when I change routes, and then come back to the page with the select box on it. It takes ~40 seconds to load the view on IE. Is there anyway way to improve performance?
This is how it is set up:
<select name="" id="" ng-model="model.searchParams.shipto" ng-options="ship.cd as ship.cd + (ship.cd===''?'' : ' - ') + ship.ds for ship in shiptoSelect" class="dropdownbar"></select>
This is the call that is made to retrieve the results. This is only executed once, and then the results are stored in my globalParams. So when I return to this view, this is not executed and the results are loaded from my globalParams service. That is when I run into performance issues.
$scope.getShipTo = function() {
$scope.model.searchParams.shipto = '';
$scope.model.showProgress = true;
MagicAPI.getShipToResults($scope.model.searchParams.brand, $scope.model.searchParams.soldto).then(function(response) {
if (response.status === 200) {
var resSHIPAR = eval(response.data);
var resSHIPStr = resSHIPAR;
if (resSHIPStr.length * 1 === 0) {
globalParams.getAlertList().push({
type: 'info',
msg: 'No ship-to\'s exist for this account.'
});
$scope.model.showProgress = false;
return;
} else {
var selectObj = {
cd: '',
ds: '-- select --'
};
resSHIPStr.splice(0, 0, selectObj);
globalParams.setShipToList(resSHIPStr);
$scope.shiptoSelect = resSHIPStr;
$scope.model.showProgress = false;
for (var i = 0; i < resSHIPStr.length; i++) {
if(resSHIPStr[i].cd === $scope.model.searchParams.soldto) {
$scope.isSoldToMatch = true;
return;
} else {
$scope.isSoldToMatch = false;
}
}
if ($scope.isSoldToMatch === false) {
globalParams.getAlertList().push({
type: 'info',
msg: 'No ship-to\'s exist for this account.'
});
}
}
}
}, function(response) {
$log.debug(response);
});
};
You should really read about track by and implement it
https://docs.angularjs.org/api/ng/directive/ngOptions
then your select becomes
<select name="" id=""
ng-model="model.searchParams.shipto"
ng-options="ship.cd as ship.cd + (ship.cd===''?'' : ' - ') + ship.ds for ship in shiptoSelect track by ship.id" class="dropdownbar"></select>
I want to calculate end date depending on the dropdown list and start date. I use Koala Framework 3.8 (ExtJS 2.3 and Zend 1.12).
If I choose '3' from dropdown and start date is 07.07.2015:
Then end date value becomes 07.08.2015 (+1 month, depending on DB field of '3' value):
I need something that listens to the change event on the combobox/datefield and sets the date dynamically (depending on DB month of combobox with ajax request or another way).
In steps:
I set combobox value in form and set start date
If 1st step complete values not null select month value from DB (SELECT month from approaches where approachesCount=3 AND ...)
Add selected month value from step 2 to start date
Put 3rd step date to datefield. I can change this date if needed.
How to do this?
You can add listeners on combobox and Start Date datefield that listens on change( this, newValue, oldValue, eOpts ) event.
Then check if combobox and Start Date datefield has been chosen. If its true make ajax.request to your server and get value to your End Datedatefield
This is an just example that illustrate one of many solutions(rather pseudo code):
View
Ext.define('YourPanel', {
extend: 'Ext.panel.Panel',
alias: 'widget.yourPanel',
xtype: 'yourPanel',
items:[{
xtype: 'combobox',
itemId: 'approachCountId'
},{
xtype: 'datefield',
itemId: 'dateStartId'
},{
xtype: 'datefield',
itemId: 'dateEndId'
}]
});
Controller
Ext.define('YourController', {
extend: 'Ext.app.Controller',
init: function () {
var controller = this;
controller.control({
'yourPanel combobox#approachCountId': {
change: controller.changeEndDateValue
},'yourPanel combobox#dateStartId': {
change: controller.changeEndDateValue
}
})
},
changeEndDateValue: function(field, newValue, oldValue, eOpts){
var controller = this;
//YourCode here to check if combobox value and end date value are not empty.
if(!Ext.isEmpty(startDateField) && !Ext.isEmpty(approachCount)){
//Ajax call
Ext.Ajax.request({
method: 'POST',
url: 'yourUrlToCheck',
params: {
approachCount: approachValue,
startDate: startDateValue
},
scope: this,
success: function (result, response) {
//if success set value to End Date datefield
},
failure: function (result, response) {
}
});
}
}
});
Finally I did it in this way, maybe it can be done better:
var Employees = Ext2.extend(Ext2.Panel,
{
initComponent : function(test)
{
....
....
//save context
var controller = this;
var documents = new Kwf.Auto.GridPanel({
controllerUrl : '/employees/documents',
collapsible : true,
stripeRows : true,
title : 'Recurrent training',
gridConfig: {
selModel: new Ext2.grid.CheckboxSelectionModel()
},
listeners: {
loaded: function() {
//get gripdpanel autoform
var autoForm = this.getEditDialog().getAutoForm();
//add form render event actions
autoForm.on('renderform', function(form) {
//get fields
var typeId = form.findField('typeId');
var startDate = form.findField('startDate');
//add select event to ComboBox
typeId.on('select', function(typeId, record, index) {
//get start date
var startDateValue = startDate.getValue();
//function call with autoform context
controller.changeDateType.call(autoForm, startDateValue, record.data.id);
});
//add select event to DateField
startDate.on('select', function(startDate, date) {
//get id type
var typeName = typeId.getValue();
//function call with autoform context
controller.changeDateType.call(autoForm, date, typeName);
});
//add keyup event to DateField
startDate.on('keyup', function(startDate, e) {
//if valid
if(startDate.isValid()) {
//get start date
var startDateValue = startDate.getValue();
//get id type
var typeName = typeId.getValue();
//function call with autoform context
controller.changeDateType.call(autoForm, startDateValue, typeName);
}
});
});
}
}
});
....
....
},
changeDateType: function(date, type){
//get end date
var endDate = this.findField('endDate');
//if both values not empty
if(!Ext2.isEmpty(date) && !Ext2.isEmpty(type)){
//do ajax with:
//url - catalog url
//params - id type
Ext2.Ajax.request({
url: '/flightchecks/flightcheck/json-load',
params: { id: type },
success: function(response, options, result) {
//get months from result
var months = result.data.months;
//create new date and plus returned months
var newDate = date.add(Date.MONTH, months);
//set new date
endDate.setValue(newDate);
}
});
}
}
});
I want to change the value of a global jquery variable within the foreach loop every time there is a new model item. I want to add new dates to the calendar but cant do that until I can access these functions from foreach loop.
*edit***
I over simplified my example for the question which was answered correctly by vov v. The actual code will do a lot more than add a value as it will add data to a calendar. I've added more code to show what it will do a little better
jquery:
<div id="calendar" style="width: 500px;" />
<script type="text/javascript">
$(document).ready(function () {
var calendar = $('#calendar').glDatePicker(
{
showAlways: true,
borderSize: 0,
dowOffset: 1,
selectableDOW: [1, 2, 3, 4, 5],
selectableYears: [2012, 2013, 2014, 2015],
specialDates: [
{
date: new Date(2013, 0, 8),
data: { message: 'Meeting every day 8 of the month' },
repeatMonth: true
},
{
date: new Date(2013, 5, 7),
data: { message: 'Meeting every day 8 of the month' }
},
],
onClick: function (target, cell, date, data) {
target.val(date.getFullYear() + ' - ' +
date.getMonth() + ' - ' +
date.getDate());
if (data != null) {
alert(data.message + '\n' + date);
}
}
}).glDatePicker(true);
$('#visible').change(function () {
var showAlways = eval($(this).val());
calendar.options.showAlways = showAlways;
if (!showAlways) {
calendar.hide();
}
else {
calendar.show();
}
});
});
var value = 0;
$('#total').click(function () {
alert(value);
});
function add() {
// will eventually add new specialDates to the calendar taken from model items
//test lines
//value = value + 1;
//return value;
}
</script>
razor view:
<input type="button" id="total" />
#foreach (var item in Model){
if (item.AppointmentStatus == "active")
{
// item display code
#: <script type="text/javascript"> add();</script>
}
if (item.AppointmentStatus == "history")
{
// item display code
}
}
I run this and get error below as it doesnt see the other code
'0x800a1391 - JavaScript runtime error: 'add' is undefined'
If you just want to capture "a count" that you want to send down to your client then you can simply do it like this:
<script>
var value = '#Model.Count';
// the rest of you script goes here
$(document).ready(function () {
$('#total').click(function () {
alert(value);
}
});
</script>
So say you have 7 items in your model, then the html that will be generated is this:
var value = 7;
and when you click on that total element it will give you an alert with the text 7.
Try moving your add function and variable declaration outside of doc ready. The functions in doc ready are not available until your razor has executed.