root/trunk/Wierszowki/Wierszowki.Web/Scripts/jquery.datePicker.js @ 900

Wersja 752, 41.2 KB (wprowadzona przez marek, 17 years temu)

wiersz

Line 
1/**
2 * Copyright (c) 2008 Kelvin Luck (http://www.kelvinluck.com/)
3 * Dual licensed under the MIT (http://www.opensource.org/licenses/mit-license.php)
4 * and GPL (http://www.opensource.org/licenses/gpl-license.php) licenses.
5 *
6 * $Id: jquery.datePicker.js 52 2009-02-09 06:16:11Z kelvin.luck $
7 **/
8
9(function($){
10   
11        $.fn.extend({
12/**
13 * Render a calendar table into any matched elements.
14 *
15 * @param Object s (optional) Customize your calendars.
16 * @option Number month The month to render (NOTE that months are zero based). Default is today's month.
17 * @option Number year The year to render. Default is today's year.
18 * @option Function renderCallback A reference to a function that is called as each cell is rendered and which can add classes and event listeners to the created nodes. Default is no callback.
19 * @option Number showHeader Whether or not to show the header row, possible values are: $.dpConst.SHOW_HEADER_NONE (no header), $.dpConst.SHOW_HEADER_SHORT (first letter of each day) and $.dpConst.SHOW_HEADER_LONG (full name of each day). Default is $.dpConst.SHOW_HEADER_SHORT.
20 * @option String hoverClass The class to attach to each cell when you hover over it (to allow you to use hover effects in IE6 which doesn't support the :hover pseudo-class on elements other than links). Default is dp-hover. Pass false if you don't want a hover class.
21 * @type jQuery
22 * @name renderCalendar
23 * @cat plugins/datePicker
24 * @author Kelvin Luck (http://www.kelvinluck.com/)
25 *
26 * @example $('#calendar-me').renderCalendar({month:0, year:2007});
27 * @desc Renders a calendar displaying January 2007 into the element with an id of calendar-me.
28 *
29 * @example
30 * var testCallback = function($td, thisDate, month, year)
31 * {
32 * if ($td.is('.current-month') && thisDate.getDay() == 4) {
33 *              var d = thisDate.getDate();
34 *              $td.bind(
35 *                      'click',
36 *                      function()
37 *                      {
38 *                              alert('You clicked on ' + d + '/' + (Number(month)+1) + '/' + year);
39 *                      }
40 *              ).addClass('thursday');
41 *      } else if (thisDate.getDay() == 5) {
42 *              $td.html('Friday the ' + $td.html() + 'th');
43 *      }
44 * }
45 * $('#calendar-me').renderCalendar({month:0, year:2007, renderCallback:testCallback});
46 *
47 * @desc Renders a calendar displaying January 2007 into the element with an id of calendar-me. Every Thursday in the current month has a class of "thursday" applied to it, is clickable and shows an alert when clicked. Every Friday on the calendar has the number inside replaced with text.
48 **/
49                renderCalendar  :   function(s)
50                {
51                        var dc = function(a)
52                        {
53                                return document.createElement(a);
54                        };
55
56                        s = $.extend({}, $.fn.datePicker.defaults, s);
57                       
58                        if (s.showHeader != $.dpConst.SHOW_HEADER_NONE) {
59                                var headRow = $(dc('tr'));
60                                for (var i=Date.firstDayOfWeek; i<Date.firstDayOfWeek+7; i++) {
61                                        var weekday = i%7;
62                                        var day = Date.dayNames[weekday];
63                                        headRow.append(
64                                                jQuery(dc('th')).attr({'scope':'col', 'abbr':day, 'title':day, 'class':(weekday == 0 || weekday == 6 ? 'weekend' : 'weekday')}).html(s.showHeader == $.dpConst.SHOW_HEADER_SHORT ? day.substr(0, 1) : day)
65                                        );
66                                }
67                        };
68                       
69                        var calendarTable = $(dc('table'))
70                                                                        .attr(
71                                                                                {
72                                                                                        'cellspacing':2,
73                                                                                        'className':'jCalendar'
74                                                                                }
75                                                                        )
76                                                                        .append(
77                                                                                (s.showHeader != $.dpConst.SHOW_HEADER_NONE ?
78                                                                                        $(dc('thead'))
79                                                                                                .append(headRow)
80                                                                                        :
81                                                                                        dc('thead')
82                                                                                )
83                                                                        );
84                        var tbody = $(dc('tbody'));
85                       
86                        var today = (new Date()).zeroTime();
87                       
88                        var month = s.month == undefined ? today.getMonth() : s.month;
89                        var year = s.year || today.getFullYear();
90                       
91                        var currentDate = new Date(year, month, 1);
92                       
93                       
94                        var firstDayOffset = Date.firstDayOfWeek - currentDate.getDay() + 1;
95                        if (firstDayOffset > 1) firstDayOffset -= 7;
96                        var weeksToDraw = Math.ceil(( (-1*firstDayOffset+1) + currentDate.getDaysInMonth() ) /7);
97                        currentDate.addDays(firstDayOffset-1);
98                       
99                        var doHover = function(firstDayInBounds)
100                        {
101                                return function()
102                                {
103                                        if (s.hoverClass) {
104                                                var $this = $(this);
105                                                if (!s.selectWeek) {
106                                                        $this.addClass(s.hoverClass);
107                                                } else if (firstDayInBounds && !$this.is('.disabled')) {
108                                                        $this.parent().addClass('activeWeekHover');
109                                                }
110                                        }
111                                }
112                        };
113                        var unHover = function()
114                        {
115                                if (s.hoverClass) {
116                                        var $this = $(this);
117                                        $this.removeClass(s.hoverClass);
118                                        $this.parent().removeClass('activeWeekHover');
119                                }
120                        };     
121                       
122                        var w = 0;
123                        while (w++<weeksToDraw) {
124                                var r = jQuery(dc('tr'));
125                                var firstDayInBounds = s.dpController ? currentDate > s.dpController.startDate : false;
126                                for (var i=0; i<7; i++) {
127                                        var thisMonth = currentDate.getMonth() == month;
128                                        var d = $(dc('td'))
129                                                                .text(currentDate.getDate() + '')
130                                                                .attr('className', (thisMonth ? 'current-month ' : 'other-month ') +
131                                                                                                        (currentDate.isWeekend() ? 'weekend ' : 'weekday ') +
132                                                                                                        (thisMonth && currentDate.getTime() == today.getTime() ? 'today ' : '')
133                                                                )
134                                                                .data('datePickerDate', currentDate.asString())
135                                                                .hover(doHover(firstDayInBounds), unHover)
136                                                        ;
137                                        r.append(d);
138                                        if (s.renderCallback) {
139                                                s.renderCallback(d, currentDate, month, year);
140                                        }
141                                        currentDate.addDays(1);
142                                }
143                                tbody.append(r);
144                        }
145                        calendarTable.append(tbody);
146                       
147                        return this.each(
148                                function()
149                                {
150                                        $(this).empty().append(calendarTable);
151                                }
152                        );
153                },
154/**
155 * Create a datePicker associated with each of the matched elements.
156 *
157 * The matched element will receive a few custom events with the following signatures:
158 *
159 * dateSelected(event, date, $td, status)
160 * Triggered when a date is selected. event is a reference to the event, date is the Date selected, $td is a jquery object wrapped around the TD that was clicked on and status is whether the date was selected (true) or deselected (false)
161 *
162 * dpClosed(event, selected)
163 * Triggered when the date picker is closed. event is a reference to the event and selected is an Array containing Date objects.
164 *
165 * dpMonthChanged(event, displayedMonth, displayedYear)
166 * Triggered when the month of the popped up calendar is changed. event is a reference to the event, displayedMonth is the number of the month now displayed (zero based) and displayedYear is the year of the month.
167 *
168 * dpDisplayed(event, $datePickerDiv)
169 * Triggered when the date picker is created. $datePickerDiv is the div containing the date picker. Use this event to add custom content/ listeners to the popped up date picker.
170 *
171 * @param Object s (optional) Customize your date pickers.
172 * @option Number month The month to render when the date picker is opened (NOTE that months are zero based). Default is today's month.
173 * @option Number year The year to render when the date picker is opened. Default is today's year.
174 * @option String startDate The first date date can be selected.
175 * @option String endDate The last date that can be selected.
176 * @option Boolean inline Whether to create the datePicker as inline (e.g. always on the page) or as a model popup. Default is false (== modal popup)
177 * @option Boolean createButton Whether to create a .dp-choose-date anchor directly after the matched element which when clicked will trigger the showing of the date picker. Default is true.
178 * @option Boolean showYearNavigation Whether to display buttons which allow the user to navigate through the months a year at a time. Default is true.
179 * @option Boolean closeOnSelect Whether to close the date picker when a date is selected. Default is true.
180 * @option Boolean displayClose Whether to create a "Close" button within the date picker popup. Default is false.
181 * @option Boolean selectMultiple Whether a user should be able to select multiple dates with this date picker. Default is false.
182 * @option Number numSelectable The maximum number of dates that can be selected where selectMultiple is true. Default is a very high number.
183 * @option Boolean clickInput If the matched element is an input type="text" and this option is true then clicking on the input will cause the date picker to appear.
184 * @option Boolean rememberViewedMonth Whether the datePicker should remember the last viewed month and open on it. If false then the date picker will always open with the month for the first selected date visible.
185 * @option Boolean selectWeek Whether to select a complete week at a time...
186 * @option Number verticalPosition The vertical alignment of the popped up date picker to the matched element. One of $.dpConst.POS_TOP and $.dpConst.POS_BOTTOM. Default is $.dpConst.POS_TOP.
187 * @option Number horizontalPosition The horizontal alignment of the popped up date picker to the matched element. One of $.dpConst.POS_LEFT and $.dpConst.POS_RIGHT.
188 * @option Number verticalOffset The number of pixels offset from the defined verticalPosition of this date picker that it should pop up in. Default in 0.
189 * @option Number horizontalOffset The number of pixels offset from the defined horizontalPosition of this date picker that it should pop up in. Default in 0.
190 * @option (Function|Array) renderCallback A reference to a function (or an array of seperate functions) that is called as each cell is rendered and which can add classes and event listeners to the created nodes. Each callback function will receive four arguments; a jquery object wrapping the created TD, a Date object containing the date this TD represents, a number giving the currently rendered month and a number giving the currently rendered year. Default is no callback.
191 * @option String hoverClass The class to attach to each cell when you hover over it (to allow you to use hover effects in IE6 which doesn't support the :hover pseudo-class on elements other than links). Default is dp-hover. Pass false if you don't want a hover class.
192 * @type jQuery
193 * @name datePicker
194 * @cat plugins/datePicker
195 * @author Kelvin Luck (http://www.kelvinluck.com/)
196 *
197 * @example $('input.date-picker').datePicker();
198 * @desc Creates a date picker button next to all matched input elements. When the button is clicked on the value of the selected date will be placed in the corresponding input (formatted according to Date.format).
199 *
200 * @example demo/index.html
201 * @desc See the projects homepage for many more complex examples...
202 **/
203                datePicker : function(s)
204                {                       
205                        if (!$.event._dpCache) $.event._dpCache = [];
206                       
207                        // initialise the date picker controller with the relevant settings...
208                        s = $.extend({}, $.fn.datePicker.defaults, s);
209                       
210                        return this.each(
211                                function()
212                                {
213                                        var $this = $(this);
214                                        var alreadyExists = true;
215                                       
216                                        if (!this._dpId) {
217                                                this._dpId = $.event.guid++;
218                                                $.event._dpCache[this._dpId] = new DatePicker(this);
219                                                alreadyExists = false;
220                                        }
221                                       
222                                        if (s.inline) {
223                                                s.createButton = false;
224                                                s.displayClose = false;
225                                                s.closeOnSelect = false;
226                                                $this.empty();
227                                        }
228                                       
229                                        var controller = $.event._dpCache[this._dpId];
230                                       
231                                        controller.init(s);
232                                       
233                                        if (!alreadyExists && s.createButton) {
234                                                // create it!
235                                                controller.button = $('<a href="#" class="dp-choose-date" title="' + $.dpText.TEXT_CHOOSE_DATE + '">' + $.dpText.TEXT_CHOOSE_DATE + '</a>')
236                                                                .bind(
237                                                                        'click',
238                                                                        function()
239                                                                        {
240                                                                                $this.dpDisplay(this);
241                                                                                this.blur();
242                                                                                return false;
243                                                                        }
244                                                                );
245                                                $this.after(controller.button);
246                                        }
247                                       
248                                        if (!alreadyExists && $this.is(':text')) {
249                                                $this
250                                                        .bind(
251                                                                'dateSelected',
252                                                                function(e, selectedDate, $td)
253                                                                {
254                                                                        this.value = selectedDate.asString();
255                                                                }
256                                                        ).bind(
257                                                                'change',
258                                                                function()
259                                                                {
260                                                                        if (this.value != '') {
261                                                                                var d = Date.fromString(this.value);
262                                                                                if (d) {
263                                                                                        controller.setSelected(d, true, true);
264                                                                                }
265                                                                        }
266                                                                }
267                                                        );
268                                                if (s.clickInput) {
269                                                        $this.bind(
270                                                                'click',
271                                                                function()
272                                                                {
273                                                                        $this.dpDisplay();
274                                                                }
275                                                        );
276                                                }
277                                                var d = Date.fromString(this.value);
278                                                if (this.value != '' && d) {
279                                                        controller.setSelected(d, true, true);
280                                                }
281                                        }
282                                       
283                                        $this.addClass('dp-applied');
284                                       
285                                }
286                        )
287                },
288/**
289 * Disables or enables this date picker
290 *
291 * @param Boolean s Whether to disable (true) or enable (false) this datePicker
292 * @type jQuery
293 * @name dpSetDisabled
294 * @cat plugins/datePicker
295 * @author Kelvin Luck (http://www.kelvinluck.com/)
296 *
297 * @example $('.date-picker').datePicker();
298 * $('.date-picker').dpSetDisabled(true);
299 * @desc Prevents this date picker from displaying and adds a class of dp-disabled to it (and it's associated button if it has one) for styling purposes. If the matched element is an input field then it will also set the disabled attribute to stop people directly editing the field.
300 **/
301                dpSetDisabled : function(s)
302                {
303                        return _w.call(this, 'setDisabled', s);
304                },
305/**
306 * Updates the first selectable date for any date pickers on any matched elements.
307 *
308 * @param String d A string representing the first selectable date (formatted according to Date.format).
309 * @type jQuery
310 * @name dpSetStartDate
311 * @cat plugins/datePicker
312 * @author Kelvin Luck (http://www.kelvinluck.com/)
313 *
314 * @example $('.date-picker').datePicker();
315 * $('.date-picker').dpSetStartDate('01/01/2000');
316 * @desc Creates a date picker associated with all elements with a class of "date-picker" then sets the first selectable date for each of these to the first day of the millenium.
317 **/
318                dpSetStartDate : function(d)
319                {
320                        return _w.call(this, 'setStartDate', d);
321                },
322/**
323 * Updates the last selectable date for any date pickers on any matched elements.
324 *
325 * @param String d A string representing the last selectable date (formatted according to Date.format).
326 * @type jQuery
327 * @name dpSetEndDate
328 * @cat plugins/datePicker
329 * @author Kelvin Luck (http://www.kelvinluck.com/)
330 *
331 * @example $('.date-picker').datePicker();
332 * $('.date-picker').dpSetEndDate('01/01/2010');
333 * @desc Creates a date picker associated with all elements with a class of "date-picker" then sets the last selectable date for each of these to the first Janurary 2010.
334 **/
335                dpSetEndDate : function(d)
336                {
337                        return _w.call(this, 'setEndDate', d);
338                },
339/**
340 * Gets a list of Dates currently selected by this datePicker. This will be an empty array if no dates are currently selected or NULL if there is no datePicker associated with the matched element.
341 *
342 * @type Array
343 * @name dpGetSelected
344 * @cat plugins/datePicker
345 * @author Kelvin Luck (http://www.kelvinluck.com/)
346 *
347 * @example $('.date-picker').datePicker();
348 * alert($('.date-picker').dpGetSelected());
349 * @desc Will alert an empty array (as nothing is selected yet)
350 **/
351                dpGetSelected : function()
352                {
353                        var c = _getController(this[0]);
354                        if (c) {
355                                return c.getSelected();
356                        }
357                        return null;
358                },
359/**
360 * Selects or deselects a date on any matched element's date pickers. Deselcting is only useful on date pickers where selectMultiple==true. Selecting will only work if the passed date is within the startDate and endDate boundries for a given date picker.
361 *
362 * @param String d A string representing the date you want to select (formatted according to Date.format).
363 * @param Boolean v Whether you want to select (true) or deselect (false) this date. Optional - default = true.
364 * @param Boolean m Whether you want the date picker to open up on the month of this date when it is next opened. Optional - default = true.
365 * @type jQuery
366 * @name dpSetSelected
367 * @cat plugins/datePicker
368 * @author Kelvin Luck (http://www.kelvinluck.com/)
369 *
370 * @example $('.date-picker').datePicker();
371 * $('.date-picker').dpSetSelected('01/01/2010');
372 * @desc Creates a date picker associated with all elements with a class of "date-picker" then sets the selected date on these date pickers to the first Janurary 2010. When the date picker is next opened it will display Janurary 2010.
373 **/
374                dpSetSelected : function(d, v, m)
375                {
376                        if (v == undefined) v=true;
377                        if (m == undefined) m=true;
378                        return _w.call(this, 'setSelected', Date.fromString(d), v, m, true);
379                },
380/**
381 * Sets the month that will be displayed when the date picker is next opened. If the passed month is before startDate then the month containing startDate will be displayed instead. If the passed month is after endDate then the month containing the endDate will be displayed instead.
382 *
383 * @param Number m The month you want the date picker to display. Optional - defaults to the currently displayed month.
384 * @param Number y The year you want the date picker to display. Optional - defaults to the currently displayed year.
385 * @type jQuery
386 * @name dpSetDisplayedMonth
387 * @cat plugins/datePicker
388 * @author Kelvin Luck (http://www.kelvinluck.com/)
389 *
390 * @example $('.date-picker').datePicker();
391 * $('.date-picker').dpSetDisplayedMonth(10, 2008);
392 * @desc Creates a date picker associated with all elements with a class of "date-picker" then sets the selected date on these date pickers to the first Janurary 2010. When the date picker is next opened it will display Janurary 2010.
393 **/
394                dpSetDisplayedMonth : function(m, y)
395                {
396                        return _w.call(this, 'setDisplayedMonth', Number(m), Number(y), true);
397                },
398/**
399 * Displays the date picker associated with the matched elements. Since only one date picker can be displayed at once then the date picker associated with the last matched element will be the one that is displayed.
400 *
401 * @param HTMLElement e An element that you want the date picker to pop up relative in position to. Optional - default behaviour is to pop up next to the element associated with this date picker.
402 * @type jQuery
403 * @name dpDisplay
404 * @cat plugins/datePicker
405 * @author Kelvin Luck (http://www.kelvinluck.com/)
406 *
407 * @example $('#date-picker').datePicker();
408 * $('#date-picker').dpDisplay();
409 * @desc Creates a date picker associated with the element with an id of date-picker and then causes it to pop up.
410 **/
411                dpDisplay : function(e)
412                {
413                        return _w.call(this, 'display', e);
414                },
415/**
416 * Sets a function or array of functions that is called when each TD of the date picker popup is rendered to the page
417 *
418 * @param (Function|Array) a A function or an array of functions that are called when each td is rendered. Each function will receive four arguments; a jquery object wrapping the created TD, a Date object containing the date this TD represents, a number giving the currently rendered month and a number giving the currently rendered year.
419 * @type jQuery
420 * @name dpSetRenderCallback
421 * @cat plugins/datePicker
422 * @author Kelvin Luck (http://www.kelvinluck.com/)
423 *
424 * @example $('#date-picker').datePicker();
425 * $('#date-picker').dpSetRenderCallback(function($td, thisDate, month, year)
426 * {
427 *      // do stuff as each td is rendered dependant on the date in the td and the displayed month and year
428 * });
429 * @desc Creates a date picker associated with the element with an id of date-picker and then creates a function which is called as each td is rendered when this date picker is displayed.
430 **/
431                dpSetRenderCallback : function(a)
432                {
433                        return _w.call(this, 'setRenderCallback', a);
434                },
435/**
436 * Sets the position that the datePicker will pop up (relative to it's associated element)
437 *
438 * @param Number v The vertical alignment of the created date picker to it's associated element. Possible values are $.dpConst.POS_TOP and $.dpConst.POS_BOTTOM
439 * @param Number h The horizontal alignment of the created date picker to it's associated element. Possible values are $.dpConst.POS_LEFT and $.dpConst.POS_RIGHT
440 * @type jQuery
441 * @name dpSetPosition
442 * @cat plugins/datePicker
443 * @author Kelvin Luck (http://www.kelvinluck.com/)
444 *
445 * @example $('#date-picker').datePicker();
446 * $('#date-picker').dpSetPosition($.dpConst.POS_BOTTOM, $.dpConst.POS_RIGHT);
447 * @desc Creates a date picker associated with the element with an id of date-picker and makes it so that when this date picker pops up it will be bottom and right aligned to the #date-picker element.
448 **/
449                dpSetPosition : function(v, h)
450                {
451                        return _w.call(this, 'setPosition', v, h);
452                },
453/**
454 * Sets the offset that the popped up date picker will have from it's default position relative to it's associated element (as set by dpSetPosition)
455 *
456 * @param Number v The vertical offset of the created date picker.
457 * @param Number h The horizontal offset of the created date picker.
458 * @type jQuery
459 * @name dpSetOffset
460 * @cat plugins/datePicker
461 * @author Kelvin Luck (http://www.kelvinluck.com/)
462 *
463 * @example $('#date-picker').datePicker();
464 * $('#date-picker').dpSetOffset(-20, 200);
465 * @desc Creates a date picker associated with the element with an id of date-picker and makes it so that when this date picker pops up it will be 20 pixels above and 200 pixels to the right of it's default position.
466 **/
467                dpSetOffset : function(v, h)
468                {
469                        return _w.call(this, 'setOffset', v, h);
470                },
471/**
472 * Closes the open date picker associated with this element.
473 *
474 * @type jQuery
475 * @name dpClose
476 * @cat plugins/datePicker
477 * @author Kelvin Luck (http://www.kelvinluck.com/)
478 *
479 * @example $('.date-pick')
480 *              .datePicker()
481 *              .bind(
482 *                      'focus',
483 *                      function()
484 *                      {
485 *                              $(this).dpDisplay();
486 *                      }
487 *              ).bind(
488 *                      'blur',
489 *                      function()
490 *                      {
491 *                              $(this).dpClose();
492 *                      }
493 *              );
494 * @desc Creates a date picker and makes it appear when the relevant element is focused and disappear when it is blurred.
495 **/
496                dpClose : function()
497                {
498                        return _w.call(this, '_closeCalendar', false, this[0]);
499                },
500                // private function called on unload to clean up any expandos etc and prevent memory links...
501                _dpDestroy : function()
502                {
503                        // TODO - implement this?
504                }
505        });
506       
507        // private internal function to cut down on the amount of code needed where we forward
508        // dp* methods on the jQuery object on to the relevant DatePicker controllers...
509        var _w = function(f, a1, a2, a3, a4)
510        {
511                return this.each(
512                        function()
513                        {
514                                var c = _getController(this);
515                                if (c) {
516                                        c[f](a1, a2, a3, a4);
517                                }
518                        }
519                );
520        };
521       
522        function DatePicker(ele)
523        {
524                this.ele = ele;
525               
526                // initial values...
527                this.displayedMonth             =       null;
528                this.displayedYear              =       null;
529                this.startDate                  =       null;
530                this.endDate                    =       null;
531                this.showYearNavigation =       null;
532                this.closeOnSelect              =       null;
533                this.displayClose               =       null;
534                this.rememberViewedMonth=       null;
535                this.selectMultiple             =       null;
536                this.numSelectable              =       null;
537                this.numSelected                =       null;
538                this.verticalPosition   =       null;
539                this.horizontalPosition =       null;
540                this.verticalOffset             =       null;
541                this.horizontalOffset   =       null;
542                this.button                             =       null;
543                this.renderCallback             =       [];
544                this.selectedDates              =       {};
545                this.inline                             =       null;
546                this.context                    =       '#dp-popup';
547                this.settings                   =       {};
548        };
549        $.extend(
550                DatePicker.prototype,
551                {       
552                        init : function(s)
553                        {
554                                this.setStartDate(s.startDate);
555                                this.setEndDate(s.endDate);
556                                this.setDisplayedMonth(Number(s.month), Number(s.year));
557                                this.setRenderCallback(s.renderCallback);
558                                this.showYearNavigation = s.showYearNavigation;
559                                this.closeOnSelect = s.closeOnSelect;
560                                this.displayClose = s.displayClose;
561                                this.rememberViewedMonth =      s.rememberViewedMonth;
562                                this.selectMultiple = s.selectMultiple;
563                                this.numSelectable = s.selectMultiple ? s.numSelectable : 1;
564                                this.numSelected = 0;
565                                this.verticalPosition = s.verticalPosition;
566                                this.horizontalPosition = s.horizontalPosition;
567                                this.hoverClass = s.hoverClass;
568                                this.setOffset(s.verticalOffset, s.horizontalOffset);
569                                this.inline = s.inline;
570                                this.settings = s;
571                                if (this.inline) {
572                                        this.context = this.ele;
573                                        this.display();
574                                }
575                        },
576                        setStartDate : function(d)
577                        {
578                                if (d) {
579                                        this.startDate = Date.fromString(d);
580                                }
581                                if (!this.startDate) {
582                                        this.startDate = (new Date()).zeroTime();
583                                }
584                                this.setDisplayedMonth(this.displayedMonth, this.displayedYear);
585                        },
586                        setEndDate : function(d)
587                        {
588                                if (d) {
589                                        this.endDate = Date.fromString(d);
590                                }
591                                if (!this.endDate) {
592                                        this.endDate = (new Date('12/31/2999')); // using the JS Date.parse function which expects mm/dd/yyyy
593                                }
594                                if (this.endDate.getTime() < this.startDate.getTime()) {
595                                        this.endDate = this.startDate;
596                                }
597                                this.setDisplayedMonth(this.displayedMonth, this.displayedYear);
598                        },
599                        setPosition : function(v, h)
600                        {
601                                this.verticalPosition = v;
602                                this.horizontalPosition = h;
603                        },
604                        setOffset : function(v, h)
605                        {
606                                this.verticalOffset = parseInt(v) || 0;
607                                this.horizontalOffset = parseInt(h) || 0;
608                        },
609                        setDisabled : function(s)
610                        {
611                                $e = $(this.ele);
612                                $e[s ? 'addClass' : 'removeClass']('dp-disabled');
613                                if (this.button) {
614                                        $but = $(this.button);
615                                        $but[s ? 'addClass' : 'removeClass']('dp-disabled');
616                                        $but.attr('title', s ? '' : $.dpText.TEXT_CHOOSE_DATE);
617                                }
618                                if ($e.is(':text')) {
619                                        $e.attr('disabled', s ? 'disabled' : '');
620                                }
621                        },
622                        setDisplayedMonth : function(m, y, rerender)
623                        {
624                                if (this.startDate == undefined || this.endDate == undefined) {
625                                        return;
626                                }
627                                var s = new Date(this.startDate.getTime());
628                                s.setDate(1);
629                                var e = new Date(this.endDate.getTime());
630                                e.setDate(1);
631                               
632                                var t;
633                                if ((!m && !y) || (isNaN(m) && isNaN(y))) {
634                                        // no month or year passed - default to current month
635                                        t = new Date().zeroTime();
636                                        t.setDate(1);
637                                } else if (isNaN(m)) {
638                                        // just year passed in - presume we want the displayedMonth
639                                        t = new Date(y, this.displayedMonth, 1);
640                                } else if (isNaN(y)) {
641                                        // just month passed in - presume we want the displayedYear
642                                        t = new Date(this.displayedYear, m, 1);
643                                } else {
644                                        // year and month passed in - that's the date we want!
645                                        t = new Date(y, m, 1)
646                                }
647                                // check if the desired date is within the range of our defined startDate and endDate
648                                if (t.getTime() < s.getTime()) {
649                                        t = s;
650                                } else if (t.getTime() > e.getTime()) {
651                                        t = e;
652                                }
653                                var oldMonth = this.displayedMonth;
654                                var oldYear = this.displayedYear;
655                                this.displayedMonth = t.getMonth();
656                                this.displayedYear = t.getFullYear();
657
658                                if (rerender && (this.displayedMonth != oldMonth || this.displayedYear != oldYear))
659                                {
660                                        this._rerenderCalendar();
661                                        $(this.ele).trigger('dpMonthChanged', [this.displayedMonth, this.displayedYear]);
662                                }
663                        },
664                        setSelected : function(d, v, moveToMonth, dispatchEvents)
665                        {
666                                var s = this.settings;
667                                if (s.selectWeek)
668                                {
669                                        d = d.addDays(- (d.getDay() - Date.firstDayOfWeek + 7) % 7);
670                                        if (d < this.startDate) // The first day of this week is before the start date so is unselectable...
671                                        {
672                                                return;
673                                        }
674                                }
675                                if (v == this.isSelected(d)) // this date is already un/selected
676                                {
677                                        return;
678                                }
679                                if (this.selectMultiple == false) {
680                                        this.selectedDates = {};
681                                        this.numSelected = 0;
682                                        $('td.selected', this.context).removeClass('selected').parent().removeClass('selectedWeek');
683                                } else if (v && this.numSelected == this.numSelectable) {
684                                        // can't select any more dates...
685                                        return;
686                                }
687                                if (moveToMonth && (this.displayedMonth != d.getMonth() || this.displayedYear != d.getFullYear())) {
688                                        this.setDisplayedMonth(d.getMonth(), d.getFullYear(), true);
689                                }
690                                this.selectedDates[d.toString()] = v;
691                                this.numSelected += v ? 1 : -1;
692                                var selectorString = 'td.' +( d.getMonth() == this.displayedMonth ? 'current-month' : 'other-month');
693                                var $td;
694                                $(selectorString, this.context).each(
695                                        function()
696                                        {
697                                                if ($(this).data('datePickerDate') == d.asString()) {
698                                                        $td = $(this);
699                                                        if (s.selectWeek)
700                                                        {
701                                                                $td.parent()[v ? 'addClass' : 'removeClass']('selectedWeek');
702                                                        }
703                                                        $td[v ? 'addClass' : 'removeClass']('selected');
704                                                }
705                                        }
706                                );
707                                $('td', this.context).not('.selected')[this.selectMultiple &&  this.numSelected == this.numSelectable ? 'addClass' : 'removeClass']('unselectable');
708                               
709                                if (dispatchEvents)
710                                {
711                                        var s = this.isSelected(d);
712                                        $e = $(this.ele);
713                                        var dClone = Date.fromString(d.asString());
714                                        $e.trigger('dateSelected', [dClone, $td, s]);
715                                        $e.trigger('change');
716                                }
717                        },
718                        isSelected : function(d)
719                        {
720                                return this.selectedDates[d.toString()];
721                        },
722                        getSelected : function()
723                        {
724                                var r = [];
725                                for(s in this.selectedDates) {
726                                        if (this.selectedDates[s] == true) {
727                                                r.push(Date.parse(s));
728                                        }
729                                }
730                                return r;
731                        },
732                        display : function(eleAlignTo)
733                        {
734                                if ($(this.ele).is('.dp-disabled')) return;
735                               
736                                eleAlignTo = eleAlignTo || this.ele;
737                                var c = this;
738                                var $ele = $(eleAlignTo);
739                                var eleOffset = $ele.offset();
740                               
741                                var $createIn;
742                                var attrs;
743                                var attrsCalendarHolder;
744                                var cssRules;
745                               
746                                if (c.inline) {
747                                        $createIn = $(this.ele);
748                                        attrs = {
749                                                'id'            :       'calendar-' + this.ele._dpId,
750                                                'className'     :       'dp-popup dp-popup-inline'
751                                        };
752
753                                        $('.dp-popup', $createIn).remove();
754                                        cssRules = {
755                                        };
756                                } else {
757                                        $createIn = $('body');
758                                        attrs = {
759                                                'id'            :       'dp-popup',
760                                                'className'     :       'dp-popup'
761                                        };
762                                        cssRules = {
763                                                'top'   :       eleOffset.top + c.verticalOffset,
764                                                'left'  :       eleOffset.left + c.horizontalOffset
765                                        };
766                                       
767                                        var _checkMouse = function(e)
768                                        {
769                                                var el = e.target;
770                                                var cal = $('#dp-popup')[0];
771                                               
772                                                while (true){
773                                                        if (el == cal) {
774                                                                return true;
775                                                        } else if (el == document) {
776                                                                c._closeCalendar();
777                                                                return false;
778                                                        } else {
779                                                                el = $(el).parent()[0];
780                                                        }
781                                                }
782                                        };
783                                        this._checkMouse = _checkMouse;
784                                       
785                                        c._closeCalendar(true);
786                                        $(document).bind(
787                                                'keydown.datepicker',
788                                                function(event)
789                                                {
790                                                        if (event.keyCode == 27) {
791                                                                c._closeCalendar();
792                                                        }
793                                                }
794                                        );
795                                }
796                               
797                                if (!c.rememberViewedMonth)
798                                {
799                                        var selectedDate = this.getSelected()[0];
800                                        if (selectedDate) {
801                                                selectedDate = new Date(selectedDate);
802                                                this.setDisplayedMonth(selectedDate.getMonth(), selectedDate.getFullYear(), false);
803                                        }
804                                }
805                               
806                                $createIn
807                                        .append(
808                                                $('<div></div>')
809                                                        .attr(attrs)
810                                                        .css(cssRules)
811                                                        .append(
812//                                                              $('<a href="#" class="selecteee">aaa</a>'),
813                                                                $('<h2></h2>'),
814                                                                $('<div class="dp-nav-prev"></div>')
815                                                                        .append(
816                                                                                $('<a class="dp-nav-prev-year" href="#" title="' + $.dpText.TEXT_PREV_YEAR + '">&lt;&lt;</a>')
817                                                                                        .bind(
818                                                                                                'click',
819                                                                                                function()
820                                                                                                {
821                                                                                                        return c._displayNewMonth.call(c, this, 0, -1);
822                                                                                                }
823                                                                                        ),
824                                                                                $('<a class="dp-nav-prev-month" href="#" title="' + $.dpText.TEXT_PREV_MONTH + '">&lt;</a>')
825                                                                                        .bind(
826                                                                                                'click',
827                                                                                                function()
828                                                                                                {
829                                                                                                        return c._displayNewMonth.call(c, this, -1, 0);
830                                                                                                }
831                                                                                        )
832                                                                        ),
833                                                                $('<div class="dp-nav-next"></div>')
834                                                                        .append(
835                                                                                $('<a class="dp-nav-next-year" href="#" title="' + $.dpText.TEXT_NEXT_YEAR + '">&gt;&gt;</a>')
836                                                                                        .bind(
837                                                                                                'click',
838                                                                                                function()
839                                                                                                {
840                                                                                                        return c._displayNewMonth.call(c, this, 0, 1);
841                                                                                                }
842                                                                                        ),
843                                                                                $('<a class="dp-nav-next-month" href="#" title="' + $.dpText.TEXT_NEXT_MONTH + '">&gt;</a>')
844                                                                                        .bind(
845                                                                                                'click',
846                                                                                                function()
847                                                                                                {
848                                                                                                        return c._displayNewMonth.call(c, this, 1, 0);
849                                                                                                }
850                                                                                        )
851                                                                        ),
852                                                                $('<div></div>')
853                                                                        .attr('className', 'dp-calendar')
854                                                        )
855                                                        .bgIframe()
856                                                );
857                                       
858                                var $pop = this.inline ? $('.dp-popup', this.context) : $('#dp-popup');
859                               
860                                if (this.showYearNavigation == false) {
861                                        $('.dp-nav-prev-year, .dp-nav-next-year', c.context).css('display', 'none');
862                                }
863                                if (this.displayClose) {
864                                        $pop.append(
865                                                $('<a href="#" id="dp-close">' + $.dpText.TEXT_CLOSE + '</a>')
866                                                        .bind(
867                                                                'click',
868                                                                function()
869                                                                {
870                                                                        c._closeCalendar();
871                                                                        return false;
872                                                                }
873                                                        )
874                                        );
875                                }
876                                c._renderCalendar();
877
878                                $(this.ele).trigger('dpDisplayed', $pop);
879                               
880                                if (!c.inline) {
881                                        if (this.verticalPosition == $.dpConst.POS_BOTTOM) {
882                                                $pop.css('top', eleOffset.top + $ele.height() - $pop.height() + c.verticalOffset);
883                                        }
884                                        if (this.horizontalPosition == $.dpConst.POS_RIGHT) {
885                                                $pop.css('left', eleOffset.left + $ele.width() - $pop.width() + c.horizontalOffset);
886                                        }
887//                                      $('.selectee', this.context).focus();
888                                        $(document).bind('mousedown.datepicker', this._checkMouse);
889                                }
890                               
891                        },
892                        setRenderCallback : function(a)
893                        {
894                                if (a == null) return;
895                                if (a && typeof(a) == 'function') {
896                                        a = [a];
897                                }
898                                this.renderCallback = this.renderCallback.concat(a);
899                        },
900                        cellRender : function ($td, thisDate, month, year) {
901                                var c = this.dpController;
902                                var d = new Date(thisDate.getTime());
903                               
904                                // add our click handlers to deal with it when the days are clicked...
905                               
906                                $td.bind(
907                                        'click',
908                                        function()
909                                        {
910                                                var $this = $(this);
911                                                if (!$this.is('.disabled')) {
912                                                        c.setSelected(d, !$this.is('.selected') || !c.selectMultiple, false, true);
913                                                        if (c.closeOnSelect) {
914                                                                c._closeCalendar();
915                                                        }
916                                                        // TODO: Instead of this which doesn't work in IE anyway we should find the next focusable element in the document
917                                                        // and pass the focus onto that. That would allow the user to continue on the form as expected...
918                                                        if (!$.browser.msie)
919                                                        {
920                                                                $(c.ele).trigger('focus', [$.dpConst.DP_INTERNAL_FOCUS]);
921                                                        }
922                                                }
923                                        }
924                                );
925                               
926                                if (c.isSelected(d)) {
927                                        $td.addClass('selected');
928                                        if (c.settings.selectWeek)
929                                        {
930                                                $td.parent().addClass('selectedWeek');
931                                        }
932                                } else  if (c.selectMultiple && c.numSelected == c.numSelectable) {
933                                        $td.addClass('unselectable');
934                                }
935                               
936                        },
937                        _applyRenderCallbacks : function()
938                        {
939                                var c = this;
940                                $('td', this.context).each(
941                                        function()
942                                        {
943                                                for (var i=0; i<c.renderCallback.length; i++) {
944                                                        $td = $(this);
945                                                        c.renderCallback[i].apply(this, [$td, Date.fromString($td.data('datePickerDate')), c.displayedMonth, c.displayedYear]);
946                                                }
947                                        }
948                                );
949                                return;
950                        },
951                        // ele is the clicked button - only proceed if it doesn't have the class disabled...
952                        // m and y are -1, 0 or 1 depending which direction we want to go in...
953                        _displayNewMonth : function(ele, m, y)
954                        {
955                                if (!$(ele).is('.disabled')) {
956                                        this.setDisplayedMonth(this.displayedMonth + m, this.displayedYear + y, true);
957                                }
958                                ele.blur();
959                                return false;
960                        },
961                        _rerenderCalendar : function()
962                        {
963                                this._clearCalendar();
964                                this._renderCalendar();
965                        },
966                        _renderCalendar : function()
967                        {
968                                // set the title...
969                                $('h2', this.context).html((new Date(this.displayedYear, this.displayedMonth, 1)).asString($.dpText.HEADER_FORMAT));
970                               
971                                // render the calendar...
972                                $('.dp-calendar', this.context).renderCalendar(
973                                        $.extend(
974                                                {},
975                                                this.settings,
976                                                {
977                                                        month                   : this.displayedMonth,
978                                                        year                    : this.displayedYear,
979                                                        renderCallback  : this.cellRender,
980                                                        dpController    : this,
981                                                        hoverClass              : this.hoverClass
982                                                })
983                                );
984                               
985                                // update the status of the control buttons and disable dates before startDate or after endDate...
986                                // TODO: When should the year buttons be disabled? When you can't go forward a whole year from where you are or is that annoying?
987                                if (this.displayedYear == this.startDate.getFullYear() && this.displayedMonth == this.startDate.getMonth()) {
988                                        $('.dp-nav-prev-year', this.context).addClass('disabled');
989                                        $('.dp-nav-prev-month', this.context).addClass('disabled');
990                                        $('.dp-calendar td.other-month', this.context).each(
991                                                function()
992                                                {
993                                                        var $this = $(this);
994                                                        if (Number($this.text()) > 20) {
995                                                                $this.addClass('disabled');
996                                                        }
997                                                }
998                                        );
999                                        var d = this.startDate.getDate();
1000                                        $('.dp-calendar td.current-month', this.context).each(
1001                                                function()
1002                                                {
1003                                                        var $this = $(this);
1004                                                        if (Number($this.text()) < d) {
1005                                                                $this.addClass('disabled');
1006                                                        }
1007                                                }
1008                                        );
1009                                } else {
1010                                        $('.dp-nav-prev-year', this.context).removeClass('disabled');
1011                                        $('.dp-nav-prev-month', this.context).removeClass('disabled');
1012                                        var d = this.startDate.getDate();
1013                                        if (d > 20) {
1014                                                // check if the startDate is last month as we might need to add some disabled classes...
1015                                                var st = this.startDate.getTime();
1016                                                var sd = new Date(st);
1017                                                sd.addMonths(1);
1018                                                if (this.displayedYear == sd.getFullYear() && this.displayedMonth == sd.getMonth()) {
1019                                                        $('.dp-calendar td.other-month', this.context).each(
1020                                                                function()
1021                                                                {
1022                                                                        var $this = $(this);
1023                                                                        if (Date.fromString($this.data('datePickerDate')).getTime() < st) {
1024                                                                                $this.addClass('disabled');
1025                                                                        }
1026                                                                }
1027                                                        );
1028                                                }
1029                                        }
1030                                }
1031                                if (this.displayedYear == this.endDate.getFullYear() && this.displayedMonth == this.endDate.getMonth()) {
1032                                        $('.dp-nav-next-year', this.context).addClass('disabled');
1033                                        $('.dp-nav-next-month', this.context).addClass('disabled');
1034                                        $('.dp-calendar td.other-month', this.context).each(
1035                                                function()
1036                                                {
1037                                                        var $this = $(this);
1038                                                        if (Number($this.text()) < 14) {
1039                                                                $this.addClass('disabled');
1040                                                        }
1041                                                }
1042                                        );
1043                                        var d = this.endDate.getDate();
1044                                        $('.dp-calendar td.current-month', this.context).each(
1045                                                function()
1046                                                {
1047                                                        var $this = $(this);
1048                                                        if (Number($this.text()) > d) {
1049                                                                $this.addClass('disabled');
1050                                                        }
1051                                                }
1052                                        );
1053                                } else {
1054                                        $('.dp-nav-next-year', this.context).removeClass('disabled');
1055                                        $('.dp-nav-next-month', this.context).removeClass('disabled');
1056                                        var d = this.endDate.getDate();
1057                                        if (d < 13) {
1058                                                // check if the endDate is next month as we might need to add some disabled classes...
1059                                                var ed = new Date(this.endDate.getTime());
1060                                                ed.addMonths(-1);
1061                                                if (this.displayedYear == ed.getFullYear() && this.displayedMonth == ed.getMonth()) {
1062                                                        $('.dp-calendar td.other-month', this.context).each(
1063                                                                function()
1064                                                                {
1065                                                                        var $this = $(this);
1066                                                                        if (Number($this.text()) > d) {
1067                                                                                $this.addClass('disabled');
1068                                                                        }
1069                                                                }
1070                                                        );
1071                                                }
1072                                        }
1073                                }
1074                                this._applyRenderCallbacks();
1075                        },
1076                        _closeCalendar : function(programatic, ele)
1077                        {
1078                                if (!ele || ele == this.ele)
1079                                {
1080                                        $(document).unbind('mousedown.datepicker');
1081                                        $(document).unbind('keydown.datepicker');
1082                                        this._clearCalendar();
1083                                        $('#dp-popup a').unbind();
1084                                        $('#dp-popup').empty().remove();
1085                                        if (!programatic) {
1086                                                $(this.ele).trigger('dpClosed', [this.getSelected()]);
1087                                        }
1088                                }
1089                        },
1090                        // empties the current dp-calendar div and makes sure that all events are unbound
1091                        // and expandos removed to avoid memory leaks...
1092                        _clearCalendar : function()
1093                        {
1094                                // TODO.
1095                                $('.dp-calendar td', this.context).unbind();
1096                                $('.dp-calendar', this.context).empty();
1097                        }
1098                }
1099        );
1100       
1101        // static constants
1102        $.dpConst = {
1103                SHOW_HEADER_NONE        :       0,
1104                SHOW_HEADER_SHORT       :       1,
1105                SHOW_HEADER_LONG        :       2,
1106                POS_TOP                         :       0,
1107                POS_BOTTOM                      :       1,
1108                POS_LEFT                        :       0,
1109                POS_RIGHT                       :       1,
1110                DP_INTERNAL_FOCUS       :       'dpInternalFocusTrigger'
1111        };
1112        // localisable text
1113        $.dpText = {
1114                TEXT_PREV_YEAR          :       'Previous year',
1115                TEXT_PREV_MONTH         :       'Previous month',
1116                TEXT_NEXT_YEAR          :       'Next year',
1117                TEXT_NEXT_MONTH         :       'Next month',
1118                TEXT_CLOSE                      :       'Close',
1119                TEXT_CHOOSE_DATE        :       'Choose date',
1120                HEADER_FORMAT           :       'mmmm yyyy'
1121        };
1122        // version
1123        $.dpVersion = '$Id: jquery.datePicker.js 52 2009-02-09 06:16:11Z kelvin.luck $';
1124
1125        $.fn.datePicker.defaults = {
1126                month                           : undefined,
1127                year                            : undefined,
1128                showHeader                      : $.dpConst.SHOW_HEADER_SHORT,
1129                startDate                       : undefined,
1130                endDate                         : undefined,
1131                inline                          : false,
1132                renderCallback          : null,
1133                createButton            : true,
1134                showYearNavigation      : true,
1135                closeOnSelect           : true,
1136                displayClose            : false,
1137                selectMultiple          : false,
1138                numSelectable           : Number.MAX_VALUE,
1139                clickInput                      : false,
1140                rememberViewedMonth     : true,
1141                selectWeek                      : false,
1142                verticalPosition        : $.dpConst.POS_TOP,
1143                horizontalPosition      : $.dpConst.POS_LEFT,
1144                verticalOffset          : 0,
1145                horizontalOffset        : 0,
1146                hoverClass                      : 'dp-hover'
1147        };
1148
1149        function _getController(ele)
1150        {
1151                if (ele._dpId) return $.event._dpCache[ele._dpId];
1152                return false;
1153        };
1154       
1155        // make it so that no error is thrown if bgIframe plugin isn't included (allows you to use conditional
1156        // comments to only include bgIframe where it is needed in IE without breaking this plugin).
1157        if ($.fn.bgIframe == undefined) {
1158                $.fn.bgIframe = function() {return this; };
1159        };
1160
1161
1162        // clean-up
1163        $(window)
1164                .bind('unload', function() {
1165                        var els = $.event._dpCache || [];
1166                        for (var i in els) {
1167                                $(els[i].ele)._dpDestroy();
1168                        }
1169                });
1170               
1171       
1172})(jQuery);
Notatka: Zobacz TracBrowser aby uzyskać więcej informacji.