I am trying to write a custom datepicker, where the default drop downs for months and year ranges (enabled through changeMonth and changeYear options) are replaced by custom drop downs. It is something like this:
Fiddle: http://jsfiddle.net/gGV3v/
$("#myId").datepicker({
...default settings...
beforeShow: function() {
...here I replace the default dropdowns by custom dropdowns...
...something like...
$(".ui-datepicker-month").replaceWith("#custom-html-block");
$(".ui-datepicker-year").replaceWith("#another-custom-html-block");
}
});
On choosing either month or year from the custom dropdowns, I want to change the date in the view accordingly. So I construct the date string from the current month and year (the date for the new month/year combo defaults to 1 here), and I call
$("#custom-html-block .custom-dropdown-option").on("click",function() {
...construct newDateString...
$("#myId").datepicker("setDate",newDateString)
});
$("#another-custom-html-block .custom-dropdown-option").on("click",function() {
...construct newDateString...
$("#myId").datepicker("setDate",newDateString)
});
I want the span with text foo to remain intact when setting the new date programmatically on clicking it.
The problem is: it wipes off the custom drop downs and the default ones come again. I tried to do things like this:
$("#myId").datepicker($.extend({setDate: newDateString},oldSettings))
But it still doesn't work. How do I make this work?
You can set the value of the function $.datepicker._generateMonthYearHeader, the downside it that will be global for all datepicker in the page.
The sample is below:
$.datepicker._generateMonthYearHeader = function(inst, drawMonth, drawYear, minDate, maxDate,
secondary, monthNames, monthNamesShort) {
var inMinYear, inMaxYear, month, years, thisYear, determineYear, year, endYear,
changeMonth = this._get(inst, "changeMonth"),
changeYear = this._get(inst, "changeYear"),
showMonthAfterYear = this._get(inst, "showMonthAfterYear"),
html = "<div class='ui-datepicker-title'>",
monthHtml = "";
// year selection
if ( !inst.yearshtml ) {
inst.yearshtml = "";
if (secondary || !changeYear) {
html += "<span class='ui-datepicker-year'>" + drawYear + "</span>";
} else {
// determine range of years to display
years = this._get(inst, "yearRange").split(":");
thisYear = new Date().getFullYear();
determineYear = function(value) {
var year = (value.match(/c[+\-].*/) ? drawYear + parseInt(value.substring(1), 10) :
(value.match(/[+\-].*/) ? thisYear + parseInt(value, 10) :
parseInt(value, 10)));
return (isNaN(year) ? thisYear : year);
};
year = determineYear(years[0]);
endYear = Math.max(year, determineYear(years[1] || ""));
year = (minDate ? Math.max(year, minDate.getFullYear()) : year);
endYear = (maxDate ? Math.min(endYear, maxDate.getFullYear()) : endYear);
inst.yearshtml += "<span class = 'dummy'>Foo</span> <select class='ui-datepicker-year' data-handler='selectYear' data-event='change'>"
for (; year <= endYear; year++) {
inst.yearshtml += "<option value='" + year + "'" +
(year === drawYear ? " selected='selected'" : "") +
">" + year + "</option>";
}
inst.yearshtml += "</select>";
html += inst.yearshtml;
inst.yearshtml = null;
}
}
And your fiddle: http://jsfiddle.net/gGV3v/2/
UPDATE:
Without the buttons, and using a better approach, now you have control of all generated HTML:
var oldGenerateHTML = $.datepicker._generateHTML;
function newGenerateHTML(inst) {
var html = oldGenerateHTML.call(this, inst);
var $html = $(html);
$html.find('[data-handler=prev]').remove();
$html.find('[data-handler=next]').remove();
$html.find('[data-handler=selectMonth]').replaceWith('<span class="dummy">Foo</span>');
return $html;
}
$.datepicker._generateHTML = newGenerateHTML;
Fiddle also updated: http://jsfiddle.net/gGV3v/4/
In general this is why extend sucks. The parent (in your case datepicker) doesn't know anything about childs (your custom html). Everytime it refresh the view, your changes are lost. This problem is usually solved using composition. The goal is to create your own widget (I think that was the term in jQuery) that have datepicker as a local variable and to control _generateMonthYearHeader function calls. It's easy to say in theory but in practice (specially case with jQuery) is hard to achive. Easier solution will be to proxy the function.
//preserve _generateHTML because after it finish, html is visible and .ui-datepicker-month and .ui-datepicker-year are in dom tree
fn = $.datepicker._generateHTML; //preserve original function
$.datepicker._generateHTML = function(inst) {
//call original function
fn.call(this, inst);
//do custom changes
//you'll need better selectors in case of multiple datepicker instances
$(".ui-datepicker-month").replaceWith("#custom-html-block");
$(".ui-datepicker-year").replaceWith("#another-custom-html-block");
}
Personally I dislike this approach (I prefer composition as I said) but in your case it'll be easier to implement. The reason its easier is because generateMonthYearHeader is called from many different functions.
P.S. Not tested
Related
Do we have any available calendar widgets in jquery/javascript which helps us to select a week rather than dates.
My application has 2 dropdowns, From week and To week.
This is something that you need:
$('#weeklyDatePicker').on('dp.change', function (e) {
var value = $("#weeklyDatePicker").val();
var firstDate = moment(value, "MM-DD-YYYY").day(0).format("MM-DD-YYYY");
var lastDate = moment(value, "MM-DD-YYYY").day(6).format("MM-DD-YYYY");
$("#weeklyDatePicker").val(firstDate + " - " + lastDate);
});
for refrence you can check this link
https://jsfiddle.net/Prakash_Thete/9usq3enn/
This may help you
What is the best way to call function that will return string and show that string in a label when using angularJs?
I have three drop downs, and when I select values in all of them I want to show a label.
Content of a label is calculated in one function so on that moment (when all 3 drop downs have some values selected) I need to call function that will return value for label as well.
All that hiding/showing label logic I have put in html like this:
<div class="col-md-2"
ng-show="newTestSessionCtrl.formData.sessionTime && newTestSessionCtrl.formData.timeZone && newTestSessionCtrl.formData.sessionCloseInterval">
<lable>Your local time</lable>
<div ng-value="convertSelectedTimeZoneToClients()"></div>
</div>
This is convertSelectedTimeZoneToClients() function code:
convertSelectedTimeZoneToClients() {
let timeZoneInfo = {
usersTimeZone: this.$rootScope.mtz.tz.guess(),
utcOffset: this.formData.timeZone.offset,
selectedDateTime: this.toJSONLocal(this.formData.sessionDate) + " " + this.formData.sessionTime
};
let utcTime = this.$rootScope.mtz.utc(timeZoneInfo.selectedDateTime).utcOffset(timeZoneInfo.utcOffset).format("YYYY-MM-DD HH:mm");
let localTime = this.$rootScope.mtz.utc(utcTime).toDate();
localTime = this.$rootScope.mtz(localTime).format("YYYY-MM-DD HH:mm");
return localTime;
}
So when values are selected I am showing label that says: Your local time
And underneath I want to show result from convertSelectedTimeZoneToClients()that will be basically string in 'YYYY-MM-DD HH:mm' format.
Can I preform something like this on the html as well or I will have to move to controller? What is the best or easiest way to accomplish this?
I have tried ng-value, but I guess I am doing wrongly. Nothing gets show, but I do not get any errors in console as well.
in your function you can check if your drop downs are selected, then calculate and return result
$scope.getData = function () {
if ($scope.ValueOfFirstDropDown != undefined && $scope.ValueOfSecondDropDown != undefined && $scope.ValueOfThirdDropDown != undefined) {
//calculate result
return result;
}
}
and in your html
<label>{{getData()}}</label>
Try this:
<div ng-bind="convertSelectedTimeZoneToClients()"></div>
You should call this function on change of selected value
<select ng-change="convertSelectedTimeZoneToClients();"></select>
<div class="col-md-2"
ng-show="newTestSessionCtrl.formData.sessionTime && newTestSessionCtrl.formData.timeZone && newTestSessionCtrl.formData.sessionCloseInterval">
<lable>Your local time</lable>
<div ng-bind="clientDateTimeZone"></div>
</div>
and reflect $scope.clientDateTimeZone = yourreturnedvalue
No need to return any thing
$scope.convertSelectedTimeZoneToClients = function() {
let timeZoneInfo = {
usersTimeZone: this.$rootScope.mtz.tz.guess(),
utcOffset: this.formData.timeZone.offset,
selectedDateTime: this.toJSONLocal(this.formData.sessionDate) + " " + this.formData.sessionTime
};
let utcTime = this.$rootScope.mtz.utc(timeZoneInfo.selectedDateTime).utcOffset(timeZoneInfo.utcOffset).format("YYYY-MM-DD HH:mm");
let localTime = this.$rootScope.mtz.utc(utcTime).toDate();
localTime = this.$rootScope.mtz(localTime).format("YYYY-MM-DD HH:mm");
//set It here
$scope.clientDateTimeZone = localTime
//return localTime;
}
I used dhtmlx for chart gantt, I succeed in saving tasks in the data base, the problem is that when I add a new task there is no change in the chart,
for example if I add a new task with 4 days as duration it appears just one cell not four ones and also for the other properties.
Here the code of adding a new task :
<script type="text/javascript">
gantt.init("gantt_here");
gantt.attachEvent("onLightboxSave", function(id, task, is_new){
mnth = ("0" + (task.start_date.getMonth()+1)).slice(-2),
day = ("0" + task.start_date.getDate()).slice(-2);
mnth = ("0" + (task.end_date.getMonth()+1)).slice(-2),
day = ("0" + task.end_date.getDate()).slice(-2);
$.post("Control",{id:task.id,duration:task.duration,text:task.text,start_date:[ day,mnth, task.start_date.getFullYear() ].join("-").toString()},function(data){
alert(data);
}) ;
gantt.hideLightbox();
});
</script>
Try returning 'true' from onLightboxSave handler http://docs.dhtmlx.com/gantt/api__gantt_onlightboxsave_event.html
If you return 'false' or 'undefined' (as in your case), the form stays opened and the form values are not applied to the client-side.
Returning 'true' will save values and close the form, so you won't need to call hideLightbox manually
gantt.attachEvent("onLightboxSave", function(id, task, is_new){
var dateToStr = gantt.date.date_to_str("%d-%m-%Y");
$.post("Control",{
id:task.id,
duration:task.duration,
text:task.text,
start_date:dateToStr(task.start_date)
},function(data){
alert(data);
}) ;
return true;
});
I do apologize if this is an easy fix, I'm a tad new to jquery. To start I don't think that it is my initial call that is messing up because if I put a simple alert function in than it will work fine onclick, basically when this <li> is clicked on, jquery trigers an ajax to php function sending the class of the <li> to a php script and back, opening an alert with the result. As far as I can tell it should be working, but again my knowledge is rather limited. Any change anyone can take a look at what I have and see if you can clean it up at all, currently nothing happens onclick, no errors even appear in the console. But I imagine that even my ajax call is wrong. Any ideas why nothing happens on click?
HTML:
<li title = "Previous Month" id = "changeMonthBack" class = "<?php echo date('n'); ?>"><img src="images/leftArrow.gif" width="54" height="45" alt="previous month"></li>
jQuery/javascript:
//javascript document
$(document).ready(function(){
//need to do an onclick for getting the new month(previous)
$(".changeMonthBack").click(function(){
function calendar(){
//set the id for php
var identifier = 1;
//get the class to use for month
var str = document.getElementById("changeMonthBack").class;
//get the month number
//if the month is 1, we obviously need it to be 12
if str == 1{
var month = 12;
}
else{
var month = str - 1;
}
$.post("redraw.php"),{
identifier: identifier,
month: month
},
function(data,status){
alert("Data: " + data + "\nStatus: " + status);
};
})//end function 1
});
There are multiple problems with the script.
1. As Aesthete suggested the selector should be an id selector #changeMonthBack
2. You are creating a closure method called calendar but never called it
3. There were multiple syntax error (Use a javascript editor like spket)
You are creating a function called calendar but never calls it.
$(document).ready(function() {
// need to do an onclick for getting the new month(previous)
$("#changeMonthBack").click(function() {
// set the id for php
var identifier = 1;
// get the class to use for month
var str = parseInt($(this).attr('class'),10);
// get the month number
// if the month is 1, we obviously need it to be 12
if (str == 1) {
var month = 12;
} else {
var month = str - 1;
}
$.post("redraw.php", {
identifier : identifier,
month : month
},
function(data, status) {
alert("Data: " + data + "\nStatus: "
+ status);
});
});
});
I'm building out an online reservation system for a pet-boarding business in my city and I've hit a wall as to how to efficiently carry out this specific functionality.
Quick gist of the user process...
Some preliminary info is given (client info, pet info, etc etc).
User chooses 2 dates; the check-in and check-out days.
The program calculates the number of days the client is staying and each day is thrown into a constructor for class "Day". A ... block is generated for each day and displayed to the user. It also might be worth noting that all of the Day objects are stored in an array which is then contained in the mama class "ReservationData"...which besides the Day-array also holds some meta-data pertaining to the reservation itself.
Anyway, my problem is that once the 'dayBlocks' are listed & displayed to the user, the user must then be able to go and check individual "extras" that they want for their pet on that specific day.
So I've broken it down so that {ReservationData} <--(has an array of)-- {Days} <--(has an array of)-- {Extras}. There are 14 extra services to choose from, so for each day displayed there is a simple list of checkboxes and labels.
Ideally, I want it setup so that when a checkbox is checked by the user, it directly & immediately alters its corresponding variable within the reservationDataDaysExtraDeepArray accordingly. The C-programmer in me wants to tie a pointer to each checkbox, but I'm (at least I think) pretty sure that's not doable with jQuery.
Although I think I explained it pretty clearly, here's some of the code:
//Day Object/Class
function day(_date, _daynum) {
this.date = new Date(_date);
this.dayNum = _daynum;
this.dayExtras = {
'YH': false, //<--- How can I directly manipulate
'PP': false, //<--- all of these guys via user-control
'EE': false, //<--- of corresponding/assigned
'ST': false, //<--- checkboxes?
'PT': false,
'TT15': false,
'TT30': false,
'TT45': false,
'DC': false //--- Or can I? :/
};
console.log("Day object created with date of " + day.date + " and day-number of " + day.dayNum + ".");
this.getDayNum = function() { return this.dayNum; }
this.getDayDate = function() { return this.date; }
}
This is my first question on this site, but I did a lot of searching and am still lost...thanks guys!
Assuming the name of your checkboxes correspond to the keys in your dayExtras object something like this would do..
//Day Object/Class
function day(_date, _daynum) {
this.date = new Date(_date);
this.dayNum = _daynum;
this.dayExtras = {
'YH': false, //<--- How can I directly manipulate
'PP': false, //<--- all of these guys via user-control
'EE': false, //<--- of corresponding/assigned
'ST': false, //<--- checkboxes?
'PT': false,
'TT15': false,
'TT30': false,
'TT45': false,
'DC': false //--- Or can I? :/
};
console.log("Day object created with date of " + day.date + " and day-number of "+day.dayNum+".");
this.getDayNum = function() { return this.dayNum; }
this.getDayDate = function() { return this.date; }
this.setDayExtras = function (key,val) {
if(key in this.dayExtras){
this.dayExtras[key] = val;
}
}
}
var myDay = new day(null,null);
$(document).on('change','#myForm input[type="checkbox"]', function () {
myDay.setDayExtras(this.name,this.checked);
});
Got it working, thanks for pointing me in the right direction guys!
function saveExtra(me) {
var extraName = me.attr('name');
var extraVal = me.val();
(reservationData[extraName]).dayExtras[extraVal] = me.prop('checked');
for (key in reservationData) {
(reservationData[key]).dump(); //Day data-dump method.
}
}
this.generateExtrasGrid = function() {
var fieldName = "day" + this.dayNum + "";
var exGrid = "";
exGrid += "<form class='extrasGrid' id='" + this.dayNum + "'>";
exGrid += "<input type='checkbox' class='extra' name='" + fieldName + "' value='YH' onclick='saveExtra($(this))' />";............
exGrid += "</form>";
return exGrid;
}