+/*\r
+ * MultiDatesPicker v1.6.1\r
+ * http://multidatespickr.sourceforge.net/\r
+ * \r
+ * Copyright 2011, Luca Lauretta\r
+ * Dual licensed under the MIT or GPL version 2 licenses.\r
+ */\r
+(function( $ ){\r
+ $.extend($.ui, { multiDatesPicker: { version: "1.6.1" } });\r
+ \r
+ $.fn.multiDatesPicker = function(method) {\r
+ var mdp_arguments = arguments;\r
+ var ret = this;\r
+ var today_date = new Date();\r
+ var day_zero = new Date(0);\r
+ var mdp_events = {};\r
+ \r
+ function removeDate(date, type) {\r
+ if(!type) type = 'picked';\r
+ date = dateConvert.call(this, date);\r
+ for(var i in this.multiDatesPicker.dates[type])\r
+ if(!methods.compareDates(this.multiDatesPicker.dates[type][i], date))\r
+ return this.multiDatesPicker.dates[type].splice(i, 1).pop();\r
+ }\r
+ function removeIndex(index, type) {\r
+ if(!type) type = 'picked';\r
+ return this.multiDatesPicker.dates[type].splice(index, 1).pop();\r
+ }\r
+ function addDate(date, type, no_sort) {\r
+ if(!type) type = 'picked';\r
+ date = dateConvert.call(this, date);\r
+ \r
+ // @todo: use jQuery UI datepicker method instead\r
+ date.setHours(0);\r
+ date.setMinutes(0);\r
+ date.setSeconds(0);\r
+ date.setMilliseconds(0);\r
+ \r
+ if (methods.gotDate.call(this, date, type) === false) {\r
+ this.multiDatesPicker.dates[type].push(date);\r
+ if(!no_sort) this.multiDatesPicker.dates[type].sort(methods.compareDates);\r
+ } \r
+ }\r
+ function sortDates(type) {\r
+ if(!type) type = 'picked';\r
+ this.multiDatesPicker.dates[type].sort(methods.compareDates);\r
+ }\r
+ function dateConvert(date, desired_type, date_format) {\r
+ if(!desired_type) desired_type = 'object';/*\r
+ if(!date_format && (typeof date == 'string')) {\r
+ date_format = $(this).datepicker('option', 'dateFormat');\r
+ if(!date_format) date_format = $.datepicker._defaults.dateFormat;\r
+ }\r
+ */\r
+ return methods.dateConvert.call(this, date, desired_type, date_format);\r
+ }\r
+ \r
+ var methods = {\r
+ init : function( options ) {\r
+ var $this = $(this);\r
+ this.multiDatesPicker.changed = false;\r
+ \r
+ var mdp_events = {\r
+ beforeShow: function(input, inst) {\r
+ this.multiDatesPicker.changed = false;\r
+ if(this.multiDatesPicker.originalBeforeShow) \r
+ this.multiDatesPicker.originalBeforeShow.call(this, input, inst);\r
+ },\r
+ onSelect : function(dateText, inst) {\r
+ var $this = $(this);\r
+ this.multiDatesPicker.changed = true;\r
+ \r
+ if (dateText) {\r
+ $this.multiDatesPicker('toggleDate', dateText);\r
+ }\r
+ \r
+ if (this.multiDatesPicker.mode == 'normal' && this.multiDatesPicker.dates.picked.length > 0 && this.multiDatesPicker.pickableRange) {\r
+ var min_date = this.multiDatesPicker.dates.picked[0],\r
+ max_date = new Date(min_date.getTime());\r
+ \r
+ methods.sumDays(max_date, this.multiDatesPicker.pickableRange-1);\r
+ \r
+ // counts the number of disabled dates in the range\r
+ if(this.multiDatesPicker.adjustRangeToDisabled) {\r
+ var c_disabled, \r
+ disabled = this.multiDatesPicker.dates.disabled.slice(0);\r
+ do {\r
+ c_disabled = 0;\r
+ for(var i = 0; i < disabled.length; i++) {\r
+ if(disabled[i].getTime() <= max_date.getTime()) {\r
+ if((min_date.getTime() <= disabled[i].getTime()) && (disabled[i].getTime() <= max_date.getTime()) ) {\r
+ c_disabled++;\r
+ }\r
+ disabled.splice(i, 1);\r
+ i--;\r
+ }\r
+ }\r
+ max_date.setDate(max_date.getDate() + c_disabled);\r
+ } while(c_disabled != 0);\r
+ }\r
+ \r
+ if(this.multiDatesPicker.maxDate && (max_date > this.multiDatesPicker.maxDate))\r
+ max_date = this.multiDatesPicker.maxDate;\r
+ \r
+ $this\r
+ .datepicker("option", "minDate", min_date)\r
+ .datepicker("option", "maxDate", max_date);\r
+ } else {\r
+ $this\r
+ .datepicker("option", "minDate", this.multiDatesPicker.minDate)\r
+ .datepicker("option", "maxDate", this.multiDatesPicker.maxDate);\r
+ }\r
+ \r
+ if(this.tagName == 'INPUT') { // for inputs\r
+ $this.val(\r
+ $this.multiDatesPicker('getDates', 'string')\r
+ );\r
+ }\r
+ \r
+ if(this.multiDatesPicker.originalOnSelect && dateText)\r
+ this.multiDatesPicker.originalOnSelect.call(this, dateText, inst);\r
+ \r
+ // thanks to bibendus83 -> http://sourceforge.net/tracker/?func=detail&atid=1495384&aid=3403159&group_id=358205\r
+ if ($this.datepicker('option', 'altField') != undefined && $this.datepicker('option', 'altField') != "") {\r
+ $($this.datepicker('option', 'altField')).val(\r
+ $this.multiDatesPicker('getDates', 'string')\r
+ );\r
+ }\r
+ },\r
+ beforeShowDay : function(date) {\r
+ var $this = $(this),\r
+ gotThisDate = $this.multiDatesPicker('gotDate', date) !== false,\r
+ isDisabledCalendar = $this.datepicker('option', 'disabled'),\r
+ isDisabledDate = $this.multiDatesPicker('gotDate', date, 'disabled') !== false,\r
+ areAllSelected = this.multiDatesPicker.maxPicks == this.multiDatesPicker.dates.picked.length;\r
+ \r
+ var custom = [true, ''];\r
+ if(this.multiDatesPicker.originalBeforeShowDay)\r
+ custom = this.multiDatesPicker.originalBeforeShowDay.call(this, date);\r
+ \r
+ var highlight_class = gotThisDate ? 'ui-state-highlight' : custom[1];\r
+ var highlight_class = (gotThisDate ? 'ui-state-highlight' : '') + ((custom[1] && gotThisDate) ? ' ' : '') + custom[1];\r
+ var selectable_date = !(isDisabledCalendar || isDisabledDate || (areAllSelected && !highlight_class));\r
+ custom[0] = selectable_date && custom[0];\r
+ custom[1] = highlight_class;\r
+ return custom;\r
+ },\r
+ onClose: function(dateText, inst) {\r
+ if(this.tagName == 'INPUT' && this.multiDatesPicker.changed) {\r
+ $(inst.dpDiv[0]).stop(false,true);\r
+ setTimeout('$("#'+inst.id+'").datepicker("show")',50);\r
+ }\r
+ if(this.multiDatesPicker.originalOnClose) this.multiDatesPicker.originalOnClose.call(this, dateText, inst);\r
+ }\r
+ };\r
+ \r
+ if(options) {\r
+ this.multiDatesPicker.originalBeforeShow = options.beforeShow;\r
+ this.multiDatesPicker.originalOnSelect = options.onSelect;\r
+ this.multiDatesPicker.originalBeforeShowDay = options.beforeShowDay;\r
+ this.multiDatesPicker.originalOnClose = options.onClose;\r
+ \r
+ $this.datepicker(options);\r
+ \r
+ this.multiDatesPicker.minDate = $.datepicker._determineDate(this, options.minDate, null);\r
+ this.multiDatesPicker.maxDate = $.datepicker._determineDate(this, options.maxDate, null);\r
+ \r
+ if(options.addDates) methods.addDates.call(this, options.addDates);\r
+ if(options.addDisabledDates)\r
+ methods.addDates.call(this, options.addDisabledDates, 'disabled');\r
+ \r
+ methods.setMode.call(this, options);\r
+ } else {\r
+ $this.datepicker();\r
+ }\r
+ \r
+ $this.datepicker('option', mdp_events);\r
+ \r
+ if(this.tagName == 'INPUT') $this.val($this.multiDatesPicker('getDates', 'string'));\r
+ \r
+ // Fixes the altField filled with defaultDate by default\r
+ var altFieldOption = $this.datepicker('option', 'altField');\r
+ if (altFieldOption) $(altFieldOption).val($this.multiDatesPicker('getDates', 'string'));\r
+ },\r
+ compareDates : function(date1, date2) {\r
+ date1 = dateConvert.call(this, date1);\r
+ date2 = dateConvert.call(this, date2);\r
+ // return > 0 means date1 is later than date2 \r
+ // return == 0 means date1 is the same day as date2 \r
+ // return < 0 means date1 is earlier than date2 \r
+ var diff = date1.getFullYear() - date2.getFullYear();\r
+ if(!diff) {\r
+ diff = date1.getMonth() - date2.getMonth();\r
+ if(!diff) \r
+ diff = date1.getDate() - date2.getDate();\r
+ }\r
+ return diff;\r
+ },\r
+ sumDays : function( date, n_days ) {\r
+ var origDateType = typeof date;\r
+ obj_date = dateConvert.call(this, date);\r
+ obj_date.setDate(obj_date.getDate() + n_days);\r
+ return dateConvert.call(this, obj_date, origDateType);\r
+ },\r
+ dateConvert : function( date, desired_format, dateFormat ) {\r
+ var from_format = typeof date;\r
+ \r
+ if(from_format == desired_format) {\r
+ if(from_format == 'object') {\r
+ try {\r
+ date.getTime();\r
+ } catch (e) {\r
+ $.error('Received date is in a non supported format!');\r
+ return false;\r
+ }\r
+ }\r
+ return date;\r
+ }\r
+ \r
+ var $this = $(this);\r
+ if(typeof date == 'undefined') date = new Date(0);\r
+ \r
+ if(desired_format != 'string' && desired_format != 'object' && desired_format != 'number')\r
+ $.error('Date format "'+ desired_format +'" not supported!');\r
+ \r
+ if(!dateFormat) {\r
+ dateFormat = $.datepicker._defaults.dateFormat;\r
+ \r
+ // thanks to bibendus83 -> http://sourceforge.net/tracker/index.php?func=detail&aid=3213174&group_id=358205&atid=1495382\r
+ var dp_dateFormat = $this.datepicker('option', 'dateFormat');\r
+ if (dp_dateFormat) {\r
+ dateFormat = dp_dateFormat;\r
+ }\r
+ }\r
+ \r
+ // converts to object as a neutral format\r
+ switch(from_format) {\r
+ case 'object': break;\r
+ case 'string': date = $.datepicker.parseDate(dateFormat, date); break;\r
+ case 'number': date = new Date(date); break;\r
+ default: $.error('Conversion from "'+ desired_format +'" format not allowed on jQuery.multiDatesPicker');\r
+ }\r
+ // then converts to the desired format\r
+ switch(desired_format) {\r
+ case 'object': return date;\r
+ case 'string': return $.datepicker.formatDate(dateFormat, date);\r
+ case 'number': return date.getTime();\r
+ default: $.error('Conversion to "'+ desired_format +'" format not allowed on jQuery.multiDatesPicker');\r
+ }\r
+ return false;\r
+ },\r
+ gotDate : function( date, type ) {\r
+ if(!type) type = 'picked';\r
+ for(var i = 0; i < this.multiDatesPicker.dates[type].length; i++) {\r
+ if(methods.compareDates.call(this, this.multiDatesPicker.dates[type][i], date) === 0) {\r
+ return i;\r
+ }\r
+ }\r
+ return false;\r
+ },\r
+ getDates : function( format, type ) {\r
+ if(!format) format = 'string';\r
+ if(!type) type = 'picked';\r
+ switch (format) {\r
+ case 'object':\r
+ return this.multiDatesPicker.dates[type];\r
+ case 'string':\r
+ case 'number':\r
+ var o_dates = new Array();\r
+ for(var i in this.multiDatesPicker.dates[type])\r
+ o_dates.push(\r
+ dateConvert.call(\r
+ this, \r
+ this.multiDatesPicker.dates[type][i], \r
+ format\r
+ )\r
+ );\r
+ return o_dates;\r
+ \r
+ default: $.error('Format "'+format+'" not supported!');\r
+ }\r
+ },\r
+ addDates : function( dates, type ) {\r
+ if(dates.length > 0) {\r
+ if(!type) type = 'picked';\r
+ switch(typeof dates) {\r
+ case 'object':\r
+ case 'array':\r
+ if(dates.length) {\r
+ for(var i in dates)\r
+ if (typeof dates[i] != "function")\r
+ addDate.call(this, dates[i], type, true);\r
+ sortDates.call(this, type);\r
+ break;\r
+ } // else does the same as 'string'\r
+ case 'string':\r
+ case 'number':\r
+ addDate.call(this, dates, type);\r
+ break;\r
+ default: \r
+ $.error('Date format "'+ typeof dates +'" not allowed on jQuery.multiDatesPicker');\r
+ }\r
+ $(this).datepicker('refresh');\r
+ } else {\r
+ $.error('Empty array of dates received.');\r
+ }\r
+ },\r
+ removeDates : function( dates, type ) {\r
+ if(!type) type = 'picked';\r
+ var removed = [];\r
+ if (Object.prototype.toString.call(dates) === '[object Array]') {\r
+ for(var i in dates.sort(function(a,b){return b-a})) {\r
+ removed.push(removeDate.call(this, dates[i], type));\r
+ }\r
+ } else {\r
+ removed.push(removeDate.call(this, dates, type));\r
+ }\r
+ $(this).datepicker('refresh');\r
+ return removed;\r
+ },\r
+ removeIndexes : function( indexes, type ) {\r
+ if(!type) type = 'picked';\r
+ var removed = [];\r
+ if (Object.prototype.toString.call(indexes) === '[object Array]') {\r
+ for(var i in indexes.sort(function(a,b){return b-a})) {\r
+ removed.push(removeIndex.call(this, indexes[i], type));\r
+ }\r
+ } else {\r
+ removed.push(removeIndex.call(this, indexes, type));\r
+ }\r
+ $(this).datepicker('refresh');\r
+ return removed;\r
+ },\r
+ resetDates : function ( type ) {\r
+ if(!type) type = 'picked';\r
+ this.multiDatesPicker.dates[type] = [];\r
+ $(this).datepicker('refresh');\r
+ },\r
+ toggleDate : function( date, type ) {\r
+ if(!type) type = 'picked';\r
+ \r
+ switch(this.multiDatesPicker.mode) {\r
+ case 'daysRange':\r
+ this.multiDatesPicker.dates[type] = []; // deletes all picked/disabled dates\r
+ var end = this.multiDatesPicker.autoselectRange[1];\r
+ var begin = this.multiDatesPicker.autoselectRange[0];\r
+ if(end < begin) { // switch\r
+ end = this.multiDatesPicker.autoselectRange[0];\r
+ begin = this.multiDatesPicker.autoselectRange[1];\r
+ }\r
+ for(var i = begin; i < end; i++) \r
+ methods.addDates.call(this, methods.sumDays(date, i), type);\r
+ break;\r
+ default:\r
+ if(methods.gotDate.call(this, date) === false) // adds dates\r
+ methods.addDates.call(this, date, type);\r
+ else // removes dates\r
+ methods.removeDates.call(this, date, type);\r
+ break;\r
+ }\r
+ }, \r
+ setMode : function( options ) {\r
+ var $this = $(this);\r
+ if(options.mode) this.multiDatesPicker.mode = options.mode;\r
+ \r
+ switch(this.multiDatesPicker.mode) {\r
+ case 'normal':\r
+ for(option in options)\r
+ switch(option) {\r
+ case 'maxPicks':\r
+ case 'minPicks':\r
+ case 'pickableRange':\r
+ case 'adjustRangeToDisabled':\r
+ this.multiDatesPicker[option] = options[option];\r
+ break;\r
+ //default: $.error('Option ' + option + ' ignored for mode "'.options.mode.'".');\r
+ }\r
+ break;\r
+ case 'daysRange':\r
+ case 'weeksRange':\r
+ var mandatory = 1;\r
+ for(option in options)\r
+ switch(option) {\r
+ case 'autoselectRange':\r
+ mandatory--;\r
+ case 'pickableRange':\r
+ case 'adjustRangeToDisabled':\r
+ this.multiDatesPicker[option] = options[option];\r
+ break;\r
+ //default: $.error('Option ' + option + ' does not exist for setMode on jQuery.multiDatesPicker');\r
+ }\r
+ if(mandatory > 0) $.error('Some mandatory options not specified!');\r
+ break;\r
+ }\r
+ \r
+ /*\r
+ if(options.pickableRange) {\r
+ $this.datepicker("option", "maxDate", options.pickableRange);\r
+ $this.datepicker("option", "minDate", this.multiDatesPicker.minDate);\r
+ }\r
+ */\r
+ \r
+ if(mdp_events.onSelect)\r
+ mdp_events.onSelect();\r
+ $this.datepicker('refresh');\r
+ }\r
+ };\r
+ \r
+ this.each(function() {\r
+ if (!this.multiDatesPicker) {\r
+ this.multiDatesPicker = {\r
+ dates: {\r
+ picked: [],\r
+ disabled: []\r
+ },\r
+ mode: 'normal',\r
+ adjustRangeToDisabled: true\r
+ };\r
+ }\r
+ \r
+ if(methods[method]) {\r
+ var exec_result = methods[method].apply(this, Array.prototype.slice.call(mdp_arguments, 1));\r
+ switch(method) {\r
+ case 'getDates':\r
+ case 'removeDates':\r
+ case 'gotDate':\r
+ case 'sumDays':\r
+ case 'compareDates':\r
+ case 'dateConvert':\r
+ ret = exec_result;\r
+ }\r
+ return exec_result;\r
+ } else if( typeof method === 'object' || ! method ) {\r
+ return methods.init.apply(this, mdp_arguments);\r
+ } else {\r
+ $.error('Method ' + method + ' does not exist on jQuery.multiDatesPicker');\r
+ }\r
+ return false;\r
+ });\r
+ \r
+ if(method != 'gotDate' && method != 'getDates') {\r
+ aaaa = 1;\r
+ }\r
+ \r
+ return ret;\r
+ };\r
+\r
+ var PROP_NAME = 'multiDatesPicker';\r
+ var dpuuid = new Date().getTime();\r
+ var instActive;\r
+\r
+ $.multiDatesPicker = {version: false};\r
+ //$.multiDatesPicker = new MultiDatesPicker(); // singleton instance\r
+ $.multiDatesPicker.initialized = false;\r
+ $.multiDatesPicker.uuid = new Date().getTime();\r
+ $.multiDatesPicker.version = $.ui.multiDatesPicker.version;\r
+\r
+ // Workaround for #4055\r
+ // Add another global to avoid noConflict issues with inline event handlers\r
+ window['DP_jQuery_' + dpuuid] = $;\r
+})( jQuery );
\ No newline at end of file