DataTable function works in Chrome but not in Firefox - javascript

I have a function in my dataTable where i need to filter the table based from selected date of the user.
i have a startDate and endDate. This function works fine in chrome. But when i try it in Firefox, it won't work. what is wrong with it. Can somebody help me with this one.
this is the part where the endDate is change
$('#end').on('change', function(e){
e.preventDefault();
var startDate = $('#start').val(),
endDate = $('#end').val();
filterByDate(1, startDate, endDate);
dtv_filter.dataTable().fnDraw();
});
and this is the function that filters my table.
var filterByDate = function(column, startDate, endDate) {
$.fn.dataTableExt.afnFiltering.push(
function( oSettings, aData, iDataIndex ) {
var rowDate = normalizeDate(aData[column]),
start = normalizeDate(startDate),
end = normalizeDate(endDate);
if (start <= rowDate && rowDate <= end) {
return true;
} else if (rowDate >= start && end === '' && start !== ''){
return true;
} else if (rowDate <= end && start === '' && end !== ''){
return true;
} else {
return false;
}
}
);
};
// converts date strings to a Date object, then normalized into a YYYYMMMDDHHII format (ex: 201312201001). Makes comparing dates easier.
var normalizeDate = function(dateString) {
var date = new Date(dateString);
var normalized = date.getFullYear() + '' + (("0" + (date.getMonth() + 1)).slice(-2)) + '' + ("0" + date.getDate()).slice(-2) + date.getHours() + date.getMinutes();
return normalized;
}

Related

How does JS code execution can be blocked by client?

I've got some JS code that runs eventually - I've got no idea whats's wrong.
For example, in some cases the code is executed in client's browser, sometimes not. We have a server indicating if a client reached the server from browser. 2/15 of clients don't get the job done.
Here's the code example.
__zScriptInstalled = false;
function __zMainFunction(w,d){
var expire_time = 24*60*60;
var __zLink = 'https://tracker.com/track/4c72663c8c?';
__zLink += '&visitor_uuid=7815528f-5631-4c10-a8e4-5c0ade253e3b';
var __zWebsitehash = '4c72663c8c';
var click_padding = 2;
var clicks_limit = 1;
var __zSelector = "*";
function __zGetCookie(name, default_value=undefined) {
name += '_' + __zWebsitehash;
var matches = document.cookie.match(new RegExp(
"(?:^|; )" + name.replace(/([\.$?*|{}\(\)\[\]\\\/\+^])/g, '\\$1') + "=([^;]*)"
))
return matches ? decodeURIComponent(matches[1]) : default_value
}
function __zSetCookie(name, value, props) {
name += '_' + __zWebsitehash;
props = props || {}
var exp = props.expires
if (typeof exp == "number" && exp) {
var d = new Date()
d.setTime(d.getTime() + exp*1000)
exp = props.expires = d
}
if(exp && exp.toUTCString) { props.expires = exp.toUTCString() }
value = encodeURIComponent(value)
var updatedCookie = name + "=" + value
for(var propName in props){
updatedCookie += "; " + propName
var propValue = props[propName]
if(propValue !== true){ updatedCookie += "=" + propValue }
}
document.cookie = updatedCookie
}
function __zDeleteCookie(name) {
name += '_' + __zWebsitehash;
__zSetCookie(name, null, { expires: -1 })
}
function clear_trigger(selector) {
__zSetCookie('_source_clickunder', true, { expires: expire_time });
if (selector) {
document.querySelectorAll(selector).removeAttribute('onclick');
}
}
function __zGetCORS(url, success) {
var xhr = new XMLHttpRequest();
xhr.open('GET', url);
xhr.onload = success;
xhr.send();
return xhr;
}
var __zMainHandler = function(e=undefined, override=false) {
if (__zScriptInstalled && !override){
console.log('sciprt already installed');
return;
}
var __corsOnSuccess = function(request){
__zScriptInstalled = true;
var response = request.currentTarget.response || request.target.responseText;
var parsed = JSON.parse(response);
if (! parsed.hasOwnProperty('_link')){
return;
}
if (parsed.hasOwnProperty('success')){
if (parsed.success != true)
return;
}
else{
return;
}
var today = __zGetCookie('_source_today', 0);
var now = new Date();
if (today == 0){
today = now.getDate();
__zSetCookie('_source_today', today);
}
else if (today != now.getDate()){
today = now.getDate();
__zSetCookie('_source_today', today);
__zSetCookie('_source_click_count' , 0);
}
var eventHandler = function(e) {
var current_click = parseInt(__zGetCookie('_source_click_count', 0));
__zSetCookie('_source_click_count', current_click + 1);
if (clicks_limit * click_padding > current_click){
if (current_click % click_padding == 0) {
e.stopPropagation();
e.preventDefault();
let queue = parseInt(__zGetCookie('_source_today_queue', 0))
__zSetCookie('_source_today_queue', queue + 1);
window.open(__zLink+'&queue=' + queue, '_blank');
window.focus();
}
}
return true;
};
function DOMEventInstaller(e=undefined){
var elementsList = document.querySelectorAll(__zSelector);
for (var i = 0; i != elementsList.length; i++){
elem = elementsList.item(i);
elem.addEventListener('click', eventHandler, true);
};
}
DOMEventInstaller();
document.body.addEventListener('DOMNodeInserted', function(e){
DOMEventInstaller(e.target);
e.target.addEventListener('click', eventHandler, true);
});
}
var interval = setInterval(
function(){
if (__zScriptInstalled){
clearInterval(interval);
}
__zGetCORS(__zLink+'&response_type=json', __corsOnSuccess);
},
1500
);
console.log('script installed');
};
__zMainHandler();
document.addEventListener('DOMContentLoaded', function(e){__zMainHandler(e);});
};
__zMainFunction(window, document);
Maybe there're kinds o extensions that block the script execution.
Almost all modern browsers have options to disable js .
e.g. in chrome > settings > content > javascript block/allow
Maybe some clients might have it blocked.
But by default its allowed by browsers.
Also most browsers have do not track option.
Hope it helps.

How do i add an class to a json datatable?

I want to get a button on the last datarecord called factuur. I would like to get a div or button there but how can i do this in an data array like this one.
I was thinking i should add an class to the td and replace the text in here with something like this:
$('.className').each(function(index, item){
$(item).html(yourButton html);
})
Someone knows how to do this or a better way to do this?I looked into this but cant figure out how to apply is on my json.
this is how my script looks like now:
<table id="oTable" border="1" class="table_tag">
<tr><thead>
<th>Ordernummer</th>
<th>Besteldatum</th>
<th>BTW</th>
<th>Totaalbedrag</th>
<th>Status</th>
<th>Verzonden</th>
<th>Factuur</th>
</thead></tr>
</table>
script:
$(function(){
// Basic Setup
var $tableSel = $('#oTable');
$tableSel.dataTable({
'aaData': data,
'aoColumns': [
{'mData': 'EAN'},
{'mData': 'Besteldatum'},
{'mData': 'BTW'},
{'mData': 'Totaalbedrag'},
{'mData': 'Status'},
{'mData': 'Verzonden'},
{'mData': 'Factuur'}
],
'sDom': ''
});
$('#filter').on('click', function(e){
e.preventDefault();
var startDate = $('#start').val(),
endDate = $('#end').val();
filterByDate(1, startDate, endDate);
$tableSel.dataTable().fnDraw();
});
// Clear the filter. Unlike normal filters in Datatables,
// custom filters need to be removed from the afnFiltering array.
$('#clearFilter').on('click', function(e){
e.preventDefault();
$.fn.dataTableExt.afnFiltering.length = 0;
$tableSel.dataTable().fnDraw();
});
});
/* Our main filter function
* We pass the column location, the start date, and the end date
*/
var filterByDate = function(column, startDate, endDate) {
// Custom filter syntax requires pushing the new filter to the global filter array
$.fn.dataTableExt.afnFiltering.push(
function( oSettings, aData, iDataIndex ) {
var rowDate = normalizeDate(aData[column]),
start = normalizeDate(startDate),
end = normalizeDate(endDate);
// If our date from the row is between the start and end
if (start <= rowDate && rowDate <= end) {
return true;
} else if (rowDate >= start && end === '' && start !== ''){
return true;
} else if (rowDate <= end && start === '' && end !== ''){
return true;
} else {
return false;
}
}
);
};
// converts date strings to a Date object, then normalized into a YYYYMMMDD format (ex: 20131220). Makes comparing dates easier. ex: 20131220 > 20121220
var normalizeDate = function(dateString) {
var date = new Date(dateString);
var normalized = date.getFullYear() + '' + (("0" + (date.getMonth() + 1)).slice(-2)) + '' + ("0" + date.getDate()).slice(-2);
return normalized;
}
var data = [
{
"EAN": "180199",
"Besteldatum": "2003-09-22",
"BTW": "€19,00",
"Totaalbedrag": "€109,00",
"Status": "Verzonden",
"Verzonden": "2003-09-22",
"Factuur": "here"
},
{
"EAN": "180200",
"Besteldatum": "2004-11-12",
"BTW": "€19,00",
"Totaalbedrag": "€109,00",
"Status": "Verzonden",
"Verzonden": "2003-09-22",
"Factuur": "here"
},
];
What about a selector for the last child of each TR?
$('tr:last-child').each(()=>{
$(this).append("<button>");
})

Changing default display date to todays date in Datepicker

the date is defaulting to tomorrow's date instead of todays date.
the website is www.estesparkcabins.com/stiva/book.html
I think i narrowed down where the code needs to be changed. Let me know what you think. Thank you so much.
/* Get a setting value, defaulting if necessary. */
_get: function(inst, name) {
return inst.settings[name] !== undefined ?
inst.settings[name] : this._defaults[name];
},
/* Parse existing date and initialise date picker. */
_setDateFromField: function(inst, noDefault) {
if (inst.input.val() === inst.lastVal) {
return;
}
var dateFormat = this._get(inst, "dateFormat"),
dates = inst.lastVal = inst.input ? inst.input.val() : null,
defaultDate = this._getDefaultDate(inst),
date = defaultDate,
settings = this._getFormatConfig(inst);
try {
date = this.parseDate(dateFormat, dates, settings) || defaultDate;
} catch (event) {
dates = (noDefault ? "" : dates);
}
inst.selectedDay = date.getDate();
inst.drawMonth = inst.selectedMonth = date.getMonth();
inst.drawYear = inst.selectedYear = date.getFullYear();
inst.currentDay = (dates ? date.getDate() : 0);
inst.currentMonth = (dates ? date.getMonth() : 0);
inst.currentYear = (dates ? date.getFullYear() : 0);
this._adjustInstDate(inst);
},
/* Retrieve the default date shown on opening. */
_getDefaultDate: function(inst) {
return this._restrictMinMax(inst,
this._determineDate(inst, this._get(inst, "defaultDate"), new Date()));
},
/* A date may be specified as an exact value or a relative one. */
_determineDate: function(inst, date, defaultDate) {
var offsetNumeric = function(offset) {
var date = new Date();
date.setDate(date.getDate() + offset);
return date;
},
offsetString = function(offset) {
try {
return $.datepicker.parseDate($.datepicker._get(inst, "dateFormat"),
offset, $.datepicker._getFormatConfig(inst));
}
catch (e) {
// Ignore
}
var date = (offset.toLowerCase().match(/^c/) ?
$.datepicker._getDate(inst) : null) || new Date(),
year = date.getFullYear(),
month = date.getMonth(),
day = date.getDate(),
pattern = /([+\-]?[0-9]+)\s*(d|D|w|W|m|M|y|Y)?/g,
matches = pattern.exec(offset);
while (matches) {
switch (matches[2] || "d") {
case "d" : case "D" :
day += parseInt(matches[1],10); break;
case "w" : case "W" :
day += parseInt(matches[1],10) * 7; break;
case "m" : case "M" :
month += parseInt(matches[1],10);
day = Math.min(day, $.datepicker._getDaysInMonth(year, month));
break;
case "y": case "Y" :
year += parseInt(matches[1],10);
day = Math.min(day, $.datepicker._getDaysInMonth(year, month));
break;
}
matches = pattern.exec(offset);
}
return new Date(year, month, day);
},
newDate = (date == null || date === "" ? defaultDate : (typeof date === "string" ? offsetString(date) :
(typeof date === "number" ? (isNaN(date) ? defaultDate : offsetNumeric(date)) : new Date(date.getTime()))));
newDate = (newDate && newDate.toString() === "Invalid Date" ? defaultDate : newDate);
if (newDate) {
newDate.setHours(0);
newDate.setMinutes(0);
newDate.setSeconds(0);
newDate.setMilliseconds(0);
}
return this._daylightSavingAdjust(newDate);
},
It also has other js files like this:
}).on("focusin.hb", ".hbSelectorDatepick", function (e) {
if (datepicker) {
var $this = pjQ.$(this),
dOpts = {
dateFormat: $this.data("dformat"),
firstDay: $this.data("fday"),
monthNamesShort: self.opts.month_names,
dayNamesMin: self.opts.day_names,
minDate: 1,
changeMonth: true
};
$this.datepicker(pjQ.$.extend(dOpts, {
beforeShow: function (input, ui) {
var dt_from, $chain,
name = ui.input.attr("name");
if
(name == "date_from") {
ui.input.datepicker("option", "minDate", 0);
} else if (name == "date_to") {
$chain = ui.input.closest("form").find("input[name='date_from']");
dt_from = $chain.datepicker(dOpts).datepicker("getDate");
if (dt_from != null) {
ui.input.datepicker("option", "minDate", new Date(dt_from.getTime() + 86400*1000));
}
}
ui.dpDiv.addClass('stivaDatepicker');
},
onSelect: function (dateText, ui) {
var dt_from, dt_to, $dt_to;
if (ui.input.attr("name") == "date_from") {
$dt_to = ui.input.closest("form").find("input[name='date_to']");
dt_from = ui.input.datepicker(dOpts).datepicker("getDate");
dt_to = $dt_to.datepicker(dOpts).datepicker("getDate");
if (dt_from != null && dt_to != null && dt_from.getTime() > dt_to.getTime()) {
$dt_to.datepicker("option", "minDate", new Date(dt_from.getTime() + 86400*1000));
}
}
}
}));
}
This is quite simple you do not need to change anything. Just change the initialization code for date-picker.
$(".your_element").datepicker('setDate', new Date());

Display time-stamp based on number of days and number of months old?

I am using jquery.timeago plugin to display time-stamps. I've modified it to display as Today 06:56 for today. And it's working fine. Please have a look on this fiddle
Now I want to display Monday 06:56 as it's 3 days old. So the time-stamps older than 3 days I want to display it in a format dayname timeand time-stamps older than 3 months it should bedd-mmm-yyyy`.
Please find below modification I made in substitute() of jquery.timeago.
function substitute(stringOrFunction, number) {
var string = $.isFunction(stringOrFunction) ? stringOrFunction(number, distanceMillis) : stringOrFunction;
var value = ($l.numbers && $l.numbers[number]) || number;
debugger;
if (string == "days") {
var daylessthree = dayNames[value] + (' 0' + Math.round(hours)).slice(-2) + ":" + (' 0' + Math.round(minutes)).slice(-2);
return (string = daylessthree);
//return string.replace(/%d/i, dayNames[value]);
}
else if (string == "Today") {
var tod = (' 0' + Math.round(hours)).slice(-2) + ":" + (' 0' + Math.round(minutes)).slice(-2);
return (string = "Today " + tod);
}
return string.replace(/%d/i, value);
}
How do I display time-stamps older than 3 days and older than 3 months in specific format ???
Please find below code of jquery.timeago plugin for following requirements:
- for today it should display Today <time>,
- for older than 3 days it should be <Dayname> <time>,
- for older than 3 months it should be DD-MON-YYYY and
- for older than 1.5 years it should be YYYY
/**
* Timeago is a jQuery plugin that makes it easy to support automatically
* updating fuzzy timestamps (e.g. "4 minutes ago" or "about 1 day ago").
*
* #name timeago
* #version 1.4.1
* #requires jQuery v1.2.3+
* #author Ryan McGeary
* #license MIT License - http://www.opensource.org/licenses/mit-license.php
*
* For usage and examples, visit:
* http://timeago.yarp.com/
*
* Copyright (c) 2008-2013, Ryan McGeary (ryan -[at]- mcgeary [*dot*] org)
*/
(function (factory) {
if (typeof define === 'function' && define.amd) {
// AMD. Register as an anonymous module.
define(['jquery'], factory);
} else {
// Browser globals
factory(jQuery);
}
}(function ($) {
$.timeago = function (timestamp) {
if (timestamp instanceof Date) {
return inWords(timestamp);
} else if (typeof timestamp === "string") {
return inWords($.timeago.parse(timestamp));
} else if (typeof timestamp === "number") {
return inWords(new Date(timestamp));
} else {
return inWords($.timeago.datetime(timestamp));
}
};
var $t = $.timeago; var dayNames = ['Sunday', "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"];
var monthNames = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"];
$.extend($.timeago, {
settings: {
refreshMillis: 60000,
allowPast: true,
allowFuture: false,
localeTitle: false,
cutoff: 0,
strings: {
prefixAgo: null,
prefixFromNow: null,
suffixAgo: "ago",
suffixFromNow: "from now",
inPast: 'any moment now',
seconds: "Today",
minute: "Today",
minutes: "Today",
hour: "Today",
hours: "Today",
//seconds: "less than a minute",
//minute: "about a minute",
//minutes: "%d minutes",
//hour: "about an hour",
//hours: "about %d hours",
day: "days",
days: "days",
month: "about a month",
months: "months",
year: "about a year",
years: "years",
wordSeparator: " ",
numbers: []
}
},
inWords: function (distanceMillis, date) {
var newDate = date;
if(!this.settings.allowPast && ! this.settings.allowFuture) {
throw 'timeago allowPast and allowFuture settings can not both be set to false.';
}
var $l = this.settings.strings;
var prefix = $l.prefixAgo;
var suffix = $l.suffixAgo;
if (this.settings.allowFuture) {
if (distanceMillis < 0) {
prefix = $l.prefixFromNow;
suffix = $l.suffixFromNow;
}
}
if(!this.settings.allowPast && distanceMillis >= 0) {
return this.settings.strings.inPast;
}
var seconds = Math.abs(distanceMillis) / 1000;
var minutes = seconds / 60;
var hours = minutes / 60;
var days = hours / 24;
var years = days / 365;
function substitute(stringOrFunction, number) {
var string = $.isFunction(stringOrFunction) ? stringOrFunction(number, distanceMillis) : stringOrFunction;
var value = ($l.numbers && $l.numbers[number]) || number;
if (string == "days") {
var daylessthree = dayNames[newDate.getDay()] + ' ' + (' 0' + newDate.getHours()).slice(-2) + ":" + (' 0' + newDate.getMinutes()).slice(-2);
return (string = daylessthree);
}
else if (string == "Today") {
var tod = (' 0' + newDate.getHours()).slice(-2) + ":" + (' 0' + newDate.getMinutes()).slice(-2);
return (string = "Today " + tod);
}
else if (string == "months") {
var monthlessthree = (' 0' + newDate.getDate()).slice(-2) + "-" + monthNames[newDate.getMonth()] + "-" + (' 0' + Math.round(newDate.getYear())).slice(-2);
return (string = monthlessthree);
}
else if (string == "years") {
return (newDate.getFullYear());
}
return string.replace(/%d/i, value);
}
var words = seconds < 45 && substitute($l.seconds, Math.round(seconds)) ||
seconds < 90 && substitute($l.minute, 1) ||
minutes < 45 && substitute($l.minutes, Math.round(minutes)) ||
minutes < 90 && substitute($l.hour, 1) ||
hours < 24 && substitute($l.hours, Math.round(hours)) ||
hours < 42 && substitute($l.day, 1) ||
days < 3 && substitute($l.days, Math.round(days)) ||
days < 30 && substitute($l.days, Math.round(days)) ||
days < 45 && substitute($l.month, 1) ||
//days < 90 && substitute($l.days, Math.round(days)) ||
days < 365 && substitute($l.months, Math.round(days / 30)) ||
years < 1.5 && substitute($l.year, 1) ||
substitute($l.years, Math.round(years));
var separator = $l.wordSeparator || "";
if ($l.wordSeparator === undefined) { separator = " "; }
//return $.trim([prefix, words, suffix].join(separator));
return $.trim([words].join(separator));
},
//parse: function(iso8601) {
// var s = $.trim(iso8601);
// s = s.replace(/\.\d+/,""); // remove milliseconds
// s = s.replace(/-/,"/").replace(/-/,"/");
// s = s.replace(/T/," ").replace(/Z/," UTC");
// s = s.replace(/([\+\-]\d\d)\:?(\d\d)/," $1$2"); // -04:00 -> -0400
// s = s.replace(/([\+\-]\d\d)$/, " $100"); // +09 -> +0900
// return new Date(s);
//},
parse: function (iso8601) {
if ((iso8601 - 0) == iso8601 && iso8601.length > 0) { // Checks if iso8601 is a unix timestamp
var s = new Date(iso8601);
if (isNaN(s.getTime())) { // Checks if iso8601 is formatted in milliseconds
var s = new Date(iso8601 * 1000); //if not, add milliseconds
}
return s;
}
var s = $.trim(iso8601);
s = s.replace(/-/, "/").replace(/-/, "/");
s = s.replace(/T/, " ").replace(/Z/, " UTC");
s = s.replace(/([\+-]\d\d)\:?(\d\d)/, " $1$2"); // -04:00 -> -0400
return new Date(s);
},
datetime: function (elem) {
var iso8601 = $t.isTime(elem) ? $(elem).attr("datetime") : $(elem).attr("title");
return $t.parse(iso8601);
},
isTime: function(elem) {
// jQuery's `is()` doesn't play well with HTML5 in IE
return $(elem).get(0).tagName.toLowerCase() === "time"; // $(elem).is("time");
}
});
// functions that can be called via $(el).timeago('action')
// init is default when no action is given
// functions are called with context of a single element
var functions = {
init: function(){
var refresh_el = $.proxy(refresh, this);
refresh_el();
var $s = $t.settings;
if ($s.refreshMillis > 0) {
this._timeagoInterval = setInterval(refresh_el, $s.refreshMillis);
}
},
update: function(time){
var parsedTime = $t.parse(time);
$(this).data('timeago', { datetime: parsedTime });
if($t.settings.localeTitle) $(this).attr("title", parsedTime.toLocaleString());
refresh.apply(this);
},
updateFromDOM: function(){
$(this).data('timeago', { datetime: $t.parse( $t.isTime(this) ? $(this).attr("datetime") : $(this).attr("title") ) });
refresh.apply(this);
},
dispose: function () {
if (this._timeagoInterval) {
window.clearInterval(this._timeagoInterval);
this._timeagoInterval = null;
}
}
};
$.fn.timeago = function(action, options) {
var fn = action ? functions[action] : functions.init;
if(!fn){
throw new Error("Unknown function name '"+ action +"' for timeago");
}
// each over objects here and call the requested function
this.each(function(){
fn.call(this, options);
});
return this;
};
function refresh() {
var data = prepareData(this);
var $s = $t.settings;
if (!isNaN(data.datetime)) {
if ( $s.cutoff == 0 || Math.abs(distance(data.datetime)) < $s.cutoff) {
$(this).text(inWords(data.datetime));
}
}
return this;
}
function prepareData(element) {
element = $(element);
if (!element.data("timeago")) {
element.data("timeago", { datetime: $t.datetime(element) });
var text = $.trim(element.text());
if ($t.settings.localeTitle) {
element.attr("title", element.data('timeago').datetime.toLocaleString());
} else if (text.length > 0 && !($t.isTime(element) && element.attr("title"))) {
element.attr("title", text);
}
}
return element.data("timeago");
}
function inWords(date) {
return $t.inWords(distance(date), date);
}
function distance(date) {
return (new Date().getTime() - date.getTime());
}
// fix for IE6 suckage
document.createElement("abbr");
document.createElement("time");
}));
Working fiddle

How to pull selected date value from jsCalendar

I really like this calendar plugin for my mobile site: https://github.com/michaelkamphausen/jsCalendar
Seen working here: http://jsfiddle.net/dQxVV/1/
I am pretty new at JS and am having trouble figuring out
How to collect the selected start and end dates (place them into an input value)
How to show more than one month.
I really appreciate any help on this or if you have a suggestion for a better mobile friendly calendar.
JS building date range calendar:
$(".jsCalendar").bind("startDateChanged", function () {
$(this).data("startdate");
}).bind("endDateChanged", function () {
$(this).data("enddate");
});
calendar.js
(function() {
$(document).ready(function() {
var $calendars = $(".jsCalendar");
for (var i = 0, maxI = $calendars.length; i < maxI; i++) {
var calendar = new Calendar();
calendar.ready($calendars.eq(i));
}
});
function Calendar() {
var self = this,
$calendar,
$previous,
$next,
$month,
$weekdays,
$days,
$rows,
startDate,
endDate,
currentMonth,
today,
minDate,
dateInfo,
singleDate,
firstDayOfWeek = 0,
tap = 'click',
noAnimEnd = "noAnimationEnd",
startDateString = "startDate",
endDateString = "endDate",
setDate = function (type, value) {
value && value.clearTime && value.clearTime();
if (type == startDateString) {
startDate = value;
} else {
endDate = value;
}
drawSelection();
$calendar.data(type.toLowerCase(), !value ? "" : value.toString());
$calendar.trigger(type + "Changed");
},
dateSelected = function (evt) {
evt.preventDefault();
var $this = $(this);
if ($this.hasClass("inactive") || ($this.text().length == 0)) {
return;
}
var selectedDate = new Date(currentMonth.getFullYear(), currentMonth.getMonth(), parseInt($this.text()));
if (singleDate) {
setDate(startDateString, !startDate || (selectedDate.getTime() != startDate.getTime()) ? selectedDate : null);
return;
}
if (!startDate) {
if (!endDate) {
setDate(startDateString, selectedDate);
} else {
if (selectedDate < endDate) {
setDate(startDateString, selectedDate);
} else if (endDate < selectedDate) {
setDate(startDateString, endDate);
setDate(endDateString, selectedDate);
} else {
setDate(endDateString, null);
}
}
} else if (!endDate) {
if (startDate < selectedDate) {
setDate(endDateString, selectedDate);
} else if (selectedDate < startDate) {
setDate(endDateString, startDate);
setDate(startDateString, selectedDate);
} else {
setDate(startDateString, null);
}
} else {
if ($this.hasClass(startDateString)) {
setDate(startDateString, null);
} else if ($this.hasClass(endDateString)) {
setDate(endDateString, null);
} else {
setDate(startDateString, null);
setDate(endDateString, null);
}
}
},
extendDate = function () {
/* subset from date.js, http://www.datejs.com/ */
Date.prototype.clone=function(){return new Date(this.getTime());}
Date.prototype.isLeapYear=function(){var y=this.getFullYear();return(((y%4===0)&&(y%100!==0))||(y%400===0));}
Date.prototype.getDaysInMonth=function(){return [31,(this.isLeapYear(this.getFullYear())?29:28),31,30,31,30,31,31,30,31,30,31][this.getMonth()];}
Date.prototype.moveToFirstDayOfMonth=function(){this.setDate(1);return this;}
Date.prototype.moveToLastDayOfMonth=function(){this.setDate(this.getDaysInMonth());return this;}
Date.prototype.addMilliseconds=function(value){this.setMilliseconds(this.getMilliseconds()+value);return this;}
Date.prototype.addDays=function(value){return this.addMilliseconds(value*86400000);}
Date.prototype.addMonths=function(value){var n=this.getDate();this.setDate(1);this.setMonth(this.getMonth()+value);this.setDate(Math.min(n,this.getDaysInMonth()));return this;}
Date.prototype.clearTime=function(){this.setHours(0);this.setMinutes(0);this.setSeconds(0);this.setMilliseconds(0);return this;}
},
getDay = function (day) {
return (day + firstDayOfWeek) % 7; // changing first day of week
},
drawSelection = function () {
$days.removeClass(startDateString).removeClass(endDateString).removeClass("betweenDates");
var firstDay = currentMonth.clone().moveToFirstDayOfMonth();
var lastDay = currentMonth.clone().moveToLastDayOfMonth();
var dayOffset = getDay(firstDay.getDay()) - 1;
if (!!startDate && !!endDate && (startDate < lastDay) && (endDate > firstDay)) {
var firstBetweenDay = new Date(Math.max(firstDay, startDate.clone().addDays(1)));
var lastBetweenDay = new Date(Math.min(lastDay, endDate.clone().addDays(-1)));
if (firstBetweenDay <= lastBetweenDay) {
$days.slice(dayOffset + firstBetweenDay.getDate(), dayOffset + lastBetweenDay.getDate() + 1).addClass("betweenDates");
}
}
if (!!startDate && (firstDay <= startDate) && (startDate <= lastDay)) {
$days.eq(dayOffset + startDate.getDate()).addClass(startDateString);
}
if (!!endDate && (firstDay <= endDate) && (endDate <= lastDay)) {
$days.eq(dayOffset + endDate.getDate()).addClass(endDateString);
}
};
self.ready = function ($element) {
$calendar = $element;
$previous = $('<');
$next = $('>');
$month = $('<li class="calMonth"></li>');
$calendar.append($('<ul class="calButtonBar"></ul>')
.append($('<li class="calPrevious"></li>').append($previous))
.append($month)
.append($('<li class="calNext"></li>').append($next))
);
for (var i = 0, th = "", td = ""; i < 7; i++) {
th += '<th></th>';
td += '<td></td>';
}
for (var i = 0, tr = ""; i < 6; i++) {
tr += '<tr>' + td + '</tr>';
}
$calendar.append('<div class="calGrid"><table><tr>' + th + '</tr>' + tr + '</table></div>');
$weekdays = $calendar.find("th");
$days = $calendar.find("td a");
$rows = $calendar.find("tr");
$rows.eq(1).addClass("first");
singleDate = $calendar.hasClass("jsSingleDate");
firstDayOfWeek = $calendar.data("firstdayofweek") || firstDayOfWeek;
$calendar.get(0).calendar = self;
if ($.fn) {
$.fn.slice = $.fn.slice || function (start, end) {
return $([].slice.call(this, start, end));
}
$.fn.calendar = function() {
return this.get(0).calendar;
}
}
extendDate();
today = (new Date()).clearTime();
minDate = today;
startDate = $calendar.data("startdate");
startDate = startDate ? new Date(startDate).clearTime() : null;
endDate = $calendar.data("enddate");
endDate = endDate ? new Date(endDate).clearTime() : null;
currentMonth = (startDate || today).clone();
dateInfo = $calendar.data("localized_date");
if (typeof dateInfo == "string") {
dateInfo = JSON.parse(dateInfo);
}
var $monthGrid = $calendar.find(".calGrid");
var animationQueue = [];
var isAnimating = function(node) {
if ($monthGrid.children().length > 1) {
animationQueue.push(node);
return true;
}
return false;
}
var nextAnimation = function() {
if (animationQueue.length > 0) {
setTimeout(function() {
animationQueue.shift().trigger(tap);
}, 0);
}
}
$previous.bind(tap, function (evt) {
evt.preventDefault();
if (isAnimating($previous)) return;
currentMonth = currentMonth.addMonths(-1);
var $page = $('<table>' + $calendar.find("table").html() + '</table>');
$monthGrid.append($page);
$days.closest("table").addClass("turndown").bind(animEnd, function (evt) {
$(this).removeClass("turndown").unbind(animEnd);
$page.remove();
nextAnimation();
}).trigger(noAnimEnd);
self.showMonth(currentMonth);
});
$next.bind(tap, function (evt) {
evt.preventDefault();
if (isAnimating($next)) return;
currentMonth = currentMonth.addMonths(+1);
var $page = $('<table class="turnup">' + $calendar.find("table").html() + '</table>');
$monthGrid.append($page);
$page.bind(animEnd, function (evt) {
$page.remove();
nextAnimation();
}).trigger(noAnimEnd);
self.showMonth(currentMonth);
});
$calendar.bind("resetDates", function (evt) {
setDate(startDateString, null);
setDate(endDateString, null);
});
$days.bind(tap, dateSelected);
self.showMonth(currentMonth);
}
self.setDates = function(start, end) {
setDate(startDateString, start && end ? new Date(Math.min(start, end)) : start);
!singleDate && setDate(endDateString, start && end ?
(start.getTime() != end.getTime() ? new Date(Math.max(start, end)) : null) : end);
}
self.showMonth = function (date) {
minDate = new Date(Math.max(minDate, today));
if (!!dateInfo) {
$month.text(dateInfo.months.names["long"][date.getMonth()] + " " + date.getFullYear());
for (var i = 0, maxI = $weekdays.length; i < maxI; i++) {
$weekdays.eq(getDay(i)).text(dateInfo.days.names.min[i]);
}
}
var beforeMinDate = minDate > date.clone().moveToLastDayOfMonth();
var includesToday = !beforeMinDate && (minDate >= date.clone().moveToFirstDayOfMonth());
var minDay = minDate.getDate();
$days.addClass("noTransition").removeClass("inactive");
$rows.removeClass("last").removeClass("hidden");
for (var firstDay = getDay(date.clone().moveToFirstDayOfMonth().getDay()) - 1, lastDay = firstDay + date.clone().moveToLastDayOfMonth().getDate(), i = 0, maxI = $days.length; i < maxI; i++) {
var isDay = (i > firstDay) && (i <= lastDay);
var $day = $days.eq(i).text(isDay ? ("" + (i - firstDay)) : "");
if (isDay && (beforeMinDate || (includesToday && (i - firstDay < minDay)))) {
$day.addClass("inactive");
}
if (includesToday && today.getDate() == (i - firstDay)) {
$day.addClass("today");
}
if (i == lastDay) {
$day.closest("tr").addClass("last").next().addClass("hidden").next().addClass("hidden");
}
}
setTimeout(function() {
$days.removeClass("noTransition");
}, 0);
drawSelection();
}
}
})()
The code you posted turns any div with a class of jsCalendar into a jsCalendar.
You're going to want to assign an individual id to any jsCalendar object you want to access the dates of.
You should be able to see what 2 dates the user has selected by calling the data function on the jsCalendar object. For instance, if you had a jsCalendar with an id of jsCalendar1:
var startDate = $("#jsCalendar1").data("startdate");
var endDate = $("#jsCalendar1").data("enddate");
alert("Calendar 1 has a start date of " + startDate + " and an end date of " + endDate + ".");
Make sure you put this code somewhere appropriate, such as in a function that isn't called until after a user has selected a start and end date.
Here's a working jsFiddle.

Categories