├── .gitignore
├── src
├── themes
│ └── default
│ │ └── modules
│ │ ├── calendar.overrides
│ │ └── calendar.variables
├── theme.config
├── theme.less
└── definitions
│ └── modules
│ ├── calendar.less
│ └── calendar.js
├── bower.json
├── package.json
├── LICENSE
├── dist
├── calendar.min.css
├── calendar.css
├── calendar.min.js
└── calendar.js
├── gulpfile.js
└── README.md
/.gitignore:
--------------------------------------------------------------------------------
1 | *.DS_Store
2 | /node_modules/
3 |
--------------------------------------------------------------------------------
/src/themes/default/modules/calendar.overrides:
--------------------------------------------------------------------------------
1 | /*******************************
2 | Theme Overrides
3 | *******************************/
4 |
--------------------------------------------------------------------------------
/src/theme.config:
--------------------------------------------------------------------------------
1 | @site : 'default';
2 | @calendar : 'default';
3 |
4 | @themesFolder : 'themes';
5 |
6 | @import "theme.less";
7 |
8 | /* End Config */
--------------------------------------------------------------------------------
/bower.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "semantic-ui-calendar",
3 | "version": "0.0.8",
4 | "main": [
5 | "./dist/calendar.css",
6 | "./dist/calendar.js"
7 | ],
8 | "ignore": [
9 | "node_modules",
10 | ".bowerrc",
11 | ".gitignore",
12 | ".jshintignore",
13 | ".jshintrc",
14 | "bower.json",
15 | "gulpfile.js",
16 | "package.json",
17 | "README.md"
18 | ]
19 | }
--------------------------------------------------------------------------------
/src/theme.less:
--------------------------------------------------------------------------------
1 | @theme: @@element;
2 |
3 | @import "@{themesFolder}/default/globals/site.variables";
4 | @import "@{themesFolder}/@{site}/globals/site.variables";
5 |
6 | @import "@{themesFolder}/default/@{type}s/@{element}.variables";
7 | @import (optional) "@{themesFolder}/@{theme}/@{type}s/@{element}.variables";
8 |
9 | .loadUIOverrides() {
10 | @import (optional) "@{themesFolder}/@{theme}/@{type}s/@{element}.overrides";
11 | }
12 |
--------------------------------------------------------------------------------
/src/themes/default/modules/calendar.variables:
--------------------------------------------------------------------------------
1 | /*******************************
2 | Calendar
3 | *******************************/
4 |
5 | @focusBoxShadow: inset 0 0 0 1px @focusedFormBorderColor;
6 | @focusInvertedBoxShadow: inset 0 0 0 1px @focusedFormBorderColor;
7 |
8 | @todayFontWeight: bold;
9 |
10 | @rangeBackground: @transparentBlack;
11 | @rangeTextColor: @selectedTextColor;
12 | @rangeBoxShadow: none;
13 | @rangeInvertedBackground: @transparentWhite;
14 | @rangeInvertedTextColor: @invertedSelectedTextColor;
15 | @rangeInvertedBoxShadow: none;
16 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "semantic-ui-calendar",
3 | "version": "0.0.8",
4 | "description": "Calendar module for Semantic UI",
5 | "author": "Michael de Hoog (https://github.com/mdehoog/)",
6 | "repository": {
7 | "type": "git",
8 | "url": "https://github.com/mdehoog/semantic-ui-calendar.git"
9 | },
10 | "license": "MIT",
11 | "devDependencies": {
12 | "gulp": "^3.9.1",
13 | "gulp-autoprefixer": "^3.1.1",
14 | "gulp-clean-css": "^2.0.13",
15 | "gulp-clone": "^1.0.0",
16 | "gulp-flatten": "^0.3.1",
17 | "gulp-less": "^3.1.0",
18 | "gulp-rename": "^1.2.2",
19 | "gulp-replace": "^0.5.4",
20 | "gulp-uglify": "^2.0.0",
21 | "require-dot-file": "^0.4.0",
22 | "semantic-ui-less": "^2.2.4"
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2016 Michael de Hoog
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
--------------------------------------------------------------------------------
/dist/calendar.min.css:
--------------------------------------------------------------------------------
1 | /*!
2 | * # Semantic UI 0.0.8 - Calendar
3 | * http://github.com/semantic-org/semantic-ui/
4 | *
5 | *
6 | * Released under the MIT license
7 | * http://opensource.org/licenses/MIT
8 | *
9 | */.ui.calendar .ui.popup{max-width:none;padding:0;border:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.ui.calendar .calendar:focus{outline:0}.ui.calendar .ui.popup .ui.grid{display:block;white-space:nowrap}.ui.calendar .ui.popup .ui.grid>.column{width:auto}.ui.calendar .ui.table.minute,.ui.calendar .ui.table.month,.ui.calendar .ui.table.year{min-width:15em}.ui.calendar .ui.table.day{min-width:18em}.ui.calendar .ui.table.hour{min-width:20em}.ui.calendar .ui.table tr td,.ui.calendar .ui.table tr th{padding:.5em;white-space:nowrap}.ui.calendar .ui.table tr th{border-left:none}.ui.calendar .ui.table tr th .icon{margin:0}.ui.calendar .ui.table tr:first-child th{position:relative;padding-left:0;padding-right:0}.ui.calendar .ui.table.day tr:first-child th{border:none}.ui.calendar .ui.table.day tr:nth-child(2) th{padding-top:.2em;padding-bottom:.3em}.ui.calendar .ui.table tr td{padding-left:.1em;padding-right:.1em}.ui.calendar .ui.table tr .link{cursor:pointer}.ui.calendar .ui.table tr .prev.link{width:14.28571429%;position:absolute;left:0}.ui.calendar .ui.table tr .next.link{width:14.28571429%;position:absolute;right:0}.ui.calendar .ui.table tr .disabled{pointer-events:none;color:rgba(40,40,40,.3)}.ui.calendar .ui.table tr td.today{font-weight:700}.ui.calendar .ui.table tr td.range{background:rgba(0,0,0,.05);color:rgba(0,0,0,.95);box-shadow:none}.ui.calendar .ui.table.inverted tr td.range{background:rgba(255,255,255,.08);color:#fff;box-shadow:none}.ui.calendar .calendar.active .ui.table tbody tr td.focus,.ui.calendar .calendar.active .ui.table.inverted tbody tr td.focus,.ui.calendar .calendar:focus .ui.table tbody tr td.focus,.ui.calendar .calendar:focus .ui.table.inverted tbody tr td.focus{box-shadow:inset 0 0 0 1px #85B7D9}
--------------------------------------------------------------------------------
/gulpfile.js:
--------------------------------------------------------------------------------
1 | var gulp = require('gulp');
2 | var less = require('gulp-less');
3 | var autoprefixer = require('gulp-autoprefixer');
4 | var flatten = require('gulp-flatten');
5 | var clone = require('gulp-clone');
6 | var replace = require('gulp-replace');
7 | var minifyCSS = require('gulp-clean-css');
8 | var rename = require('gulp-rename');
9 | var uglify = require('gulp-uglify');
10 | var path = require('path');
11 | var npmPackage = require('./package.json');
12 |
13 | var settings = {
14 | less: {
15 | paths: [
16 | path.join(__dirname, 'node_modules', 'semantic-ui-less')
17 | ]
18 | },
19 |
20 | /* What Browsers to Prefix */
21 | prefix: {
22 | browsers: [
23 | 'last 2 versions',
24 | '> 1%',
25 | 'opera 12.1',
26 | 'bb 10',
27 | 'android 4'
28 | ]
29 | },
30 |
31 | /* File Renames */
32 | rename: {
33 | minJS : { extname : '.min.js' },
34 | minCSS : { extname : '.min.css' },
35 | rtlCSS : { extname : '.rtl.css' },
36 | rtlMinCSS : { extname : '.rtl.min.css' }
37 | },
38 |
39 | /* Minified CSS Concat */
40 | minify: {
41 | processImport : false,
42 | restructuring : false,
43 | keepSpecialComments : 1,
44 | roundingPrecision : -1,
45 | },
46 |
47 | /* Minified JS Settings */
48 | uglify: {
49 | mangle : true,
50 | preserveComments : 'some'
51 | }
52 | };
53 |
54 | var comments = {
55 | // remove all comments from config files (.variable)
56 | variables : {
57 | in : /(\/\*[\s\S]+?\*\/+)[\s\S]+?\/\* End Config \*\//,
58 | out : '$1',
59 | },
60 | // add version to first comment
61 | license: {
62 | in : /(^\/\*[\s\S]+)(# Semantic UI )([\s\S]+?\*\/)/,
63 | out : '$1$2' + npmPackage.version + ' $3'
64 | },
65 | // adds uniform spacing around comments
66 | large: {
67 | in : /(\/\*\*\*\*[\s\S]+?\*\/)/mg,
68 | out : '\n\n$1\n'
69 | },
70 | small: {
71 | in : /(\/\*---[\s\S]+?\*\/)/mg,
72 | out : '\n$1\n'
73 | },
74 | tiny: {
75 | in : /(\/\* [\s\S]+? \*\/)/mg,
76 | out : '\n$1'
77 | }
78 | };
79 |
80 | gulp.task('default', function() {
81 | gulp.start('less', 'javascript');
82 | });
83 |
84 | gulp.task('less', function () {
85 | return gulp.src('./src/definitions/**/*.less')
86 | .pipe(less(settings.less))
87 | .pipe(autoprefixer(settings.prefix))
88 | .pipe(replace(comments.variables.in, comments.variables.out))
89 | .pipe(replace(comments.license.in, comments.license.out))
90 | .pipe(replace(comments.large.in, comments.large.out))
91 | .pipe(replace(comments.small.in, comments.small.out))
92 | .pipe(replace(comments.tiny.in, comments.tiny.out))
93 | .pipe(flatten())
94 | .pipe(gulp.dest('./dist'))
95 | .pipe(minifyCSS(settings.minify))
96 | .pipe(rename(settings.rename.minCSS))
97 | .pipe(gulp.dest('./dist'));
98 | });
99 |
100 | gulp.task('javascript', function () {
101 | return gulp.src('./src/definitions/**/*.js')
102 | .pipe(flatten())
103 | .pipe(replace(comments.license.in, comments.license.out))
104 | .pipe(gulp.dest('./dist'))
105 | .pipe(uglify(settings.uglify))
106 | .pipe(rename(settings.rename.minJS))
107 | .pipe(gulp.dest('./dist'));
108 | });
109 |
--------------------------------------------------------------------------------
/dist/calendar.css:
--------------------------------------------------------------------------------
1 | /*!
2 | * # Semantic UI 0.0.8 - Calendar
3 | * http://github.com/semantic-org/semantic-ui/
4 | *
5 | *
6 | * Released under the MIT license
7 | * http://opensource.org/licenses/MIT
8 | *
9 | */
10 |
11 |
12 | /*******************************
13 | Popup
14 | *******************************/
15 |
16 | .ui.calendar .ui.popup {
17 | max-width: none;
18 | padding: 0;
19 | border: none;
20 | -webkit-user-select: none;
21 | -moz-user-select: none;
22 | -ms-user-select: none;
23 | user-select: none;
24 | }
25 |
26 |
27 | /*******************************
28 | Calendar
29 | *******************************/
30 |
31 | .ui.calendar .calendar:focus {
32 | outline: 0;
33 | }
34 |
35 |
36 | /*******************************
37 | Grid
38 | *******************************/
39 |
40 | .ui.calendar .ui.popup .ui.grid {
41 | display: block;
42 | white-space: nowrap;
43 | }
44 | .ui.calendar .ui.popup .ui.grid > .column {
45 | width: auto;
46 | }
47 |
48 |
49 | /*******************************
50 | Table
51 | *******************************/
52 |
53 | .ui.calendar .ui.table.year,
54 | .ui.calendar .ui.table.month,
55 | .ui.calendar .ui.table.minute {
56 | min-width: 15em;
57 | }
58 | .ui.calendar .ui.table.day {
59 | min-width: 18em;
60 | }
61 | .ui.calendar .ui.table.hour {
62 | min-width: 20em;
63 | }
64 | .ui.calendar .ui.table tr th,
65 | .ui.calendar .ui.table tr td {
66 | padding: 0.5em;
67 | white-space: nowrap;
68 | }
69 | .ui.calendar .ui.table tr th {
70 | border-left: none;
71 | }
72 | .ui.calendar .ui.table tr th .icon {
73 | margin: 0;
74 | }
75 | .ui.calendar .ui.table tr th .icon {
76 | margin: 0;
77 | }
78 | .ui.calendar .ui.table tr:first-child th {
79 | position: relative;
80 | padding-left: 0;
81 | padding-right: 0;
82 | }
83 | .ui.calendar .ui.table.day tr:first-child th {
84 | border: none;
85 | }
86 | .ui.calendar .ui.table.day tr:nth-child(2) th {
87 | padding-top: 0.2em;
88 | padding-bottom: 0.3em;
89 | }
90 | .ui.calendar .ui.table tr td {
91 | padding-left: 0.1em;
92 | padding-right: 0.1em;
93 | }
94 | .ui.calendar .ui.table tr .link {
95 | cursor: pointer;
96 | }
97 | .ui.calendar .ui.table tr .prev.link {
98 | width: 14.28571429%;
99 | position: absolute;
100 | left: 0;
101 | }
102 | .ui.calendar .ui.table tr .next.link {
103 | width: 14.28571429%;
104 | position: absolute;
105 | right: 0;
106 | }
107 | .ui.calendar .ui.table tr .disabled {
108 | pointer-events: none;
109 | color: rgba(40, 40, 40, 0.3);
110 | }
111 |
112 | /*--------------
113 | States
114 | ---------------*/
115 |
116 | .ui.calendar .ui.table tr td.today {
117 | font-weight: bold;
118 | }
119 | .ui.calendar .ui.table tr td.range {
120 | background: rgba(0, 0, 0, 0.05);
121 | color: rgba(0, 0, 0, 0.95);
122 | box-shadow: none;
123 | }
124 | .ui.calendar .ui.table.inverted tr td.range {
125 | background: rgba(255, 255, 255, 0.08);
126 | color: #ffffff;
127 | box-shadow: none;
128 | }
129 | .ui.calendar .calendar:focus .ui.table tbody tr td.focus,
130 | .ui.calendar .calendar.active .ui.table tbody tr td.focus {
131 | box-shadow: inset 0 0 0 1px #85B7D9;
132 | }
133 | .ui.calendar .calendar:focus .ui.table.inverted tbody tr td.focus,
134 | .ui.calendar .calendar.active .ui.table.inverted tbody tr td.focus {
135 | box-shadow: inset 0 0 0 1px #85B7D9;
136 | }
137 |
138 |
139 | /*******************************
140 | Theme Overrides
141 | *******************************/
142 |
143 |
--------------------------------------------------------------------------------
/src/definitions/modules/calendar.less:
--------------------------------------------------------------------------------
1 | /*!
2 | * # Semantic UI - Calendar
3 | * http://github.com/semantic-org/semantic-ui/
4 | *
5 | *
6 | * Released under the MIT license
7 | * http://opensource.org/licenses/MIT
8 | *
9 | */
10 |
11 | /*******************************
12 | Theme
13 | *******************************/
14 |
15 | @type : 'module';
16 | @element : 'calendar';
17 |
18 | @import (multiple) '../../theme.config';
19 |
20 | /*******************************
21 | Popup
22 | *******************************/
23 |
24 | .ui.calendar .ui.popup {
25 | max-width: none;
26 | padding: 0;
27 | border: none;
28 | user-select: none;
29 | }
30 |
31 | /*******************************
32 | Calendar
33 | *******************************/
34 |
35 | .ui.calendar .calendar:focus {
36 | outline: 0;
37 | }
38 |
39 | /*******************************
40 | Grid
41 | *******************************/
42 |
43 | .ui.calendar .ui.popup .ui.grid {
44 | display: block;
45 | white-space: nowrap;
46 | }
47 |
48 | .ui.calendar .ui.popup .ui.grid > .column {
49 | width: auto;
50 | }
51 |
52 | /*******************************
53 | Table
54 | *******************************/
55 |
56 | .ui.calendar .ui.table.year,
57 | .ui.calendar .ui.table.month,
58 | .ui.calendar .ui.table.minute {
59 | min-width: 15em;
60 | }
61 |
62 | .ui.calendar .ui.table.day {
63 | min-width: 18em;
64 | }
65 |
66 | .ui.calendar .ui.table.hour {
67 | min-width: 20em;
68 | }
69 |
70 | .ui.calendar .ui.table tr th,
71 | .ui.calendar .ui.table tr td {
72 | padding: 0.5em;
73 | white-space: nowrap;
74 | }
75 |
76 | .ui.calendar .ui.table tr th {
77 | border-left: none;
78 | }
79 |
80 | .ui.calendar .ui.table tr th .icon {
81 | margin: 0;
82 | }
83 |
84 | .ui.calendar .ui.table tr th .icon {
85 | margin: 0;
86 | }
87 |
88 | .ui.calendar .ui.table tr:first-child th {
89 | position: relative;
90 | padding-left: 0;
91 | padding-right: 0;
92 | }
93 |
94 | .ui.calendar .ui.table.day tr:first-child th {
95 | border: none;
96 | }
97 |
98 | .ui.calendar .ui.table.day tr:nth-child(2) th {
99 | padding-top: 0.2em;
100 | padding-bottom: 0.3em;
101 | }
102 |
103 | .ui.calendar .ui.table tr td {
104 | padding-left: 0.1em;
105 | padding-right: 0.1em;
106 | }
107 |
108 | .ui.calendar .ui.table tr .link {
109 | cursor: pointer;
110 | }
111 |
112 | .ui.calendar .ui.table tr .prev.link {
113 | width: 14.28571429%;
114 | position: absolute;
115 | left: 0;
116 | }
117 |
118 | .ui.calendar .ui.table tr .next.link {
119 | width: 14.28571429%;
120 | position: absolute;
121 | right: 0;
122 | }
123 |
124 | .ui.calendar .ui.table tr .disabled {
125 | pointer-events: none;
126 | color: @disabledTextColor;
127 | }
128 |
129 | /*--------------
130 | States
131 | ---------------*/
132 |
133 | .ui.calendar .ui.table tr td.today {
134 | font-weight: @todayFontWeight;
135 | }
136 |
137 | .ui.calendar .ui.table tr td.range {
138 | background: @rangeBackground;
139 | color: @rangeTextColor;
140 | box-shadow: @rangeBoxShadow;
141 | }
142 |
143 | .ui.calendar .ui.table.inverted tr td.range {
144 | background: @rangeInvertedBackground;
145 | color: @rangeInvertedTextColor;
146 | box-shadow: @rangeInvertedBoxShadow;
147 | }
148 |
149 | .ui.calendar .calendar:focus .ui.table tbody tr td.focus,
150 | .ui.calendar .calendar.active .ui.table tbody tr td.focus {
151 | box-shadow: @focusBoxShadow;
152 | }
153 |
154 | .ui.calendar .calendar:focus .ui.table.inverted tbody tr td.focus,
155 | .ui.calendar .calendar.active .ui.table.inverted tbody tr td.focus {
156 | box-shadow: @focusInvertedBoxShadow;
157 | }
158 |
159 | .loadUIOverrides();
160 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |  No longer maintained. See [Fomantic-UI](https://github.com/fomantic/Fomantic-UI) for a more recently updated version of this module.
2 |
3 | # Semantic-UI-Calendar
4 |
5 | Calendar module for Semantic UI. See https://jsbin.com/ruqakehefa/ for example usage.
6 |
7 | This was originally a PR for Semantic UI: https://github.com/Semantic-Org/Semantic-UI/pull/3256.
8 |
9 | ## Installation
10 |
11 | Install using bower:
12 |
13 | ```
14 | bower install --save semantic-ui-calendar
15 | ```
16 |
17 | Install using npm:
18 |
19 | ```
20 | npm install --save semantic-ui-calendar
21 | ```
22 |
23 | Include javascript and css in html:
24 |
25 | ```html
26 |
27 |
28 | ```
29 |
30 | ## Compiling CSS from LESS
31 |
32 | If you want to theme the calendar, or change some of the variables from the default theme, you can compile the LESS source using your favourite build tool.
33 |
34 | Import the calendar.less file into your app.
35 |
36 | ```less
37 | @import 'definitions/modules/calendar';
38 | ```
39 |
40 | Ensure that this module's `src` directory is included when compiling the LESS:
41 |
42 | ```javascript
43 | lessOptions: {
44 | paths: [
45 | 'bower_components/semantic-ui-calendar/src',
46 | ...
47 | ]
48 | }
49 | ```
50 |
51 | ## Behavior
52 |
53 | These functions can be called the same way you call Semantic UI behavior functions:
54 |
55 | ```javascript
56 | $('#mycalendar').calendar('behavior name', argumentOne, argumentTwo);
57 | ```
58 |
59 | Behavior | Description
60 | --- | ---
61 | `refresh` | Refresh the calendar.
62 | `popup(arguments)` | Call the popup module (e.g. passing 'show' will show the calendar popup).
63 | `focus` | Focus the calendar input.
64 | `blur` | Blur the calendar input.
65 | `clear` | Clear the selected date.
66 | `get date` | Get the selected date.
67 | `set date(date, updateInput = true, fireChange = true)` | Set the selected date. Pass `false` to `updateInput` to disable updating the input. Pass `false` to `fireChange` to disable the `onChange` callback for this change.
68 | `get mode` | Get the current selection mode (`year`, `month`, `day`, `hour`, `minute`).
69 | `set mode(mode)` | Set the current selection mode (`year`, `month`, `day`, `hour`, `minute`).
70 | `get startDate` | Get the start date for range selection.
71 | `set startDate(date)` | Set the start date for range selection.
72 | `get endDate` | Get the end date for range selection.
73 | `set endDate(date)` | Set the end date for range selection.
74 | `get focusDate` | Get the currently focused date.
75 | `set focusDate(date)` | Set the currently focused date.
76 |
77 | ## Settings
78 |
79 | The following settings are supported by this module:
80 |
81 | ```javascript
82 | type: 'datetime', // picker type, can be 'datetime', 'date', 'time', 'month', or 'year'
83 | firstDayOfWeek: 0, // day for first day column (0 = Sunday)
84 | constantHeight: true, // add rows to shorter months to keep day calendar height consistent (6 rows)
85 | today: false, // show a 'today/now' button at the bottom of the calendar
86 | closable: true, // close the popup after selecting a date/time
87 | monthFirst: true, // month before day when parsing/converting date from/to text
88 | touchReadonly: true, // set input to readonly on touch devices
89 | inline: false, // create the calendar inline instead of inside a popup
90 | on: null, // when to show the popup (defaults to 'focus' for input, 'click' for others)
91 | initialDate: null, // date to display initially when no date is selected (null = now)
92 | startMode: false, // display mode to start in, can be 'year', 'month', 'day', 'hour', 'minute' (false = 'day')
93 | minDate: null, // minimum date/time that can be selected, dates/times before are disabled
94 | maxDate: null, // maximum date/time that can be selected, dates/times after are disabled
95 | ampm: true, // show am/pm in time mode
96 | disableYear: false, // disable year selection mode
97 | disableMonth: false, // disable month selection mode
98 | disableMinute: false, // disable minute selection mode
99 | formatInput: true, // format the input text upon input blur and module creation
100 | startCalendar: null, // jquery object or selector for another calendar that represents the start date of a date range
101 | endCalendar: null, // jquery object or selector for another calendar that represents the end date of a date range
102 | multiMonth: 1, // show multiple months when in 'day' mode
103 |
104 | // popup options ('popup', 'on', 'hoverable', and show/hide callbacks are overridden)
105 | popupOptions: {
106 | position: 'bottom left',
107 | lastResort: 'bottom left',
108 | prefer: 'opposite',
109 | hideOnScroll: false
110 | },
111 |
112 | text: {
113 | days: ['S', 'M', 'T', 'W', 'T', 'F', 'S'],
114 | months: ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'],
115 | monthsShort: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'],
116 | today: 'Today',
117 | now: 'Now',
118 | am: 'AM',
119 | pm: 'PM'
120 | },
121 |
122 | formatter: {
123 | header: function (date, mode, settings) {
124 | //return a string to show on the header for the given 'date' and 'mode'
125 | },
126 | yearHeader: function (date, settings) {
127 | //return a string to show on the header for the given 'date' in year mode
128 | },
129 | monthHeader: function (date, settings) {
130 | //return a string to show on the header for the given 'date' in month mode
131 | },
132 | dayHeader: function (date, settings) {
133 | //return a string to show on the header for the given 'date' in day mode
134 | },
135 | hourHeader: function (date, settings) {
136 | //return a string to show on the header for the given 'date' in hour mode
137 | },
138 | minuteHeader: function (date, settings) {
139 | //return a string to show on the header for the given 'date' in minute mode
140 | },
141 | dayColumnHeader: function (day, settings) {
142 | //return a abbreviated day string to show above each column in day mode
143 | },
144 | datetime: function (date, settings) {
145 | //return a formatted string representing the date & time of 'date'
146 | },
147 | date: function (date, settings) {
148 | //return a formatted string representing the date of 'date'
149 | },
150 | time: function (date, settings, forCalendar) {
151 | //return a formatted string representing the time of 'date'
152 | },
153 | today: function (settings) {
154 | return settings.type === 'date' ? settings.text.today : settings.text.now;
155 | },
156 | cell: function (cell, date, cellOptions) {
157 | //customize the calendar cell, cellOptions is:
158 | //{ mode: string, adjacent: boolean, disabled: boolean, active: boolean, today: boolean }
159 | }
160 | },
161 |
162 | parser: {
163 | date: function (text, settings) {
164 | //return a date parsed from 'text'
165 | }
166 | },
167 |
168 | // callback when date changes, return false to cancel the change
169 | onChange: function (date, text, mode) {
170 | },
171 |
172 | // callback before show animation, return false to prevent show
173 | onShow: function () {
174 | },
175 |
176 | // callback after show animation
177 | onVisible: function () {
178 | },
179 |
180 | // callback before hide animation, return false to prevent hide
181 | onHide: function () {
182 | },
183 |
184 | // callback after hide animation
185 | onHidden: function () {
186 | },
187 |
188 | // is the given date disabled?
189 | isDisabled: function (date, mode) {
190 | return false;
191 | },
192 |
193 | selector: {
194 | popup: '.ui.popup',
195 | input: 'input',
196 | activator: 'input'
197 | },
198 |
199 | regExp: {
200 | dateWords: /[^A-Za-z\u00C0-\u024F]+/g,
201 | dateNumbers: /[^\d:]+/g
202 | },
203 |
204 | error: {
205 | popup: 'UI Popup, a required component is not included in this page',
206 | method: 'The method you called is not defined.'
207 | },
208 |
209 | className: {
210 | calendar: 'calendar',
211 | active: 'active',
212 | popup: 'ui popup',
213 | grid: 'ui equal width grid',
214 | column: 'column',
215 | table: 'ui celled center aligned unstackable table',
216 | prev: 'prev link',
217 | next: 'next link',
218 | prevIcon: 'chevron left icon',
219 | nextIcon: 'chevron right icon',
220 | link: 'link',
221 | cell: 'link',
222 | disabledCell: 'disabled',
223 | adjacentCell: 'adjacent',
224 | activeCell: 'active',
225 | rangeCell: 'range',
226 | focusCell: 'focus',
227 | todayCell: 'today',
228 | today: 'today link'
229 | },
230 |
231 | metadata: {
232 | date: 'date',
233 | focusDate: 'focusDate',
234 | startDate: 'startDate',
235 | endDate: 'endDate',
236 | mode: 'mode',
237 | monthOffset: 'monthOffset'
238 | }
239 | ```
240 |
--------------------------------------------------------------------------------
/dist/calendar.min.js:
--------------------------------------------------------------------------------
1 | !function(e,t,a,n){"use strict";t="undefined"!=typeof t&&t.Math==Math?t:"undefined"!=typeof self&&self.Math==Math?self:Function("return this")(),e.fn.calendar=function(t){var o,r=e(this),i=r.selector||"",l=(new Date).getTime(),d=[],s=arguments[0],u="string"==typeof s,p=[].slice.call(arguments,1);return r.each(function(){var r,c,f=e.isPlainObject(t)?e.extend(!0,{},e.fn.calendar.settings,t):e.extend({},e.fn.calendar.settings),h=f.className,g=f.namespace,m=f.selector,v=f.formatter,y=f.parser,D=f.metadata,b=f.error,C="."+g,M="module-"+g,w=e(this),x=w.find(m.input),k=w.find(m.popup),T=w.find(m.activator),F=this,H=w.data(M),O=!1,I=!1;c={initialize:function(){c.debug("Initializing calendar for",F),r=c.get.isTouch(),c.setup.popup(),c.setup.inline(),c.setup.input(),c.setup.date(),c.create.calendar(),c.bind.events(),c.instantiate()},instantiate:function(){c.verbose("Storing instance of calendar"),H=c,w.data(M,H)},destroy:function(){c.verbose("Destroying previous calendar for",F),w.removeData(M),c.unbind.events()},setup:{popup:function(){if(!f.inline&&(T.length||(T=w.children().first(),T.length))){if(e.fn.popup===n)return void c.error(b.popup);k.length||(k=e("
").addClass(h.popup).prependTo(T.parent())),k.addClass(h.calendar);var t=f.onVisible,a=f.onHidden;x.length||(k.attr("tabindex","0"),t=function(){return c.focus(),f.onVisible.apply(k,arguments)},a=function(){return c.blur(),f.onHidden.apply(k,arguments)});var o=function(){return c.set.focusDate(c.get.date()),c.set.mode(f.startMode),f.onShow.apply(k,arguments)},r=f.on||(x.length?"focus":"click"),i=e.extend({},f.popupOptions,{popup:k,on:r,hoverable:"hover"===r,onShow:o,onVisible:t,onHide:f.onHide,onHidden:a});c.popup(i)}},inline:function(){T.length&&!f.inline||(k=e("").addClass(h.calendar).appendTo(w),x.length||k.attr("tabindex","0"))},input:function(){f.touchReadonly&&x.length&&r&&x.prop("readonly",!0)},date:function(){if(x.length){var e=x.val(),t=y.date(e,f);c.set.date(t,f.formatInput,!1)}}},create:{calendar:function(){var t,a,n,o,r,i,l,d=c.get.mode(),s=new Date,u=c.get.date(),p=c.get.focusDate(),g=p||u||f.initialDate||s;g=c.helper.dateInRange(g),p||(p=g,c.set.focusDate(p,!1,!1));var m="year"===d,y="month"===d,b="day"===d,C="hour"===d,M="minute"===d,w="time"===f.type,x=Math.max(f.multiMonth,1),T=b?c.get.monthOffset():0,F=g.getMinutes(),H=g.getHours(),O=g.getDate(),I=g.getMonth()+T,N=g.getFullYear(),Y=b?7:C?4:3,E=7===Y?"seven":4===Y?"four":"three",R=b||C?6:4,j=b?x:1,A=k;for(A.empty(),j>1&&(l=e("").addClass(h.grid).appendTo(A)),o=0;o1){var S=e("").addClass(h.column).appendTo(l);A=S}var V=I+o,P=(new Date(N,V,1).getDay()-f.firstDayOfWeek%7+7)%7;if(!f.constantHeight&&b){var q=new Date(N,V+1,0).getDate()+P;R=Math.ceil(q/7)}var K=m?10:y?1:0,J=b?1:0,W=C||M?1:0,z=C||M?O:1,L=new Date(N-K,V-J,z-W,H),B=new Date(N+K,V+J,z+W,H),U=m?new Date(10*Math.ceil(N/10)-9,0,0):y?new Date(N,0,0):b?new Date(N,V,0):new Date(N,V,O,(-1)),Q=m?new Date(10*Math.ceil(N/10)+1,0,1):y?new Date(N+1,0,1):b?new Date(N,V+1,1):new Date(N,V,O+1),Z=e("").addClass(h.table).addClass(E+" column").addClass(d).appendTo(A);if(!w){var G=e("").appendTo(Z);r=e("
").appendTo(G),i=e(" | ").attr("colspan",""+Y).appendTo(r);var X=m||y?new Date(N,0,1):b?new Date(N,V,1):new Date(N,V,O,H,F),$=e("").addClass(h.link).appendTo(i);$.text(v.header(X,d,f));var _=y?f.disableYear?"day":"year":b?f.disableMonth?"year":"month":"day";if($.data(D.mode,_),0===o){var ee=e("").addClass(h.prev).appendTo(i);ee.data(D.focusDate,L),ee.toggleClass(h.disabledCell,!c.helper.isDateInRange(U,d)),e("").addClass(h.prevIcon).appendTo(ee)}if(o===j-1){var te=e("").addClass(h.next).appendTo(i);te.data(D.focusDate,B),te.toggleClass(h.disabledCell,!c.helper.isDateInRange(Q,d)),e("").addClass(h.nextIcon).appendTo(te)}if(b)for(r=e("
").appendTo(G),t=0;t").appendTo(r),i.text(v.dayColumnHeader((t+f.firstDayOfWeek)%7,f))}var ae=e("").appendTo(Z);for(t=m?10*Math.ceil(N/10)-9:b?1-P:0,a=0;a").appendTo(ae),n=0;n").addClass(h.cell).appendTo(r),i.text(oe),i.data(D.date,ne);var re=b&&ne.getMonth()!==(V+12)%12,ie=re||!c.helper.isDateInRange(ne,d)||f.isDisabled(ne,d),le=c.helper.dateEqual(ne,u,d),de=c.helper.dateEqual(ne,s,d);i.toggleClass(h.adjacentCell,re),i.toggleClass(h.disabledCell,ie),i.toggleClass(h.activeCell,le&&!re),C||M||i.toggleClass(h.todayCell,!re&&de);var se={mode:d,adjacent:re,disabled:ie,active:le,today:de};v.cell(i,ne,se),c.helper.dateEqual(ne,p,d)&&c.set.focusDate(ne,!1,!1)}if(f.today){var ue=e("
").appendTo(ae),pe=e(" | ").attr("colspan",""+Y).addClass(h.today).appendTo(ue);pe.text(v.today(f)),pe.data(D.date,s)}c.update.focus(!1,Z)}}},update:{focus:function(t,a){a=a||k;var n=c.get.mode(),o=c.get.date(),i=c.get.focusDate(),l=c.get.startDate(),d=c.get.endDate(),s=(t?i:null)||o||(r?null:i);a.find("td").each(function(){var t=e(this),a=t.data(D.date);if(a){var o=t.hasClass(h.disabledCell),u=t.hasClass(h.activeCell),p=t.hasClass(h.adjacentCell),f=c.helper.dateEqual(a,i,n),g=!!s&&(!!l&&c.helper.isDateInRange(a,n,l,s)||!!d&&c.helper.isDateInRange(a,n,s,d));t.toggleClass(h.focusCell,f&&(!r||O)&&!p),t.toggleClass(h.rangeCell,g&&!u&&!o)}})}},refresh:function(){c.create.calendar()},bind:{events:function(){k.on("mousedown"+C,c.event.mousedown),k.on("touchstart"+C,c.event.mousedown),k.on("mouseup"+C,c.event.mouseup),k.on("touchend"+C,c.event.mouseup),k.on("mouseover"+C,c.event.mouseover),x.length?(x.on("input"+C,c.event.inputChange),x.on("focus"+C,c.event.inputFocus),x.on("blur"+C,c.event.inputBlur),x.on("click"+C,c.event.inputClick),x.on("keydown"+C,c.event.keydown)):k.on("keydown"+C,c.event.keydown)}},unbind:{events:function(){k.off(C),x.length&&x.off(C)}},event:{mouseover:function(t){var a=e(t.target),n=a.data(D.date),o=1===t.buttons;n&&c.set.focusDate(n,!1,!0,o)},mousedown:function(t){x.length&&t.preventDefault(),O=t.type.indexOf("touch")>=0;var a=e(t.target),n=a.data(D.date);n&&c.set.focusDate(n,!1,!0,!0)},mouseup:function(t){c.focus(),t.preventDefault(),t.stopPropagation(),O=!1;var a=e(t.target),n=a.parent();(n.data(D.date)||n.data(D.focusDate)||n.data(D.mode))&&(a=n);var o=a.data(D.date),r=a.data(D.focusDate),i=a.data(D.mode);if(o){var l=a.hasClass(h.today);c.selectDate(o,l)}else r?c.set.focusDate(r):i&&c.set.mode(i)},keydown:function(e){if(27!==e.keyCode&&9!==e.keyCode||c.popup("hide"),c.popup("is visible"))if(37===e.keyCode||38===e.keyCode||39===e.keyCode||40===e.keyCode){var t=c.get.mode(),a="day"===t?7:"hour"===t?4:3,n=37===e.keyCode?-1:38===e.keyCode?-a:39==e.keyCode?1:a;n*="minute"===t?5:1;var o=c.get.focusDate()||c.get.date()||new Date,r=o.getFullYear()+("year"===t?n:0),i=o.getMonth()+("month"===t?n:0),l=o.getDate()+("day"===t?n:0),d=o.getHours()+("hour"===t?n:0),s=o.getMinutes()+("minute"===t?n:0),u=new Date(r,i,l,d,s);"time"===f.type&&(u=c.helper.mergeDateTime(o,u)),c.helper.isDateInRange(u,t)&&c.set.focusDate(u)}else if(13===e.keyCode){var t=c.get.mode(),p=c.get.focusDate();p&&!f.isDisabled(p,t)&&c.selectDate(p),e.preventDefault(),e.stopPropagation()}38!==e.keyCode&&40!==e.keyCode||(e.preventDefault(),c.popup("show"))},inputChange:function(){var e=x.val(),t=y.date(e,f);c.set.date(t,!1)},inputFocus:function(){k.addClass(h.active)},inputBlur:function(){if(k.removeClass(h.active),f.formatInput){var e=c.get.date(),t=v.datetime(e,f);x.val(t)}},inputClick:function(){c.popup("show")}},get:{date:function(){return w.data(D.date)||null},focusDate:function(){return w.data(D.focusDate)||null},startDate:function(){var e=c.get.calendarModule(f.startCalendar);return(e?e.get.date():w.data(D.startDate))||null},endDate:function(){var e=c.get.calendarModule(f.endCalendar);return(e?e.get.date():w.data(D.endDate))||null},monthOffset:function(){return w.data(D.monthOffset)||0},mode:function(){var t=w.data(D.mode)||f.startMode,a=c.get.validModes();return e.inArray(t,a)>=0?t:"time"===f.type?"hour":"month"===f.type?"month":"year"===f.type?"year":"day"},validModes:function(){var e=[];return"time"!==f.type&&(f.disableYear&&"year"!==f.type||e.push("year"),(!f.disableMonth&&"year"!==f.type||"month"===f.type)&&e.push("month"),f.type.indexOf("date")>=0&&e.push("day")),f.type.indexOf("time")>=0&&(e.push("hour"),f.disableMinute||e.push("minute")),e},isTouch:function(){try{return a.createEvent("TouchEvent"),!0}catch(e){return!1}},calendarModule:function(t){return t?(t instanceof e||(t=w.parent().children(t).first()),t.data(M)):null}},set:{date:function(e,t,a){t=t!==!1,a=a!==!1,e=c.helper.sanitiseDate(e),e=c.helper.dateInRange(e);var o=c.get.mode(),r=v.datetime(e,f);if(a&&f.onChange.call(F,e,r,o)===!1)return!1;if(c.set.focusDate(e),f.isDisabled(e,o))return!1;var i=c.get.endDate();i&&e&&e>i&&c.set.endDate(n),c.set.dataKeyValue(D.date,e),t&&x.length&&x.val(r)},startDate:function(e,t){e=c.helper.sanitiseDate(e);var a=c.get.calendarModule(f.startCalendar);a&&a.set.date(e),c.set.dataKeyValue(D.startDate,e,t)},endDate:function(e,t){e=c.helper.sanitiseDate(e);var a=c.get.calendarModule(f.endCalendar);a&&a.set.date(e),c.set.dataKeyValue(D.endDate,e,t)},focusDate:function(e,t,a,n){e=c.helper.sanitiseDate(e),e=c.helper.dateInRange(e);var o="day"===c.get.mode(),r=c.get.focusDate();if(o&&e&&r){var i=e.getFullYear()-r.getFullYear(),l=12*i+e.getMonth()-r.getMonth();if(l){var d=c.get.monthOffset()-l;c.set.monthOffset(d,!1)}}var s=c.set.dataKeyValue(D.focusDate,e,t);a=a!==!1&&s&&t===!1||I!=n,I=n,a&&c.update.focus(n)},monthOffset:function(e,t){var a=Math.max(f.multiMonth,1);e=Math.max(1-a,Math.min(0,e)),c.set.dataKeyValue(D.monthOffset,e,t)},mode:function(e,t){c.set.dataKeyValue(D.mode,e,t)},dataKeyValue:function(e,t,a){var n=w.data(e),o=n===t||n<=t&&n>=t;return t?w.data(e,t):w.removeData(e),a=a!==!1&&!o,a&&c.create.calendar(),!o}},selectDate:function(e,t){var a=c.get.mode(),n=t||"minute"===a||f.disableMinute&&"hour"===a||"date"===f.type&&"day"===a||"month"===f.type&&"month"===a||"year"===f.type&&"year"===a;if(n){var o=c.set.date(e)===!1;if(!o&&f.closable){c.popup("hide");var r=c.get.calendarModule(f.endCalendar);r&&(r.popup("show"),r.focus())}}else{var i="year"===a?f.disableMonth?"day":"month":"month"===a?"day":"day"===a?"hour":"minute";c.set.mode(i),"hour"===a||"day"===a&&c.get.date()?c.set.date(e):c.set.focusDate(e)}},changeDate:function(e){c.set.date(e)},clear:function(){c.set.date(n)},popup:function(){return T.popup.apply(T,arguments)},focus:function(){x.length?x.focus():k.focus()},blur:function(){x.length?x.blur():k.blur()},helper:{sanitiseDate:function(e){return e?(e instanceof Date||(e=y.date(""+e,f)),isNaN(e.getTime())?n:e):n},dateDiff:function(e,t,a){a=a||"day";var n="time"===f.type,o="year"===a,r=o||"month"===a,i="minute"===a,l=i||"hour"===a;return e=new Date(n?2e3:e.getFullYear(),n?0:o?0:e.getMonth(),n?1:r?1:e.getDate(),l?e.getHours():0,i?5*Math.floor(e.getMinutes()/5):0),t=new Date(n?2e3:t.getFullYear(),n?0:o?0:t.getMonth(),n?1:r?1:t.getDate(),l?t.getHours():0,i?5*Math.floor(t.getMinutes()/5):0),t.getTime()-e.getTime()},dateEqual:function(e,t,a){return!!e&&!!t&&0===c.helper.dateDiff(e,t,a)},isDateInRange:function(e,t,a,n){if(!a&&!n){var o=c.get.startDate();a=o&&f.minDate?new Date(Math.max(o,f.minDate)):o||f.minDate,n=f.maxDate}return a=a&&new Date(a.getFullYear(),a.getMonth(),a.getDate(),a.getHours(),5*Math.ceil(a.getMinutes()/5)),!(!e||a&&c.helper.dateDiff(e,a,t)>0||n&&c.helper.dateDiff(n,e,t)>0)},dateInRange:function(e,t,a){if(!t&&!a){var n=c.get.startDate();t=n&&f.minDate?new Date(Math.max(n,f.minDate)):n||f.minDate,a=f.maxDate}t=t&&new Date(t.getFullYear(),t.getMonth(),t.getDate(),t.getHours(),5*Math.ceil(t.getMinutes()/5));var o="time"===f.type;return e?t&&c.helper.dateDiff(e,t,"minute")>0?o?c.helper.mergeDateTime(e,t):t:a&&c.helper.dateDiff(a,e,"minute")>0?o?c.helper.mergeDateTime(e,a):a:e:e},mergeDateTime:function(e,t){return e&&t?new Date(e.getFullYear(),e.getMonth(),e.getDate(),t.getHours(),t.getMinutes()):t}},setting:function(t,a){if(c.debug("Changing setting",t,a),e.isPlainObject(t))e.extend(!0,f,t);else{if(a===n)return f[t];e.isPlainObject(f[t])?e.extend(!0,f[t],a):f[t]=a}},internal:function(t,a){return c.debug("Changing internal",t,a),a===n?c[t]:void(e.isPlainObject(t)?e.extend(!0,c,t):c[t]=a)},debug:function(){!f.silent&&f.debug&&(f.performance?c.performance.log(arguments):(c.debug=Function.prototype.bind.call(console.info,console,f.name+":"),c.debug.apply(console,arguments)))},verbose:function(){!f.silent&&f.verbose&&f.debug&&(f.performance?c.performance.log(arguments):(c.verbose=Function.prototype.bind.call(console.info,console,f.name+":"),c.verbose.apply(console,arguments)))},error:function(){f.silent||(c.error=Function.prototype.bind.call(console.error,console,f.name+":"),c.error.apply(console,arguments))},performance:{log:function(e){var t,a,n;f.performance&&(t=(new Date).getTime(),n=l||t,a=t-n,l=t,d.push({Name:e[0],Arguments:[].slice.call(e,1)||"",Element:F,"Execution Time":a})),clearTimeout(c.performance.timer),c.performance.timer=setTimeout(c.performance.display,500)},display:function(){var t=f.name+":",a=0;l=!1,clearTimeout(c.performance.timer),e.each(d,function(e,t){a+=t["Execution Time"]}),t+=" "+a+"ms",i&&(t+=" '"+i+"'"),(console.group!==n||console.table!==n)&&d.length>0&&(console.groupCollapsed(t),console.table?console.table(d):e.each(d,function(e,t){console.log(t.Name+": "+t["Execution Time"]+"ms")}),console.groupEnd()),d=[]}},invoke:function(t,a,r){var i,l,d,s=H;return a=a||p,r=F||r,"string"==typeof t&&s!==n&&(t=t.split(/[\. ]/),i=t.length-1,e.each(t,function(a,o){var r=a!=i?o+t[a+1].charAt(0).toUpperCase()+t[a+1].slice(1):t;if(e.isPlainObject(s[r])&&a!=i)s=s[r];else{if(s[r]!==n)return l=s[r],!1;if(!e.isPlainObject(s[o])||a==i)return s[o]!==n?(l=s[o],!1):(c.error(b.method,t),!1);s=s[o]}})),e.isFunction(l)?d=l.apply(r,a):l!==n&&(d=l),e.isArray(o)?o.push(d):o!==n?o=[o,d]:d!==n&&(o=d),l}},u?(H===n&&c.initialize(),c.invoke(s)):(H!==n&&H.invoke("destroy"),c.initialize())}),o!==n?o:this},e.fn.calendar.settings={name:"Calendar",namespace:"calendar",silent:!1,debug:!1,verbose:!1,performance:!1,type:"datetime",firstDayOfWeek:0,constantHeight:!0,today:!1,closable:!0,monthFirst:!0,touchReadonly:!0,inline:!1,on:null,initialDate:null,startMode:!1,minDate:null,maxDate:null,ampm:!0,disableYear:!1,disableMonth:!1,disableMinute:!1,formatInput:!0,startCalendar:null,endCalendar:null,multiMonth:1,popupOptions:{position:"bottom left",lastResort:"bottom left",prefer:"opposite",hideOnScroll:!1},text:{days:["S","M","T","W","T","F","S"],months:["January","February","March","April","May","June","July","August","September","October","November","December"],monthsShort:["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"],today:"Today",now:"Now",am:"AM",pm:"PM"},formatter:{header:function(e,t,a){return"year"===t?a.formatter.yearHeader(e,a):"month"===t?a.formatter.monthHeader(e,a):"day"===t?a.formatter.dayHeader(e,a):"hour"===t?a.formatter.hourHeader(e,a):a.formatter.minuteHeader(e,a)},yearHeader:function(e,t){var a=10*Math.ceil(e.getFullYear()/10);return a-9+" - "+(a+2)},monthHeader:function(e,t){return e.getFullYear()},dayHeader:function(e,t){var a=t.text.months[e.getMonth()],n=e.getFullYear();return a+" "+n},hourHeader:function(e,t){return t.formatter.date(e,t)},minuteHeader:function(e,t){return t.formatter.date(e,t)},dayColumnHeader:function(e,t){return t.text.days[e]},datetime:function(e,t){if(!e)return"";var a="time"===t.type?"":t.formatter.date(e,t),n=t.type.indexOf("time")<0?"":t.formatter.time(e,t,!1),o="datetime"===t.type?" ":"";return a+o+n},date:function(e,t){if(!e)return"";var a=e.getDate(),n=t.text.months[e.getMonth()],o=e.getFullYear();return"year"===t.type?o:"month"===t.type?n+" "+o:(t.monthFirst?n+" "+a:a+" "+n)+", "+o},time:function(e,t,a){if(!e)return"";var n=e.getHours(),o=e.getMinutes(),r="";return t.ampm&&(r=" "+(n<12?t.text.am:t.text.pm),n=0===n?12:n>12?n-12:n),n+":"+(o<10?"0":"")+o+r},today:function(e){return"date"===e.type?e.text.today:e.text.now},cell:function(e,t,a){}},parser:{date:function(t,a){if(!t)return null;if(t=(""+t).trim().toLowerCase(),0===t.length)return null;var o,r,i,l=-1,d=-1,s=-1,u=-1,p=-1,c=n,f="time"===a.type,h=a.type.indexOf("time")<0,g=t.split(a.regExp.dateWords),m=t.split(a.regExp.dateNumbers);if(!h)for(c=e.inArray(a.text.am.toLowerCase(),g)>=0||!(e.inArray(a.text.pm.toLowerCase(),g)>=0)&&n,o=0;o=0){if(d<0||l<0){var y=v.split(":");for(i=0;i=0)break}}for(o=0;o59){p=r,m.splice(o,1);break}if(u<0)for(o=0;o1||a.monthFirst?o:1===o?0:1,r=parseInt(m[i]),!isNaN(r)&&1<=r&&r<=12){u=r,m.splice(i,1);break}for(o=0;o=0;o--)if(r=parseInt(m[o]),!isNaN(r)){r<99&&(r+=2e3),p=r,m.splice(o,1);break}}if(!h){if(d<0)for(o=0;o').addClass(className.popup).prependTo($activator.parent());
117 | }
118 | $container.addClass(className.calendar);
119 | var onVisible = settings.onVisible;
120 | var onHidden = settings.onHidden;
121 | if (!$input.length) {
122 | //no input, $container has to handle focus/blur
123 | $container.attr('tabindex', '0');
124 | onVisible = function () {
125 | module.focus();
126 | return settings.onVisible.apply($container, arguments);
127 | };
128 | onHidden = function () {
129 | module.blur();
130 | return settings.onHidden.apply($container, arguments);
131 | };
132 | }
133 | var onShow = function () {
134 | //reset the focus date onShow
135 | module.set.focusDate(module.get.date());
136 | module.set.mode(settings.startMode);
137 | return settings.onShow.apply($container, arguments);
138 | };
139 | var on = settings.on || ($input.length ? 'focus' : 'click');
140 | var options = $.extend({}, settings.popupOptions, {
141 | popup: $container,
142 | on: on,
143 | hoverable: on === 'hover',
144 | onShow: onShow,
145 | onVisible: onVisible,
146 | onHide: settings.onHide,
147 | onHidden: onHidden
148 | });
149 | module.popup(options);
150 | },
151 | inline: function () {
152 | if ($activator.length && !settings.inline) {
153 | return;
154 | }
155 | $container = $('').addClass(className.calendar).appendTo($module);
156 | if (!$input.length) {
157 | $container.attr('tabindex', '0');
158 | }
159 | },
160 | input: function () {
161 | if (settings.touchReadonly && $input.length && isTouch) {
162 | $input.prop('readonly', true);
163 | }
164 | },
165 | date: function () {
166 | if ($input.length) {
167 | var val = $input.val();
168 | var date = parser.date(val, settings);
169 | module.set.date(date, settings.formatInput, false);
170 | }
171 | }
172 | },
173 |
174 | create: {
175 | calendar: function () {
176 | var i, r, c, p, row, cell, pageGrid;
177 |
178 | var mode = module.get.mode();
179 | var today = new Date();
180 | var date = module.get.date();
181 | var focusDate = module.get.focusDate();
182 | var display = focusDate || date || settings.initialDate || today;
183 | display = module.helper.dateInRange(display);
184 |
185 | if (!focusDate) {
186 | focusDate = display;
187 | module.set.focusDate(focusDate, false, false);
188 | }
189 |
190 | var isYear = mode === 'year';
191 | var isMonth = mode === 'month';
192 | var isDay = mode === 'day';
193 | var isHour = mode === 'hour';
194 | var isMinute = mode === 'minute';
195 | var isTimeOnly = settings.type === 'time';
196 |
197 | var multiMonth = Math.max(settings.multiMonth, 1);
198 | var monthOffset = !isDay ? 0 : module.get.monthOffset();
199 |
200 | var minute = display.getMinutes();
201 | var hour = display.getHours();
202 | var day = display.getDate();
203 | var startMonth = display.getMonth() + monthOffset;
204 | var year = display.getFullYear();
205 |
206 | var columns = isDay ? 7 : isHour ? 4 : 3;
207 | var columnsString = columns === 7 ? 'seven' : columns === 4 ? 'four' : 'three';
208 | var rows = isDay || isHour ? 6 : 4;
209 | var pages = isDay ? multiMonth : 1;
210 |
211 | var container = $container;
212 | container.empty();
213 | if (pages > 1) {
214 | pageGrid = $('').addClass(className.grid).appendTo(container);
215 | }
216 |
217 | for (p = 0; p < pages; p++) {
218 | if (pages > 1) {
219 | var pageColumn = $('').addClass(className.column).appendTo(pageGrid);
220 | container = pageColumn;
221 | }
222 |
223 | var month = startMonth + p;
224 | var firstMonthDayColumn = (new Date(year, month, 1).getDay() - settings.firstDayOfWeek % 7 + 7) % 7;
225 | if (!settings.constantHeight && isDay) {
226 | var requiredCells = new Date(year, month + 1, 0).getDate() + firstMonthDayColumn;
227 | rows = Math.ceil(requiredCells / 7);
228 | }
229 |
230 | var yearChange = isYear ? 10 : isMonth ? 1 : 0;
231 | var monthChange = isDay ? 1 : 0;
232 | var dayChange = isHour || isMinute ? 1 : 0;
233 | var prevNextDay = isHour || isMinute ? day : 1;
234 | var prevDate = new Date(year - yearChange, month - monthChange, prevNextDay - dayChange, hour);
235 | var nextDate = new Date(year + yearChange, month + monthChange, prevNextDay + dayChange, hour);
236 |
237 | var prevLast = isYear ? new Date(Math.ceil(year / 10) * 10 - 9, 0, 0) :
238 | isMonth ? new Date(year, 0, 0) : isDay ? new Date(year, month, 0) : new Date(year, month, day, -1);
239 | var nextFirst = isYear ? new Date(Math.ceil(year / 10) * 10 + 1, 0, 1) :
240 | isMonth ? new Date(year + 1, 0, 1) : isDay ? new Date(year, month + 1, 1) : new Date(year, month, day + 1);
241 |
242 | var table = $('').addClass(className.table).addClass(columnsString + ' column').addClass(mode).appendTo(container);
243 |
244 | //no header for time-only mode
245 | if (!isTimeOnly) {
246 | var thead = $('').appendTo(table);
247 |
248 | row = $('
').appendTo(thead);
249 | cell = $(' | ').attr('colspan', '' + columns).appendTo(row);
250 |
251 | var headerDate = isYear || isMonth ? new Date(year, 0, 1) :
252 | isDay ? new Date(year, month, 1) : new Date(year, month, day, hour, minute);
253 | var headerText = $('').addClass(className.link).appendTo(cell);
254 | headerText.text(formatter.header(headerDate, mode, settings));
255 | var newMode = isMonth ? (settings.disableYear ? 'day' : 'year') :
256 | isDay ? (settings.disableMonth ? 'year' : 'month') : 'day';
257 | headerText.data(metadata.mode, newMode);
258 |
259 | if (p === 0) {
260 | var prev = $('').addClass(className.prev).appendTo(cell);
261 | prev.data(metadata.focusDate, prevDate);
262 | prev.toggleClass(className.disabledCell, !module.helper.isDateInRange(prevLast, mode));
263 | $('').addClass(className.prevIcon).appendTo(prev);
264 | }
265 |
266 | if (p === pages - 1) {
267 | var next = $('').addClass(className.next).appendTo(cell);
268 | next.data(metadata.focusDate, nextDate);
269 | next.toggleClass(className.disabledCell, !module.helper.isDateInRange(nextFirst, mode));
270 | $('').addClass(className.nextIcon).appendTo(next);
271 | }
272 |
273 | if (isDay) {
274 | row = $('
').appendTo(thead);
275 | for (i = 0; i < columns; i++) {
276 | cell = $(' | ').appendTo(row);
277 | cell.text(formatter.dayColumnHeader((i + settings.firstDayOfWeek) % 7, settings));
278 | }
279 | }
280 | }
281 |
282 | var tbody = $('').appendTo(table);
283 | i = isYear ? Math.ceil(year / 10) * 10 - 9 : isDay ? 1 - firstMonthDayColumn : 0;
284 | for (r = 0; r < rows; r++) {
285 | row = $('
').appendTo(tbody);
286 | for (c = 0; c < columns; c++, i++) {
287 | var cellDate = isYear ? new Date(i, month, 1, hour, minute) :
288 | isMonth ? new Date(year, i, 1, hour, minute) : isDay ? new Date(year, month, i, hour, minute) :
289 | isHour ? new Date(year, month, day, i) : new Date(year, month, day, hour, i * 5);
290 | var cellText = isYear ? i :
291 | isMonth ? settings.text.monthsShort[i] : isDay ? cellDate.getDate() :
292 | formatter.time(cellDate, settings, true);
293 | cell = $(' | ').addClass(className.cell).appendTo(row);
294 | cell.text(cellText);
295 | cell.data(metadata.date, cellDate);
296 | var adjacent = isDay && cellDate.getMonth() !== ((month + 12) % 12);
297 | var disabled = adjacent || !module.helper.isDateInRange(cellDate, mode) || settings.isDisabled(cellDate, mode);
298 | var active = module.helper.dateEqual(cellDate, date, mode);
299 | var isToday = module.helper.dateEqual(cellDate, today, mode);
300 | cell.toggleClass(className.adjacentCell, adjacent);
301 | cell.toggleClass(className.disabledCell, disabled);
302 | cell.toggleClass(className.activeCell, active && !adjacent);
303 | if (!isHour && !isMinute) {
304 | cell.toggleClass(className.todayCell, !adjacent && isToday);
305 | }
306 |
307 | // Allow for external modifications of each cell
308 | var cellOptions = {
309 | mode: mode,
310 | adjacent: adjacent,
311 | disabled: disabled,
312 | active: active,
313 | today: isToday
314 | };
315 | formatter.cell(cell, cellDate, cellOptions);
316 |
317 | if (module.helper.dateEqual(cellDate, focusDate, mode)) {
318 | //ensure that the focus date is exactly equal to the cell date
319 | //so that, if selected, the correct value is set
320 | module.set.focusDate(cellDate, false, false);
321 | }
322 | }
323 | }
324 |
325 | if (settings.today) {
326 | var todayRow = $('
').appendTo(tbody);
327 | var todayButton = $(' | ').attr('colspan', '' + columns).addClass(className.today).appendTo(todayRow);
328 | todayButton.text(formatter.today(settings));
329 | todayButton.data(metadata.date, today);
330 | }
331 |
332 | module.update.focus(false, table);
333 | }
334 | }
335 | },
336 |
337 | update: {
338 | focus: function (updateRange, container) {
339 | container = container || $container;
340 | var mode = module.get.mode();
341 | var date = module.get.date();
342 | var focusDate = module.get.focusDate();
343 | var startDate = module.get.startDate();
344 | var endDate = module.get.endDate();
345 | var rangeDate = (updateRange ? focusDate : null) || date || (!isTouch ? focusDate : null);
346 |
347 | container.find('td').each(function () {
348 | var cell = $(this);
349 | var cellDate = cell.data(metadata.date);
350 | if (!cellDate) {
351 | return;
352 | }
353 | var disabled = cell.hasClass(className.disabledCell);
354 | var active = cell.hasClass(className.activeCell);
355 | var adjacent = cell.hasClass(className.adjacentCell);
356 | var focused = module.helper.dateEqual(cellDate, focusDate, mode);
357 | var inRange = !rangeDate ? false :
358 | ((!!startDate && module.helper.isDateInRange(cellDate, mode, startDate, rangeDate)) ||
359 | (!!endDate && module.helper.isDateInRange(cellDate, mode, rangeDate, endDate)));
360 | cell.toggleClass(className.focusCell, focused && (!isTouch || isTouchDown) && !adjacent);
361 | cell.toggleClass(className.rangeCell, inRange && !active && !disabled);
362 | });
363 | }
364 | },
365 |
366 | refresh: function () {
367 | module.create.calendar();
368 | },
369 |
370 | bind: {
371 | events: function () {
372 | $container.on('mousedown' + eventNamespace, module.event.mousedown);
373 | $container.on('touchstart' + eventNamespace, module.event.mousedown);
374 | $container.on('mouseup' + eventNamespace, module.event.mouseup);
375 | $container.on('touchend' + eventNamespace, module.event.mouseup);
376 | $container.on('mouseover' + eventNamespace, module.event.mouseover);
377 | if ($input.length) {
378 | $input.on('input' + eventNamespace, module.event.inputChange);
379 | $input.on('focus' + eventNamespace, module.event.inputFocus);
380 | $input.on('blur' + eventNamespace, module.event.inputBlur);
381 | $input.on('click' + eventNamespace, module.event.inputClick);
382 | $input.on('keydown' + eventNamespace, module.event.keydown);
383 | } else {
384 | $container.on('keydown' + eventNamespace, module.event.keydown);
385 | }
386 | }
387 | },
388 |
389 | unbind: {
390 | events: function () {
391 | $container.off(eventNamespace);
392 | if ($input.length) {
393 | $input.off(eventNamespace);
394 | }
395 | }
396 | },
397 |
398 | event: {
399 | mouseover: function (event) {
400 | var target = $(event.target);
401 | var date = target.data(metadata.date);
402 | var mousedown = event.buttons === 1;
403 | if (date) {
404 | module.set.focusDate(date, false, true, mousedown);
405 | }
406 | },
407 | mousedown: function (event) {
408 | if ($input.length) {
409 | //prevent the mousedown on the calendar causing the input to lose focus
410 | event.preventDefault();
411 | }
412 | isTouchDown = event.type.indexOf('touch') >= 0;
413 | var target = $(event.target);
414 | var date = target.data(metadata.date);
415 | if (date) {
416 | module.set.focusDate(date, false, true, true);
417 | }
418 | },
419 | mouseup: function (event) {
420 | //ensure input has focus so that it receives keydown events for calendar navigation
421 | module.focus();
422 | event.preventDefault();
423 | event.stopPropagation();
424 | isTouchDown = false;
425 | var target = $(event.target);
426 | var parent = target.parent();
427 | if (parent.data(metadata.date) || parent.data(metadata.focusDate) || parent.data(metadata.mode)) {
428 | //clicked on a child element, switch to parent (used when clicking directly on prev/next icon element)
429 | target = parent;
430 | }
431 | var date = target.data(metadata.date);
432 | var focusDate = target.data(metadata.focusDate);
433 | var mode = target.data(metadata.mode);
434 | if (date) {
435 | var forceSet = target.hasClass(className.today);
436 | module.selectDate(date, forceSet);
437 | }
438 | else if (focusDate) {
439 | module.set.focusDate(focusDate);
440 | }
441 | else if (mode) {
442 | module.set.mode(mode);
443 | }
444 | },
445 | keydown: function (event) {
446 | if (event.keyCode === 27 || event.keyCode === 9) {
447 | //esc || tab
448 | module.popup('hide');
449 | }
450 |
451 | if (module.popup('is visible')) {
452 | if (event.keyCode === 37 || event.keyCode === 38 || event.keyCode === 39 || event.keyCode === 40) {
453 | //arrow keys
454 | var mode = module.get.mode();
455 | var bigIncrement = mode === 'day' ? 7 : mode === 'hour' ? 4 : 3;
456 | var increment = event.keyCode === 37 ? -1 : event.keyCode === 38 ? -bigIncrement : event.keyCode == 39 ? 1 : bigIncrement;
457 | increment *= mode === 'minute' ? 5 : 1;
458 | var focusDate = module.get.focusDate() || module.get.date() || new Date();
459 | var year = focusDate.getFullYear() + (mode === 'year' ? increment : 0);
460 | var month = focusDate.getMonth() + (mode === 'month' ? increment : 0);
461 | var day = focusDate.getDate() + (mode === 'day' ? increment : 0);
462 | var hour = focusDate.getHours() + (mode === 'hour' ? increment : 0);
463 | var minute = focusDate.getMinutes() + (mode === 'minute' ? increment : 0);
464 | var newFocusDate = new Date(year, month, day, hour, minute);
465 | if (settings.type === 'time') {
466 | newFocusDate = module.helper.mergeDateTime(focusDate, newFocusDate);
467 | }
468 | if (module.helper.isDateInRange(newFocusDate, mode)) {
469 | module.set.focusDate(newFocusDate);
470 | }
471 | } else if (event.keyCode === 13) {
472 | //enter
473 | var mode = module.get.mode();
474 | var date = module.get.focusDate();
475 | if (date && !settings.isDisabled(date, mode)) {
476 | module.selectDate(date);
477 | }
478 | //disable form submission:
479 | event.preventDefault();
480 | event.stopPropagation();
481 | }
482 | }
483 |
484 | if (event.keyCode === 38 || event.keyCode === 40) {
485 | //arrow-up || arrow-down
486 | event.preventDefault(); //don't scroll
487 | module.popup('show');
488 | }
489 | },
490 | inputChange: function () {
491 | var val = $input.val();
492 | var date = parser.date(val, settings);
493 | module.set.date(date, false);
494 | },
495 | inputFocus: function () {
496 | $container.addClass(className.active);
497 | },
498 | inputBlur: function () {
499 | $container.removeClass(className.active);
500 | if (settings.formatInput) {
501 | var date = module.get.date();
502 | var text = formatter.datetime(date, settings);
503 | $input.val(text);
504 | }
505 | },
506 | inputClick: function () {
507 | module.popup('show');
508 | }
509 | },
510 |
511 | get: {
512 | date: function () {
513 | return $module.data(metadata.date) || null;
514 | },
515 | focusDate: function () {
516 | return $module.data(metadata.focusDate) || null;
517 | },
518 | startDate: function () {
519 | var startModule = module.get.calendarModule(settings.startCalendar);
520 | return (startModule ? startModule.get.date() : $module.data(metadata.startDate)) || null;
521 | },
522 | endDate: function () {
523 | var endModule = module.get.calendarModule(settings.endCalendar);
524 | return (endModule ? endModule.get.date() : $module.data(metadata.endDate)) || null;
525 | },
526 | monthOffset: function () {
527 | return $module.data(metadata.monthOffset) || 0;
528 | },
529 | mode: function () {
530 | //only returns valid modes for the current settings
531 | var mode = $module.data(metadata.mode) || settings.startMode;
532 | var validModes = module.get.validModes();
533 | if ($.inArray(mode, validModes) >= 0) {
534 | return mode;
535 | }
536 | return settings.type === 'time' ? 'hour' :
537 | settings.type === 'month' ? 'month' :
538 | settings.type === 'year' ? 'year' : 'day';
539 | },
540 | validModes: function () {
541 | var validModes = [];
542 | if (settings.type !== 'time') {
543 | if (!settings.disableYear || settings.type === 'year') {
544 | validModes.push('year');
545 | }
546 | if (!(settings.disableMonth || settings.type === 'year') || settings.type === 'month') {
547 | validModes.push('month');
548 | }
549 | if (settings.type.indexOf('date') >= 0) {
550 | validModes.push('day');
551 | }
552 | }
553 | if (settings.type.indexOf('time') >= 0) {
554 | validModes.push('hour');
555 | if (!settings.disableMinute) {
556 | validModes.push('minute');
557 | }
558 | }
559 | return validModes;
560 | },
561 | isTouch: function () {
562 | try {
563 | document.createEvent('TouchEvent');
564 | return true;
565 | }
566 | catch (e) {
567 | return false;
568 | }
569 | },
570 | calendarModule: function (selector) {
571 | if (!selector) {
572 | return null;
573 | }
574 | if (!(selector instanceof $)) {
575 | selector = $module.parent().children(selector).first();
576 | }
577 | //assume range related calendars are using the same namespace
578 | return selector.data(moduleNamespace);
579 | }
580 | },
581 |
582 | set: {
583 | date: function (date, updateInput, fireChange) {
584 | updateInput = updateInput !== false;
585 | fireChange = fireChange !== false;
586 | date = module.helper.sanitiseDate(date);
587 | date = module.helper.dateInRange(date);
588 |
589 | var mode = module.get.mode();
590 | var text = formatter.datetime(date, settings);
591 | if (fireChange && settings.onChange.call(element, date, text, mode) === false) {
592 | return false;
593 | }
594 |
595 | module.set.focusDate(date);
596 |
597 | if (settings.isDisabled(date, mode)) {
598 | return false;
599 | }
600 |
601 | var endDate = module.get.endDate();
602 | if (!!endDate && !!date && date > endDate) {
603 | //selected date is greater than end date in range, so clear end date
604 | module.set.endDate(undefined);
605 | }
606 | module.set.dataKeyValue(metadata.date, date);
607 |
608 | if (updateInput && $input.length) {
609 | $input.val(text);
610 | }
611 | },
612 | startDate: function (date, refreshCalendar) {
613 | date = module.helper.sanitiseDate(date);
614 | var startModule = module.get.calendarModule(settings.startCalendar);
615 | if (startModule) {
616 | startModule.set.date(date);
617 | }
618 | module.set.dataKeyValue(metadata.startDate, date, refreshCalendar);
619 | },
620 | endDate: function (date, refreshCalendar) {
621 | date = module.helper.sanitiseDate(date);
622 | var endModule = module.get.calendarModule(settings.endCalendar);
623 | if (endModule) {
624 | endModule.set.date(date);
625 | }
626 | module.set.dataKeyValue(metadata.endDate, date, refreshCalendar);
627 | },
628 | focusDate: function (date, refreshCalendar, updateFocus, updateRange) {
629 | date = module.helper.sanitiseDate(date);
630 | date = module.helper.dateInRange(date);
631 | var isDay = module.get.mode() === 'day';
632 | var oldFocusDate = module.get.focusDate();
633 | if (isDay && date && oldFocusDate) {
634 | var yearDelta = date.getFullYear() - oldFocusDate.getFullYear();
635 | var monthDelta = yearDelta * 12 + date.getMonth() - oldFocusDate.getMonth();
636 | if (monthDelta) {
637 | var monthOffset = module.get.monthOffset() - monthDelta;
638 | module.set.monthOffset(monthOffset, false);
639 | }
640 | }
641 | var changed = module.set.dataKeyValue(metadata.focusDate, date, refreshCalendar);
642 | updateFocus = (updateFocus !== false && changed && refreshCalendar === false) || focusDateUsedForRange != updateRange;
643 | focusDateUsedForRange = updateRange;
644 | if (updateFocus) {
645 | module.update.focus(updateRange);
646 | }
647 | },
648 | monthOffset: function (monthOffset, refreshCalendar) {
649 | var multiMonth = Math.max(settings.multiMonth, 1);
650 | monthOffset = Math.max(1 - multiMonth, Math.min(0, monthOffset));
651 | module.set.dataKeyValue(metadata.monthOffset, monthOffset, refreshCalendar);
652 | },
653 | mode: function (mode, refreshCalendar) {
654 | module.set.dataKeyValue(metadata.mode, mode, refreshCalendar);
655 | },
656 | dataKeyValue: function (key, value, refreshCalendar) {
657 | var oldValue = $module.data(key);
658 | var equal = oldValue === value || (oldValue <= value && oldValue >= value); //equality test for dates and string objects
659 | if (value) {
660 | $module.data(key, value);
661 | } else {
662 | $module.removeData(key);
663 | }
664 | refreshCalendar = refreshCalendar !== false && !equal;
665 | if (refreshCalendar) {
666 | module.create.calendar();
667 | }
668 | return !equal;
669 | }
670 | },
671 |
672 | selectDate: function (date, forceSet) {
673 | var mode = module.get.mode();
674 | var complete = forceSet || mode === 'minute' ||
675 | (settings.disableMinute && mode === 'hour') ||
676 | (settings.type === 'date' && mode === 'day') ||
677 | (settings.type === 'month' && mode === 'month') ||
678 | (settings.type === 'year' && mode === 'year');
679 | if (complete) {
680 | var canceled = module.set.date(date) === false;
681 | if (!canceled && settings.closable) {
682 | module.popup('hide');
683 | //if this is a range calendar, show the end date calendar popup and focus the input
684 | var endModule = module.get.calendarModule(settings.endCalendar);
685 | if (endModule) {
686 | endModule.popup('show');
687 | endModule.focus();
688 | }
689 | }
690 | } else {
691 | var newMode = mode === 'year' ? (!settings.disableMonth ? 'month' : 'day') :
692 | mode === 'month' ? 'day' : mode === 'day' ? 'hour' : 'minute';
693 | module.set.mode(newMode);
694 | if (mode === 'hour' || (mode === 'day' && module.get.date())) {
695 | //the user has chosen enough to consider a valid date/time has been chosen
696 | module.set.date(date);
697 | } else {
698 | module.set.focusDate(date);
699 | }
700 | }
701 | },
702 |
703 | changeDate: function (date) {
704 | module.set.date(date);
705 | },
706 |
707 | clear: function () {
708 | module.set.date(undefined);
709 | },
710 |
711 | popup: function () {
712 | return $activator.popup.apply($activator, arguments);
713 | },
714 |
715 | focus: function () {
716 | if ($input.length) {
717 | $input.focus();
718 | } else {
719 | $container.focus();
720 | }
721 | },
722 | blur: function () {
723 | if ($input.length) {
724 | $input.blur();
725 | } else {
726 | $container.blur();
727 | }
728 | },
729 |
730 | helper: {
731 | sanitiseDate: function (date) {
732 | if (!date) {
733 | return undefined;
734 | }
735 | if (!(date instanceof Date)) {
736 | date = parser.date('' + date, settings);
737 | }
738 | if (isNaN(date.getTime())) {
739 | return undefined;
740 | }
741 | return date;
742 | },
743 | dateDiff: function (date1, date2, mode) {
744 | mode = mode || 'day';
745 | var isTimeOnly = settings.type === 'time';
746 | var isYear = mode === 'year';
747 | var isYearOrMonth = isYear || mode === 'month';
748 | var isMinute = mode === 'minute';
749 | var isHourOrMinute = isMinute || mode === 'hour';
750 | //only care about a minute accuracy of 5
751 | date1 = new Date(
752 | isTimeOnly ? 2000 : date1.getFullYear(),
753 | isTimeOnly ? 0 : isYear ? 0 : date1.getMonth(),
754 | isTimeOnly ? 1 : isYearOrMonth ? 1 : date1.getDate(),
755 | !isHourOrMinute ? 0 : date1.getHours(),
756 | !isMinute ? 0 : 5 * Math.floor(date1.getMinutes() / 5));
757 | date2 = new Date(
758 | isTimeOnly ? 2000 : date2.getFullYear(),
759 | isTimeOnly ? 0 : isYear ? 0 : date2.getMonth(),
760 | isTimeOnly ? 1 : isYearOrMonth ? 1 : date2.getDate(),
761 | !isHourOrMinute ? 0 : date2.getHours(),
762 | !isMinute ? 0 : 5 * Math.floor(date2.getMinutes() / 5));
763 | return date2.getTime() - date1.getTime();
764 | },
765 | dateEqual: function (date1, date2, mode) {
766 | return !!date1 && !!date2 && module.helper.dateDiff(date1, date2, mode) === 0;
767 | },
768 | isDateInRange: function (date, mode, minDate, maxDate) {
769 | if (!minDate && !maxDate) {
770 | var startDate = module.get.startDate();
771 | minDate = startDate && settings.minDate ? new Date(Math.max(startDate, settings.minDate)) : startDate || settings.minDate;
772 | maxDate = settings.maxDate;
773 | }
774 | minDate = minDate && new Date(minDate.getFullYear(), minDate.getMonth(), minDate.getDate(), minDate.getHours(), 5 * Math.ceil(minDate.getMinutes() / 5));
775 | return !(!date ||
776 | (minDate && module.helper.dateDiff(date, minDate, mode) > 0) ||
777 | (maxDate && module.helper.dateDiff(maxDate, date, mode) > 0));
778 | },
779 | dateInRange: function (date, minDate, maxDate) {
780 | if (!minDate && !maxDate) {
781 | var startDate = module.get.startDate();
782 | minDate = startDate && settings.minDate ? new Date(Math.max(startDate, settings.minDate)) : startDate || settings.minDate;
783 | maxDate = settings.maxDate;
784 | }
785 | minDate = minDate && new Date(minDate.getFullYear(), minDate.getMonth(), minDate.getDate(), minDate.getHours(), 5 * Math.ceil(minDate.getMinutes() / 5));
786 | var isTimeOnly = settings.type === 'time';
787 | return !date ? date :
788 | (minDate && module.helper.dateDiff(date, minDate, 'minute') > 0) ?
789 | (isTimeOnly ? module.helper.mergeDateTime(date, minDate) : minDate) :
790 | (maxDate && module.helper.dateDiff(maxDate, date, 'minute') > 0) ?
791 | (isTimeOnly ? module.helper.mergeDateTime(date, maxDate) : maxDate) :
792 | date;
793 | },
794 | mergeDateTime: function (date, time) {
795 | return (!date || !time) ? time :
796 | new Date(date.getFullYear(), date.getMonth(), date.getDate(), time.getHours(), time.getMinutes());
797 | }
798 | },
799 |
800 | setting: function (name, value) {
801 | module.debug('Changing setting', name, value);
802 | if ($.isPlainObject(name)) {
803 | $.extend(true, settings, name);
804 | }
805 | else if (value !== undefined) {
806 | if ($.isPlainObject(settings[name])) {
807 | $.extend(true, settings[name], value);
808 | }
809 | else {
810 | settings[name] = value;
811 | }
812 | }
813 | else {
814 | return settings[name];
815 | }
816 | },
817 | internal: function (name, value) {
818 | module.debug('Changing internal', name, value);
819 | if (value !== undefined) {
820 | if ($.isPlainObject(name)) {
821 | $.extend(true, module, name);
822 | }
823 | else {
824 | module[name] = value;
825 | }
826 | }
827 | else {
828 | return module[name];
829 | }
830 | },
831 | debug: function () {
832 | if (!settings.silent && settings.debug) {
833 | if (settings.performance) {
834 | module.performance.log(arguments);
835 | }
836 | else {
837 | module.debug = Function.prototype.bind.call(console.info, console, settings.name + ':');
838 | module.debug.apply(console, arguments);
839 | }
840 | }
841 | },
842 | verbose: function () {
843 | if (!settings.silent && settings.verbose && settings.debug) {
844 | if (settings.performance) {
845 | module.performance.log(arguments);
846 | }
847 | else {
848 | module.verbose = Function.prototype.bind.call(console.info, console, settings.name + ':');
849 | module.verbose.apply(console, arguments);
850 | }
851 | }
852 | },
853 | error: function () {
854 | if (!settings.silent) {
855 | module.error = Function.prototype.bind.call(console.error, console, settings.name + ':');
856 | module.error.apply(console, arguments);
857 | }
858 | },
859 | performance: {
860 | log: function (message) {
861 | var
862 | currentTime,
863 | executionTime,
864 | previousTime
865 | ;
866 | if (settings.performance) {
867 | currentTime = new Date().getTime();
868 | previousTime = time || currentTime;
869 | executionTime = currentTime - previousTime;
870 | time = currentTime;
871 | performance.push({
872 | 'Name': message[0],
873 | 'Arguments': [].slice.call(message, 1) || '',
874 | 'Element': element,
875 | 'Execution Time': executionTime
876 | });
877 | }
878 | clearTimeout(module.performance.timer);
879 | module.performance.timer = setTimeout(module.performance.display, 500);
880 | },
881 | display: function () {
882 | var
883 | title = settings.name + ':',
884 | totalTime = 0
885 | ;
886 | time = false;
887 | clearTimeout(module.performance.timer);
888 | $.each(performance, function (index, data) {
889 | totalTime += data['Execution Time'];
890 | });
891 | title += ' ' + totalTime + 'ms';
892 | if (moduleSelector) {
893 | title += ' \'' + moduleSelector + '\'';
894 | }
895 | if ((console.group !== undefined || console.table !== undefined) && performance.length > 0) {
896 | console.groupCollapsed(title);
897 | if (console.table) {
898 | console.table(performance);
899 | }
900 | else {
901 | $.each(performance, function (index, data) {
902 | console.log(data['Name'] + ': ' + data['Execution Time'] + 'ms');
903 | });
904 | }
905 | console.groupEnd();
906 | }
907 | performance = [];
908 | }
909 | },
910 | invoke: function (query, passedArguments, context) {
911 | var
912 | object = instance,
913 | maxDepth,
914 | found,
915 | response
916 | ;
917 | passedArguments = passedArguments || queryArguments;
918 | context = element || context;
919 | if (typeof query == 'string' && object !== undefined) {
920 | query = query.split(/[\. ]/);
921 | maxDepth = query.length - 1;
922 | $.each(query, function (depth, value) {
923 | var camelCaseValue = (depth != maxDepth)
924 | ? value + query[depth + 1].charAt(0).toUpperCase() + query[depth + 1].slice(1)
925 | : query
926 | ;
927 | if ($.isPlainObject(object[camelCaseValue]) && (depth != maxDepth)) {
928 | object = object[camelCaseValue];
929 | }
930 | else if (object[camelCaseValue] !== undefined) {
931 | found = object[camelCaseValue];
932 | return false;
933 | }
934 | else if ($.isPlainObject(object[value]) && (depth != maxDepth)) {
935 | object = object[value];
936 | }
937 | else if (object[value] !== undefined) {
938 | found = object[value];
939 | return false;
940 | }
941 | else {
942 | module.error(error.method, query);
943 | return false;
944 | }
945 | });
946 | }
947 | if ($.isFunction(found)) {
948 | response = found.apply(context, passedArguments);
949 | }
950 | else if (found !== undefined) {
951 | response = found;
952 | }
953 | if ($.isArray(returnedValue)) {
954 | returnedValue.push(response);
955 | }
956 | else if (returnedValue !== undefined) {
957 | returnedValue = [returnedValue, response];
958 | }
959 | else if (response !== undefined) {
960 | returnedValue = response;
961 | }
962 | return found;
963 | }
964 | };
965 |
966 | if (methodInvoked) {
967 | if (instance === undefined) {
968 | module.initialize();
969 | }
970 | module.invoke(query);
971 | }
972 | else {
973 | if (instance !== undefined) {
974 | instance.invoke('destroy');
975 | }
976 | module.initialize();
977 | }
978 | })
979 | ;
980 | return (returnedValue !== undefined)
981 | ? returnedValue
982 | : this
983 | ;
984 | };
985 |
986 | $.fn.calendar.settings = {
987 |
988 | name: 'Calendar',
989 | namespace: 'calendar',
990 |
991 | silent: false,
992 | debug: false,
993 | verbose: false,
994 | performance: false,
995 |
996 | type: 'datetime', // picker type, can be 'datetime', 'date', 'time', 'month', or 'year'
997 | firstDayOfWeek: 0, // day for first day column (0 = Sunday)
998 | constantHeight: true, // add rows to shorter months to keep day calendar height consistent (6 rows)
999 | today: false, // show a 'today/now' button at the bottom of the calendar
1000 | closable: true, // close the popup after selecting a date/time
1001 | monthFirst: true, // month before day when parsing/converting date from/to text
1002 | touchReadonly: true, // set input to readonly on touch devices
1003 | inline: false, // create the calendar inline instead of inside a popup
1004 | on: null, // when to show the popup (defaults to 'focus' for input, 'click' for others)
1005 | initialDate: null, // date to display initially when no date is selected (null = now)
1006 | startMode: false, // display mode to start in, can be 'year', 'month', 'day', 'hour', 'minute' (false = 'day')
1007 | minDate: null, // minimum date/time that can be selected, dates/times before are disabled
1008 | maxDate: null, // maximum date/time that can be selected, dates/times after are disabled
1009 | ampm: true, // show am/pm in time mode
1010 | disableYear: false, // disable year selection mode
1011 | disableMonth: false, // disable month selection mode
1012 | disableMinute: false, // disable minute selection mode
1013 | formatInput: true, // format the input text upon input blur and module creation
1014 | startCalendar: null, // jquery object or selector for another calendar that represents the start date of a date range
1015 | endCalendar: null, // jquery object or selector for another calendar that represents the end date of a date range
1016 | multiMonth: 1, // show multiple months when in 'day' mode
1017 |
1018 | // popup options ('popup', 'on', 'hoverable', and show/hide callbacks are overridden)
1019 | popupOptions: {
1020 | position: 'bottom left',
1021 | lastResort: 'bottom left',
1022 | prefer: 'opposite',
1023 | hideOnScroll: false
1024 | },
1025 |
1026 | text: {
1027 | days: ['S', 'M', 'T', 'W', 'T', 'F', 'S'],
1028 | months: ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'],
1029 | monthsShort: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'],
1030 | today: 'Today',
1031 | now: 'Now',
1032 | am: 'AM',
1033 | pm: 'PM'
1034 | },
1035 |
1036 | formatter: {
1037 | header: function (date, mode, settings) {
1038 | return mode === 'year' ? settings.formatter.yearHeader(date, settings) :
1039 | mode === 'month' ? settings.formatter.monthHeader(date, settings) :
1040 | mode === 'day' ? settings.formatter.dayHeader(date, settings) :
1041 | mode === 'hour' ? settings.formatter.hourHeader(date, settings) :
1042 | settings.formatter.minuteHeader(date, settings);
1043 | },
1044 | yearHeader: function (date, settings) {
1045 | var decadeYear = Math.ceil(date.getFullYear() / 10) * 10;
1046 | return (decadeYear - 9) + ' - ' + (decadeYear + 2);
1047 | },
1048 | monthHeader: function (date, settings) {
1049 | return date.getFullYear();
1050 | },
1051 | dayHeader: function (date, settings) {
1052 | var month = settings.text.months[date.getMonth()];
1053 | var year = date.getFullYear();
1054 | return month + ' ' + year;
1055 | },
1056 | hourHeader: function (date, settings) {
1057 | return settings.formatter.date(date, settings);
1058 | },
1059 | minuteHeader: function (date, settings) {
1060 | return settings.formatter.date(date, settings);
1061 | },
1062 | dayColumnHeader: function (day, settings) {
1063 | return settings.text.days[day];
1064 | },
1065 | datetime: function (date, settings) {
1066 | if (!date) {
1067 | return '';
1068 | }
1069 | var day = settings.type === 'time' ? '' : settings.formatter.date(date, settings);
1070 | var time = settings.type.indexOf('time') < 0 ? '' : settings.formatter.time(date, settings, false);
1071 | var separator = settings.type === 'datetime' ? ' ' : '';
1072 | return day + separator + time;
1073 | },
1074 | date: function (date, settings) {
1075 | if (!date) {
1076 | return '';
1077 | }
1078 | var day = date.getDate();
1079 | var month = settings.text.months[date.getMonth()];
1080 | var year = date.getFullYear();
1081 | return settings.type === 'year' ? year :
1082 | settings.type === 'month' ? month + ' ' + year :
1083 | (settings.monthFirst ? month + ' ' + day : day + ' ' + month) + ', ' + year;
1084 | },
1085 | time: function (date, settings, forCalendar) {
1086 | if (!date) {
1087 | return '';
1088 | }
1089 | var hour = date.getHours();
1090 | var minute = date.getMinutes();
1091 | var ampm = '';
1092 | if (settings.ampm) {
1093 | ampm = ' ' + (hour < 12 ? settings.text.am : settings.text.pm);
1094 | hour = hour === 0 ? 12 : hour > 12 ? hour - 12 : hour;
1095 | }
1096 | return hour + ':' + (minute < 10 ? '0' : '') + minute + ampm;
1097 | },
1098 | today: function (settings) {
1099 | return settings.type === 'date' ? settings.text.today : settings.text.now;
1100 | },
1101 | cell: function (cell, date, cellOptions) {
1102 | }
1103 | },
1104 |
1105 | parser: {
1106 | date: function (text, settings) {
1107 | if (!text) {
1108 | return null;
1109 | }
1110 | text = ('' + text).trim().toLowerCase();
1111 | if (text.length === 0) {
1112 | return null;
1113 | }
1114 |
1115 | var i, j, k;
1116 | var minute = -1, hour = -1, day = -1, month = -1, year = -1;
1117 | var isAm = undefined;
1118 |
1119 | var isTimeOnly = settings.type === 'time';
1120 | var isDateOnly = settings.type.indexOf('time') < 0;
1121 |
1122 | var words = text.split(settings.regExp.dateWords);
1123 | var numbers = text.split(settings.regExp.dateNumbers);
1124 |
1125 | if (!isDateOnly) {
1126 | //am/pm
1127 | isAm = $.inArray(settings.text.am.toLowerCase(), words) >= 0 ? true :
1128 | $.inArray(settings.text.pm.toLowerCase(), words) >= 0 ? false : undefined;
1129 |
1130 | //time with ':'
1131 | for (i = 0; i < numbers.length; i++) {
1132 | var number = numbers[i];
1133 | if (number.indexOf(':') >= 0) {
1134 | if (hour < 0 || minute < 0) {
1135 | var parts = number.split(':');
1136 | for (k = 0; k < Math.min(2, parts.length); k++) {
1137 | j = parseInt(parts[k]);
1138 | if (isNaN(j)) {
1139 | j = 0;
1140 | }
1141 | if (k === 0) {
1142 | hour = j % 24;
1143 | } else {
1144 | minute = j % 60;
1145 | }
1146 | }
1147 | }
1148 | numbers.splice(i, 1);
1149 | }
1150 | }
1151 | }
1152 |
1153 | if (!isTimeOnly) {
1154 | //textual month
1155 | for (i = 0; i < words.length; i++) {
1156 | var word = words[i];
1157 | if (word.length <= 0) {
1158 | continue;
1159 | }
1160 | word = word.substring(0, Math.min(word.length, 3));
1161 | for (j = 0; j < settings.text.months.length; j++) {
1162 | var monthString = settings.text.months[j];
1163 | monthString = monthString.substring(0, Math.min(word.length, Math.min(monthString.length, 3))).toLowerCase();
1164 | if (monthString === word) {
1165 | month = j + 1;
1166 | break;
1167 | }
1168 | }
1169 | if (month >= 0) {
1170 | break;
1171 | }
1172 | }
1173 |
1174 | //year > 59
1175 | for (i = 0; i < numbers.length; i++) {
1176 | j = parseInt(numbers[i]);
1177 | if (isNaN(j)) {
1178 | continue;
1179 | }
1180 | if (j > 59) {
1181 | year = j;
1182 | numbers.splice(i, 1);
1183 | break;
1184 | }
1185 | }
1186 |
1187 | //numeric month
1188 | if (month < 0) {
1189 | for (i = 0; i < numbers.length; i++) {
1190 | k = i > 1 || settings.monthFirst ? i : i === 1 ? 0 : 1;
1191 | j = parseInt(numbers[k]);
1192 | if (isNaN(j)) {
1193 | continue;
1194 | }
1195 | if (1 <= j && j <= 12) {
1196 | month = j;
1197 | numbers.splice(k, 1);
1198 | break;
1199 | }
1200 | }
1201 | }
1202 |
1203 | //day
1204 | for (i = 0; i < numbers.length; i++) {
1205 | j = parseInt(numbers[i]);
1206 | if (isNaN(j)) {
1207 | continue;
1208 | }
1209 | if (1 <= j && j <= 31) {
1210 | day = j;
1211 | numbers.splice(i, 1);
1212 | break;
1213 | }
1214 | }
1215 |
1216 | //year <= 59
1217 | if (year < 0) {
1218 | for (i = numbers.length - 1; i >= 0; i--) {
1219 | j = parseInt(numbers[i]);
1220 | if (isNaN(j)) {
1221 | continue;
1222 | }
1223 | if (j < 99) {
1224 | j += 2000;
1225 | }
1226 | year = j;
1227 | numbers.splice(i, 1);
1228 | break;
1229 | }
1230 | }
1231 | }
1232 |
1233 | if (!isDateOnly) {
1234 | //hour
1235 | if (hour < 0) {
1236 | for (i = 0; i < numbers.length; i++) {
1237 | j = parseInt(numbers[i]);
1238 | if (isNaN(j)) {
1239 | continue;
1240 | }
1241 | if (0 <= j && j <= 23) {
1242 | hour = j;
1243 | numbers.splice(i, 1);
1244 | break;
1245 | }
1246 | }
1247 | }
1248 |
1249 | //minute
1250 | if (minute < 0) {
1251 | for (i = 0; i < numbers.length; i++) {
1252 | j = parseInt(numbers[i]);
1253 | if (isNaN(j)) {
1254 | continue;
1255 | }
1256 | if (0 <= j && j <= 59) {
1257 | minute = j;
1258 | numbers.splice(i, 1);
1259 | break;
1260 | }
1261 | }
1262 | }
1263 | }
1264 |
1265 | if (minute < 0 && hour < 0 && day < 0 && month < 0 && year < 0) {
1266 | return null;
1267 | }
1268 |
1269 | if (minute < 0) {
1270 | minute = 0;
1271 | }
1272 | if (hour < 0) {
1273 | hour = 0;
1274 | }
1275 | if (day < 0) {
1276 | day = 1;
1277 | }
1278 | if (month < 0) {
1279 | month = 1;
1280 | }
1281 | if (year < 0) {
1282 | year = new Date().getFullYear();
1283 | }
1284 |
1285 | if (isAm !== undefined) {
1286 | if (isAm) {
1287 | if (hour === 12) {
1288 | hour = 0;
1289 | }
1290 | } else if (hour < 12) {
1291 | hour += 12;
1292 | }
1293 | }
1294 |
1295 | var date = new Date(year, month - 1, day, hour, minute);
1296 | if (date.getMonth() !== month - 1 || date.getFullYear() !== year) {
1297 | //month or year don't match up, switch to last day of the month
1298 | date = new Date(year, month, 0, hour, minute);
1299 | }
1300 | return isNaN(date.getTime()) ? null : date;
1301 | }
1302 | },
1303 |
1304 | // callback when date changes, return false to cancel the change
1305 | onChange: function (date, text, mode) {
1306 | return true;
1307 | },
1308 |
1309 | // callback before show animation, return false to prevent show
1310 | onShow: function () {
1311 | },
1312 |
1313 | // callback after show animation
1314 | onVisible: function () {
1315 | },
1316 |
1317 | // callback before hide animation, return false to prevent hide
1318 | onHide: function () {
1319 | },
1320 |
1321 | // callback after hide animation
1322 | onHidden: function () {
1323 | },
1324 |
1325 | // is the given date disabled?
1326 | isDisabled: function (date, mode) {
1327 | return false;
1328 | },
1329 |
1330 | selector: {
1331 | popup: '.ui.popup',
1332 | input: 'input',
1333 | activator: 'input'
1334 | },
1335 |
1336 | regExp: {
1337 | dateWords: /[^A-Za-z\u00C0-\u024F]+/g,
1338 | dateNumbers: /[^\d:]+/g
1339 | },
1340 |
1341 | error: {
1342 | popup: 'UI Popup, a required component is not included in this page',
1343 | method: 'The method you called is not defined.'
1344 | },
1345 |
1346 | className: {
1347 | calendar: 'calendar',
1348 | active: 'active',
1349 | popup: 'ui popup',
1350 | grid: 'ui equal width grid',
1351 | column: 'column',
1352 | table: 'ui celled center aligned unstackable table',
1353 | prev: 'prev link',
1354 | next: 'next link',
1355 | prevIcon: 'chevron left icon',
1356 | nextIcon: 'chevron right icon',
1357 | link: 'link',
1358 | cell: 'link',
1359 | disabledCell: 'disabled',
1360 | adjacentCell: 'adjacent',
1361 | activeCell: 'active',
1362 | rangeCell: 'range',
1363 | focusCell: 'focus',
1364 | todayCell: 'today',
1365 | today: 'today link'
1366 | },
1367 |
1368 | metadata: {
1369 | date: 'date',
1370 | focusDate: 'focusDate',
1371 | startDate: 'startDate',
1372 | endDate: 'endDate',
1373 | mode: 'mode',
1374 | monthOffset: 'monthOffset'
1375 | }
1376 | };
1377 |
1378 | })(jQuery, window, document);
1379 |
--------------------------------------------------------------------------------
/src/definitions/modules/calendar.js:
--------------------------------------------------------------------------------
1 | /*
2 | * # Semantic UI - Calendar
3 | * http://github.com/semantic-org/semantic-ui/
4 | *
5 | *
6 | * Released under the MIT license
7 | * http://opensource.org/licenses/MIT
8 | */
9 |
10 | ;
11 | (function ($, window, document, undefined) {
12 |
13 | "use strict";
14 |
15 | window = (typeof window != 'undefined' && window.Math == Math)
16 | ? window
17 | : (typeof self != 'undefined' && self.Math == Math)
18 | ? self
19 | : Function('return this')()
20 | ;
21 |
22 | $.fn.calendar = function (parameters) {
23 |
24 | var
25 | $allModules = $(this),
26 |
27 | moduleSelector = $allModules.selector || '',
28 |
29 | time = new Date().getTime(),
30 | performance = [],
31 |
32 | query = arguments[0],
33 | methodInvoked = (typeof query == 'string'),
34 | queryArguments = [].slice.call(arguments, 1),
35 | returnedValue
36 | ;
37 |
38 | $allModules
39 | .each(function () {
40 | var
41 | settings = ( $.isPlainObject(parameters) )
42 | ? $.extend(true, {}, $.fn.calendar.settings, parameters)
43 | : $.extend({}, $.fn.calendar.settings),
44 |
45 | className = settings.className,
46 | namespace = settings.namespace,
47 | selector = settings.selector,
48 | formatter = settings.formatter,
49 | parser = settings.parser,
50 | metadata = settings.metadata,
51 | error = settings.error,
52 |
53 | eventNamespace = '.' + namespace,
54 | moduleNamespace = 'module-' + namespace,
55 |
56 | $module = $(this),
57 | $input = $module.find(selector.input),
58 | $container = $module.find(selector.popup),
59 | $activator = $module.find(selector.activator),
60 |
61 | element = this,
62 | instance = $module.data(moduleNamespace),
63 |
64 | isTouch,
65 | isTouchDown = false,
66 | focusDateUsedForRange = false,
67 | module
68 | ;
69 |
70 | module = {
71 |
72 | initialize: function () {
73 | module.debug('Initializing calendar for', element);
74 |
75 | isTouch = module.get.isTouch();
76 | module.setup.popup();
77 | module.setup.inline();
78 | module.setup.input();
79 | module.setup.date();
80 | module.create.calendar();
81 |
82 | module.bind.events();
83 | module.instantiate();
84 | },
85 |
86 | instantiate: function () {
87 | module.verbose('Storing instance of calendar');
88 | instance = module;
89 | $module.data(moduleNamespace, instance);
90 | },
91 |
92 | destroy: function () {
93 | module.verbose('Destroying previous calendar for', element);
94 | $module.removeData(moduleNamespace);
95 | module.unbind.events();
96 | },
97 |
98 | setup: {
99 | popup: function () {
100 | if (settings.inline) {
101 | return;
102 | }
103 | if (!$activator.length) {
104 | $activator = $module.children().first();
105 | if (!$activator.length) {
106 | return;
107 | }
108 | }
109 | if ($.fn.popup === undefined) {
110 | module.error(error.popup);
111 | return;
112 | }
113 | if (!$container.length) {
114 | //prepend the popup element to the activator's parent so that it has less chance of messing with
115 | //the styling (eg input action button needs to be the last child to have correct border radius)
116 | $container = $('').addClass(className.popup).prependTo($activator.parent());
117 | }
118 | $container.addClass(className.calendar);
119 | var onVisible = settings.onVisible;
120 | var onHidden = settings.onHidden;
121 | if (!$input.length) {
122 | //no input, $container has to handle focus/blur
123 | $container.attr('tabindex', '0');
124 | onVisible = function () {
125 | module.focus();
126 | return settings.onVisible.apply($container, arguments);
127 | };
128 | onHidden = function () {
129 | module.blur();
130 | return settings.onHidden.apply($container, arguments);
131 | };
132 | }
133 | var onShow = function () {
134 | //reset the focus date onShow
135 | module.set.focusDate(module.get.date());
136 | module.set.mode(settings.startMode);
137 | return settings.onShow.apply($container, arguments);
138 | };
139 | var on = settings.on || ($input.length ? 'focus' : 'click');
140 | var options = $.extend({}, settings.popupOptions, {
141 | popup: $container,
142 | on: on,
143 | hoverable: on === 'hover',
144 | onShow: onShow,
145 | onVisible: onVisible,
146 | onHide: settings.onHide,
147 | onHidden: onHidden
148 | });
149 | module.popup(options);
150 | },
151 | inline: function () {
152 | if ($activator.length && !settings.inline) {
153 | return;
154 | }
155 | $container = $('').addClass(className.calendar).appendTo($module);
156 | if (!$input.length) {
157 | $container.attr('tabindex', '0');
158 | }
159 | },
160 | input: function () {
161 | if (settings.touchReadonly && $input.length && isTouch) {
162 | $input.prop('readonly', true);
163 | }
164 | },
165 | date: function () {
166 | if ($input.length) {
167 | var val = $input.val();
168 | var date = parser.date(val, settings);
169 | module.set.date(date, settings.formatInput, false);
170 | }
171 | }
172 | },
173 |
174 | create: {
175 | calendar: function () {
176 | var i, r, c, p, row, cell, pageGrid;
177 |
178 | var mode = module.get.mode();
179 | var today = new Date();
180 | var date = module.get.date();
181 | var focusDate = module.get.focusDate();
182 | var display = focusDate || date || settings.initialDate || today;
183 | display = module.helper.dateInRange(display);
184 |
185 | if (!focusDate) {
186 | focusDate = display;
187 | module.set.focusDate(focusDate, false, false);
188 | }
189 |
190 | var isYear = mode === 'year';
191 | var isMonth = mode === 'month';
192 | var isDay = mode === 'day';
193 | var isHour = mode === 'hour';
194 | var isMinute = mode === 'minute';
195 | var isTimeOnly = settings.type === 'time';
196 |
197 | var multiMonth = Math.max(settings.multiMonth, 1);
198 | var monthOffset = !isDay ? 0 : module.get.monthOffset();
199 |
200 | var minute = display.getMinutes();
201 | var hour = display.getHours();
202 | var day = display.getDate();
203 | var startMonth = display.getMonth() + monthOffset;
204 | var year = display.getFullYear();
205 |
206 | var columns = isDay ? 7 : isHour ? 4 : 3;
207 | var columnsString = columns === 7 ? 'seven' : columns === 4 ? 'four' : 'three';
208 | var rows = isDay || isHour ? 6 : 4;
209 | var pages = isDay ? multiMonth : 1;
210 |
211 | var container = $container;
212 | container.empty();
213 | if (pages > 1) {
214 | pageGrid = $('').addClass(className.grid).appendTo(container);
215 | }
216 |
217 | for (p = 0; p < pages; p++) {
218 | if (pages > 1) {
219 | var pageColumn = $('').addClass(className.column).appendTo(pageGrid);
220 | container = pageColumn;
221 | }
222 |
223 | var month = startMonth + p;
224 | var firstMonthDayColumn = (new Date(year, month, 1).getDay() - settings.firstDayOfWeek % 7 + 7) % 7;
225 | if (!settings.constantHeight && isDay) {
226 | var requiredCells = new Date(year, month + 1, 0).getDate() + firstMonthDayColumn;
227 | rows = Math.ceil(requiredCells / 7);
228 | }
229 |
230 | var yearChange = isYear ? 10 : isMonth ? 1 : 0;
231 | var monthChange = isDay ? 1 : 0;
232 | var dayChange = isHour || isMinute ? 1 : 0;
233 | var prevNextDay = isHour || isMinute ? day : 1;
234 | var prevDate = new Date(year - yearChange, month - monthChange, prevNextDay - dayChange, hour);
235 | var nextDate = new Date(year + yearChange, month + monthChange, prevNextDay + dayChange, hour);
236 |
237 | var prevLast = isYear ? new Date(Math.ceil(year / 10) * 10 - 9, 0, 0) :
238 | isMonth ? new Date(year, 0, 0) : isDay ? new Date(year, month, 0) : new Date(year, month, day, -1);
239 | var nextFirst = isYear ? new Date(Math.ceil(year / 10) * 10 + 1, 0, 1) :
240 | isMonth ? new Date(year + 1, 0, 1) : isDay ? new Date(year, month + 1, 1) : new Date(year, month, day + 1);
241 |
242 | var table = $('').addClass(className.table).addClass(columnsString + ' column').addClass(mode).appendTo(container);
243 |
244 | //no header for time-only mode
245 | if (!isTimeOnly) {
246 | var thead = $('').appendTo(table);
247 |
248 | row = $('
').appendTo(thead);
249 | cell = $(' | ').attr('colspan', '' + columns).appendTo(row);
250 |
251 | var headerDate = isYear || isMonth ? new Date(year, 0, 1) :
252 | isDay ? new Date(year, month, 1) : new Date(year, month, day, hour, minute);
253 | var headerText = $('').addClass(className.link).appendTo(cell);
254 | headerText.text(formatter.header(headerDate, mode, settings));
255 | var newMode = isMonth ? (settings.disableYear ? 'day' : 'year') :
256 | isDay ? (settings.disableMonth ? 'year' : 'month') : 'day';
257 | headerText.data(metadata.mode, newMode);
258 |
259 | if (p === 0) {
260 | var prev = $('').addClass(className.prev).appendTo(cell);
261 | prev.data(metadata.focusDate, prevDate);
262 | prev.toggleClass(className.disabledCell, !module.helper.isDateInRange(prevLast, mode));
263 | $('').addClass(className.prevIcon).appendTo(prev);
264 | }
265 |
266 | if (p === pages - 1) {
267 | var next = $('').addClass(className.next).appendTo(cell);
268 | next.data(metadata.focusDate, nextDate);
269 | next.toggleClass(className.disabledCell, !module.helper.isDateInRange(nextFirst, mode));
270 | $('').addClass(className.nextIcon).appendTo(next);
271 | }
272 |
273 | if (isDay) {
274 | row = $('
').appendTo(thead);
275 | for (i = 0; i < columns; i++) {
276 | cell = $(' | ').appendTo(row);
277 | cell.text(formatter.dayColumnHeader((i + settings.firstDayOfWeek) % 7, settings));
278 | }
279 | }
280 | }
281 |
282 | var tbody = $('').appendTo(table);
283 | i = isYear ? Math.ceil(year / 10) * 10 - 9 : isDay ? 1 - firstMonthDayColumn : 0;
284 | for (r = 0; r < rows; r++) {
285 | row = $('
').appendTo(tbody);
286 | for (c = 0; c < columns; c++, i++) {
287 | var cellDate = isYear ? new Date(i, month, 1, hour, minute) :
288 | isMonth ? new Date(year, i, 1, hour, minute) : isDay ? new Date(year, month, i, hour, minute) :
289 | isHour ? new Date(year, month, day, i) : new Date(year, month, day, hour, i * 5);
290 | var cellText = isYear ? i :
291 | isMonth ? settings.text.monthsShort[i] : isDay ? cellDate.getDate() :
292 | formatter.time(cellDate, settings, true);
293 | cell = $(' | ').addClass(className.cell).appendTo(row);
294 | cell.text(cellText);
295 | cell.data(metadata.date, cellDate);
296 | var adjacent = isDay && cellDate.getMonth() !== ((month + 12) % 12);
297 | var disabled = adjacent || !module.helper.isDateInRange(cellDate, mode) || settings.isDisabled(cellDate, mode);
298 | var active = module.helper.dateEqual(cellDate, date, mode);
299 | var isToday = module.helper.dateEqual(cellDate, today, mode);
300 | cell.toggleClass(className.adjacentCell, adjacent);
301 | cell.toggleClass(className.disabledCell, disabled);
302 | cell.toggleClass(className.activeCell, active && !adjacent);
303 | if (!isHour && !isMinute) {
304 | cell.toggleClass(className.todayCell, !adjacent && isToday);
305 | }
306 |
307 | // Allow for external modifications of each cell
308 | var cellOptions = {
309 | mode: mode,
310 | adjacent: adjacent,
311 | disabled: disabled,
312 | active: active,
313 | today: isToday
314 | };
315 | formatter.cell(cell, cellDate, cellOptions);
316 |
317 | if (module.helper.dateEqual(cellDate, focusDate, mode)) {
318 | //ensure that the focus date is exactly equal to the cell date
319 | //so that, if selected, the correct value is set
320 | module.set.focusDate(cellDate, false, false);
321 | }
322 | }
323 | }
324 |
325 | if (settings.today) {
326 | var todayRow = $('
').appendTo(tbody);
327 | var todayButton = $(' | ').attr('colspan', '' + columns).addClass(className.today).appendTo(todayRow);
328 | todayButton.text(formatter.today(settings));
329 | todayButton.data(metadata.date, today);
330 | }
331 |
332 | module.update.focus(false, table);
333 | }
334 | }
335 | },
336 |
337 | update: {
338 | focus: function (updateRange, container) {
339 | container = container || $container;
340 | var mode = module.get.mode();
341 | var date = module.get.date();
342 | var focusDate = module.get.focusDate();
343 | var startDate = module.get.startDate();
344 | var endDate = module.get.endDate();
345 | var rangeDate = (updateRange ? focusDate : null) || date || (!isTouch ? focusDate : null);
346 |
347 | container.find('td').each(function () {
348 | var cell = $(this);
349 | var cellDate = cell.data(metadata.date);
350 | if (!cellDate) {
351 | return;
352 | }
353 | var disabled = cell.hasClass(className.disabledCell);
354 | var active = cell.hasClass(className.activeCell);
355 | var adjacent = cell.hasClass(className.adjacentCell);
356 | var focused = module.helper.dateEqual(cellDate, focusDate, mode);
357 | var inRange = !rangeDate ? false :
358 | ((!!startDate && module.helper.isDateInRange(cellDate, mode, startDate, rangeDate)) ||
359 | (!!endDate && module.helper.isDateInRange(cellDate, mode, rangeDate, endDate)));
360 | cell.toggleClass(className.focusCell, focused && (!isTouch || isTouchDown) && !adjacent);
361 | cell.toggleClass(className.rangeCell, inRange && !active && !disabled);
362 | });
363 | }
364 | },
365 |
366 | refresh: function () {
367 | module.create.calendar();
368 | },
369 |
370 | bind: {
371 | events: function () {
372 | $container.on('mousedown' + eventNamespace, module.event.mousedown);
373 | $container.on('touchstart' + eventNamespace, module.event.mousedown);
374 | $container.on('mouseup' + eventNamespace, module.event.mouseup);
375 | $container.on('touchend' + eventNamespace, module.event.mouseup);
376 | $container.on('mouseover' + eventNamespace, module.event.mouseover);
377 | if ($input.length) {
378 | $input.on('input' + eventNamespace, module.event.inputChange);
379 | $input.on('focus' + eventNamespace, module.event.inputFocus);
380 | $input.on('blur' + eventNamespace, module.event.inputBlur);
381 | $input.on('click' + eventNamespace, module.event.inputClick);
382 | $input.on('keydown' + eventNamespace, module.event.keydown);
383 | } else {
384 | $container.on('keydown' + eventNamespace, module.event.keydown);
385 | }
386 | }
387 | },
388 |
389 | unbind: {
390 | events: function () {
391 | $container.off(eventNamespace);
392 | if ($input.length) {
393 | $input.off(eventNamespace);
394 | }
395 | }
396 | },
397 |
398 | event: {
399 | mouseover: function (event) {
400 | var target = $(event.target);
401 | var date = target.data(metadata.date);
402 | var mousedown = event.buttons === 1;
403 | if (date) {
404 | module.set.focusDate(date, false, true, mousedown);
405 | }
406 | },
407 | mousedown: function (event) {
408 | if ($input.length) {
409 | //prevent the mousedown on the calendar causing the input to lose focus
410 | event.preventDefault();
411 | }
412 | isTouchDown = event.type.indexOf('touch') >= 0;
413 | var target = $(event.target);
414 | var date = target.data(metadata.date);
415 | if (date) {
416 | module.set.focusDate(date, false, true, true);
417 | }
418 | },
419 | mouseup: function (event) {
420 | //ensure input has focus so that it receives keydown events for calendar navigation
421 | module.focus();
422 | event.preventDefault();
423 | event.stopPropagation();
424 | isTouchDown = false;
425 | var target = $(event.target);
426 | var parent = target.parent();
427 | if (parent.data(metadata.date) || parent.data(metadata.focusDate) || parent.data(metadata.mode)) {
428 | //clicked on a child element, switch to parent (used when clicking directly on prev/next icon element)
429 | target = parent;
430 | }
431 | var date = target.data(metadata.date);
432 | var focusDate = target.data(metadata.focusDate);
433 | var mode = target.data(metadata.mode);
434 | if (date) {
435 | var forceSet = target.hasClass(className.today);
436 | module.selectDate(date, forceSet);
437 | }
438 | else if (focusDate) {
439 | module.set.focusDate(focusDate);
440 | }
441 | else if (mode) {
442 | module.set.mode(mode);
443 | }
444 | },
445 | keydown: function (event) {
446 | if (event.keyCode === 27 || event.keyCode === 9) {
447 | //esc || tab
448 | module.popup('hide');
449 | }
450 |
451 | if (module.popup('is visible')) {
452 | if (event.keyCode === 37 || event.keyCode === 38 || event.keyCode === 39 || event.keyCode === 40) {
453 | //arrow keys
454 | var mode = module.get.mode();
455 | var bigIncrement = mode === 'day' ? 7 : mode === 'hour' ? 4 : 3;
456 | var increment = event.keyCode === 37 ? -1 : event.keyCode === 38 ? -bigIncrement : event.keyCode == 39 ? 1 : bigIncrement;
457 | increment *= mode === 'minute' ? 5 : 1;
458 | var focusDate = module.get.focusDate() || module.get.date() || new Date();
459 | var year = focusDate.getFullYear() + (mode === 'year' ? increment : 0);
460 | var month = focusDate.getMonth() + (mode === 'month' ? increment : 0);
461 | var day = focusDate.getDate() + (mode === 'day' ? increment : 0);
462 | var hour = focusDate.getHours() + (mode === 'hour' ? increment : 0);
463 | var minute = focusDate.getMinutes() + (mode === 'minute' ? increment : 0);
464 | var newFocusDate = new Date(year, month, day, hour, minute);
465 | if (settings.type === 'time') {
466 | newFocusDate = module.helper.mergeDateTime(focusDate, newFocusDate);
467 | }
468 | if (module.helper.isDateInRange(newFocusDate, mode)) {
469 | module.set.focusDate(newFocusDate);
470 | }
471 | } else if (event.keyCode === 13) {
472 | //enter
473 | var mode = module.get.mode();
474 | var date = module.get.focusDate();
475 | if (date && !settings.isDisabled(date, mode)) {
476 | module.selectDate(date);
477 | }
478 | //disable form submission:
479 | event.preventDefault();
480 | event.stopPropagation();
481 | }
482 | }
483 |
484 | if (event.keyCode === 38 || event.keyCode === 40) {
485 | //arrow-up || arrow-down
486 | event.preventDefault(); //don't scroll
487 | module.popup('show');
488 | }
489 | },
490 | inputChange: function () {
491 | var val = $input.val();
492 | var date = parser.date(val, settings);
493 | module.set.date(date, false);
494 | },
495 | inputFocus: function () {
496 | $container.addClass(className.active);
497 | },
498 | inputBlur: function () {
499 | $container.removeClass(className.active);
500 | if (settings.formatInput) {
501 | var date = module.get.date();
502 | var text = formatter.datetime(date, settings);
503 | $input.val(text);
504 | }
505 | },
506 | inputClick: function () {
507 | module.popup('show');
508 | }
509 | },
510 |
511 | get: {
512 | date: function () {
513 | return $module.data(metadata.date) || null;
514 | },
515 | focusDate: function () {
516 | return $module.data(metadata.focusDate) || null;
517 | },
518 | startDate: function () {
519 | var startModule = module.get.calendarModule(settings.startCalendar);
520 | return (startModule ? startModule.get.date() : $module.data(metadata.startDate)) || null;
521 | },
522 | endDate: function () {
523 | var endModule = module.get.calendarModule(settings.endCalendar);
524 | return (endModule ? endModule.get.date() : $module.data(metadata.endDate)) || null;
525 | },
526 | monthOffset: function () {
527 | return $module.data(metadata.monthOffset) || 0;
528 | },
529 | mode: function () {
530 | //only returns valid modes for the current settings
531 | var mode = $module.data(metadata.mode) || settings.startMode;
532 | var validModes = module.get.validModes();
533 | if ($.inArray(mode, validModes) >= 0) {
534 | return mode;
535 | }
536 | return settings.type === 'time' ? 'hour' :
537 | settings.type === 'month' ? 'month' :
538 | settings.type === 'year' ? 'year' : 'day';
539 | },
540 | validModes: function () {
541 | var validModes = [];
542 | if (settings.type !== 'time') {
543 | if (!settings.disableYear || settings.type === 'year') {
544 | validModes.push('year');
545 | }
546 | if (!(settings.disableMonth || settings.type === 'year') || settings.type === 'month') {
547 | validModes.push('month');
548 | }
549 | if (settings.type.indexOf('date') >= 0) {
550 | validModes.push('day');
551 | }
552 | }
553 | if (settings.type.indexOf('time') >= 0) {
554 | validModes.push('hour');
555 | if (!settings.disableMinute) {
556 | validModes.push('minute');
557 | }
558 | }
559 | return validModes;
560 | },
561 | isTouch: function () {
562 | try {
563 | document.createEvent('TouchEvent');
564 | return true;
565 | }
566 | catch (e) {
567 | return false;
568 | }
569 | },
570 | calendarModule: function (selector) {
571 | if (!selector) {
572 | return null;
573 | }
574 | if (!(selector instanceof $)) {
575 | selector = $module.parent().children(selector).first();
576 | }
577 | //assume range related calendars are using the same namespace
578 | return selector.data(moduleNamespace);
579 | }
580 | },
581 |
582 | set: {
583 | date: function (date, updateInput, fireChange) {
584 | updateInput = updateInput !== false;
585 | fireChange = fireChange !== false;
586 | date = module.helper.sanitiseDate(date);
587 | date = module.helper.dateInRange(date);
588 |
589 | var mode = module.get.mode();
590 | var text = formatter.datetime(date, settings);
591 | if (fireChange && settings.onChange.call(element, date, text, mode) === false) {
592 | return false;
593 | }
594 |
595 | module.set.focusDate(date);
596 |
597 | if (settings.isDisabled(date, mode)) {
598 | return false;
599 | }
600 |
601 | var endDate = module.get.endDate();
602 | if (!!endDate && !!date && date > endDate) {
603 | //selected date is greater than end date in range, so clear end date
604 | module.set.endDate(undefined);
605 | }
606 | module.set.dataKeyValue(metadata.date, date);
607 |
608 | if (updateInput && $input.length) {
609 | $input.val(text);
610 | }
611 | },
612 | startDate: function (date, refreshCalendar) {
613 | date = module.helper.sanitiseDate(date);
614 | var startModule = module.get.calendarModule(settings.startCalendar);
615 | if (startModule) {
616 | startModule.set.date(date);
617 | }
618 | module.set.dataKeyValue(metadata.startDate, date, refreshCalendar);
619 | },
620 | endDate: function (date, refreshCalendar) {
621 | date = module.helper.sanitiseDate(date);
622 | var endModule = module.get.calendarModule(settings.endCalendar);
623 | if (endModule) {
624 | endModule.set.date(date);
625 | }
626 | module.set.dataKeyValue(metadata.endDate, date, refreshCalendar);
627 | },
628 | focusDate: function (date, refreshCalendar, updateFocus, updateRange) {
629 | date = module.helper.sanitiseDate(date);
630 | date = module.helper.dateInRange(date);
631 | var isDay = module.get.mode() === 'day';
632 | var oldFocusDate = module.get.focusDate();
633 | if (isDay && date && oldFocusDate) {
634 | var yearDelta = date.getFullYear() - oldFocusDate.getFullYear();
635 | var monthDelta = yearDelta * 12 + date.getMonth() - oldFocusDate.getMonth();
636 | if (monthDelta) {
637 | var monthOffset = module.get.monthOffset() - monthDelta;
638 | module.set.monthOffset(monthOffset, false);
639 | }
640 | }
641 | var changed = module.set.dataKeyValue(metadata.focusDate, date, refreshCalendar);
642 | updateFocus = (updateFocus !== false && changed && refreshCalendar === false) || focusDateUsedForRange != updateRange;
643 | focusDateUsedForRange = updateRange;
644 | if (updateFocus) {
645 | module.update.focus(updateRange);
646 | }
647 | },
648 | monthOffset: function (monthOffset, refreshCalendar) {
649 | var multiMonth = Math.max(settings.multiMonth, 1);
650 | monthOffset = Math.max(1 - multiMonth, Math.min(0, monthOffset));
651 | module.set.dataKeyValue(metadata.monthOffset, monthOffset, refreshCalendar);
652 | },
653 | mode: function (mode, refreshCalendar) {
654 | module.set.dataKeyValue(metadata.mode, mode, refreshCalendar);
655 | },
656 | dataKeyValue: function (key, value, refreshCalendar) {
657 | var oldValue = $module.data(key);
658 | var equal = oldValue === value || (oldValue <= value && oldValue >= value); //equality test for dates and string objects
659 | if (value) {
660 | $module.data(key, value);
661 | } else {
662 | $module.removeData(key);
663 | }
664 | refreshCalendar = refreshCalendar !== false && !equal;
665 | if (refreshCalendar) {
666 | module.create.calendar();
667 | }
668 | return !equal;
669 | }
670 | },
671 |
672 | selectDate: function (date, forceSet) {
673 | var mode = module.get.mode();
674 | var complete = forceSet || mode === 'minute' ||
675 | (settings.disableMinute && mode === 'hour') ||
676 | (settings.type === 'date' && mode === 'day') ||
677 | (settings.type === 'month' && mode === 'month') ||
678 | (settings.type === 'year' && mode === 'year');
679 | if (complete) {
680 | var canceled = module.set.date(date) === false;
681 | if (!canceled && settings.closable) {
682 | module.popup('hide');
683 | //if this is a range calendar, show the end date calendar popup and focus the input
684 | var endModule = module.get.calendarModule(settings.endCalendar);
685 | if (endModule) {
686 | endModule.popup('show');
687 | endModule.focus();
688 | }
689 | }
690 | } else {
691 | var newMode = mode === 'year' ? (!settings.disableMonth ? 'month' : 'day') :
692 | mode === 'month' ? 'day' : mode === 'day' ? 'hour' : 'minute';
693 | module.set.mode(newMode);
694 | if (mode === 'hour' || (mode === 'day' && module.get.date())) {
695 | //the user has chosen enough to consider a valid date/time has been chosen
696 | module.set.date(date);
697 | } else {
698 | module.set.focusDate(date);
699 | }
700 | }
701 | },
702 |
703 | changeDate: function (date) {
704 | module.set.date(date);
705 | },
706 |
707 | clear: function () {
708 | module.set.date(undefined);
709 | },
710 |
711 | popup: function () {
712 | return $activator.popup.apply($activator, arguments);
713 | },
714 |
715 | focus: function () {
716 | if ($input.length) {
717 | $input.focus();
718 | } else {
719 | $container.focus();
720 | }
721 | },
722 | blur: function () {
723 | if ($input.length) {
724 | $input.blur();
725 | } else {
726 | $container.blur();
727 | }
728 | },
729 |
730 | helper: {
731 | sanitiseDate: function (date) {
732 | if (!date) {
733 | return undefined;
734 | }
735 | if (!(date instanceof Date)) {
736 | date = parser.date('' + date, settings);
737 | }
738 | if (isNaN(date.getTime())) {
739 | return undefined;
740 | }
741 | return date;
742 | },
743 | dateDiff: function (date1, date2, mode) {
744 | mode = mode || 'day';
745 | var isTimeOnly = settings.type === 'time';
746 | var isYear = mode === 'year';
747 | var isYearOrMonth = isYear || mode === 'month';
748 | var isMinute = mode === 'minute';
749 | var isHourOrMinute = isMinute || mode === 'hour';
750 | //only care about a minute accuracy of 5
751 | date1 = new Date(
752 | isTimeOnly ? 2000 : date1.getFullYear(),
753 | isTimeOnly ? 0 : isYear ? 0 : date1.getMonth(),
754 | isTimeOnly ? 1 : isYearOrMonth ? 1 : date1.getDate(),
755 | !isHourOrMinute ? 0 : date1.getHours(),
756 | !isMinute ? 0 : 5 * Math.floor(date1.getMinutes() / 5));
757 | date2 = new Date(
758 | isTimeOnly ? 2000 : date2.getFullYear(),
759 | isTimeOnly ? 0 : isYear ? 0 : date2.getMonth(),
760 | isTimeOnly ? 1 : isYearOrMonth ? 1 : date2.getDate(),
761 | !isHourOrMinute ? 0 : date2.getHours(),
762 | !isMinute ? 0 : 5 * Math.floor(date2.getMinutes() / 5));
763 | return date2.getTime() - date1.getTime();
764 | },
765 | dateEqual: function (date1, date2, mode) {
766 | return !!date1 && !!date2 && module.helper.dateDiff(date1, date2, mode) === 0;
767 | },
768 | isDateInRange: function (date, mode, minDate, maxDate) {
769 | if (!minDate && !maxDate) {
770 | var startDate = module.get.startDate();
771 | minDate = startDate && settings.minDate ? new Date(Math.max(startDate, settings.minDate)) : startDate || settings.minDate;
772 | maxDate = settings.maxDate;
773 | }
774 | minDate = minDate && new Date(minDate.getFullYear(), minDate.getMonth(), minDate.getDate(), minDate.getHours(), 5 * Math.ceil(minDate.getMinutes() / 5));
775 | return !(!date ||
776 | (minDate && module.helper.dateDiff(date, minDate, mode) > 0) ||
777 | (maxDate && module.helper.dateDiff(maxDate, date, mode) > 0));
778 | },
779 | dateInRange: function (date, minDate, maxDate) {
780 | if (!minDate && !maxDate) {
781 | var startDate = module.get.startDate();
782 | minDate = startDate && settings.minDate ? new Date(Math.max(startDate, settings.minDate)) : startDate || settings.minDate;
783 | maxDate = settings.maxDate;
784 | }
785 | minDate = minDate && new Date(minDate.getFullYear(), minDate.getMonth(), minDate.getDate(), minDate.getHours(), 5 * Math.ceil(minDate.getMinutes() / 5));
786 | var isTimeOnly = settings.type === 'time';
787 | return !date ? date :
788 | (minDate && module.helper.dateDiff(date, minDate, 'minute') > 0) ?
789 | (isTimeOnly ? module.helper.mergeDateTime(date, minDate) : minDate) :
790 | (maxDate && module.helper.dateDiff(maxDate, date, 'minute') > 0) ?
791 | (isTimeOnly ? module.helper.mergeDateTime(date, maxDate) : maxDate) :
792 | date;
793 | },
794 | mergeDateTime: function (date, time) {
795 | return (!date || !time) ? time :
796 | new Date(date.getFullYear(), date.getMonth(), date.getDate(), time.getHours(), time.getMinutes());
797 | }
798 | },
799 |
800 | setting: function (name, value) {
801 | module.debug('Changing setting', name, value);
802 | if ($.isPlainObject(name)) {
803 | $.extend(true, settings, name);
804 | }
805 | else if (value !== undefined) {
806 | if ($.isPlainObject(settings[name])) {
807 | $.extend(true, settings[name], value);
808 | }
809 | else {
810 | settings[name] = value;
811 | }
812 | }
813 | else {
814 | return settings[name];
815 | }
816 | },
817 | internal: function (name, value) {
818 | module.debug('Changing internal', name, value);
819 | if (value !== undefined) {
820 | if ($.isPlainObject(name)) {
821 | $.extend(true, module, name);
822 | }
823 | else {
824 | module[name] = value;
825 | }
826 | }
827 | else {
828 | return module[name];
829 | }
830 | },
831 | debug: function () {
832 | if (!settings.silent && settings.debug) {
833 | if (settings.performance) {
834 | module.performance.log(arguments);
835 | }
836 | else {
837 | module.debug = Function.prototype.bind.call(console.info, console, settings.name + ':');
838 | module.debug.apply(console, arguments);
839 | }
840 | }
841 | },
842 | verbose: function () {
843 | if (!settings.silent && settings.verbose && settings.debug) {
844 | if (settings.performance) {
845 | module.performance.log(arguments);
846 | }
847 | else {
848 | module.verbose = Function.prototype.bind.call(console.info, console, settings.name + ':');
849 | module.verbose.apply(console, arguments);
850 | }
851 | }
852 | },
853 | error: function () {
854 | if (!settings.silent) {
855 | module.error = Function.prototype.bind.call(console.error, console, settings.name + ':');
856 | module.error.apply(console, arguments);
857 | }
858 | },
859 | performance: {
860 | log: function (message) {
861 | var
862 | currentTime,
863 | executionTime,
864 | previousTime
865 | ;
866 | if (settings.performance) {
867 | currentTime = new Date().getTime();
868 | previousTime = time || currentTime;
869 | executionTime = currentTime - previousTime;
870 | time = currentTime;
871 | performance.push({
872 | 'Name': message[0],
873 | 'Arguments': [].slice.call(message, 1) || '',
874 | 'Element': element,
875 | 'Execution Time': executionTime
876 | });
877 | }
878 | clearTimeout(module.performance.timer);
879 | module.performance.timer = setTimeout(module.performance.display, 500);
880 | },
881 | display: function () {
882 | var
883 | title = settings.name + ':',
884 | totalTime = 0
885 | ;
886 | time = false;
887 | clearTimeout(module.performance.timer);
888 | $.each(performance, function (index, data) {
889 | totalTime += data['Execution Time'];
890 | });
891 | title += ' ' + totalTime + 'ms';
892 | if (moduleSelector) {
893 | title += ' \'' + moduleSelector + '\'';
894 | }
895 | if ((console.group !== undefined || console.table !== undefined) && performance.length > 0) {
896 | console.groupCollapsed(title);
897 | if (console.table) {
898 | console.table(performance);
899 | }
900 | else {
901 | $.each(performance, function (index, data) {
902 | console.log(data['Name'] + ': ' + data['Execution Time'] + 'ms');
903 | });
904 | }
905 | console.groupEnd();
906 | }
907 | performance = [];
908 | }
909 | },
910 | invoke: function (query, passedArguments, context) {
911 | var
912 | object = instance,
913 | maxDepth,
914 | found,
915 | response
916 | ;
917 | passedArguments = passedArguments || queryArguments;
918 | context = element || context;
919 | if (typeof query == 'string' && object !== undefined) {
920 | query = query.split(/[\. ]/);
921 | maxDepth = query.length - 1;
922 | $.each(query, function (depth, value) {
923 | var camelCaseValue = (depth != maxDepth)
924 | ? value + query[depth + 1].charAt(0).toUpperCase() + query[depth + 1].slice(1)
925 | : query
926 | ;
927 | if ($.isPlainObject(object[camelCaseValue]) && (depth != maxDepth)) {
928 | object = object[camelCaseValue];
929 | }
930 | else if (object[camelCaseValue] !== undefined) {
931 | found = object[camelCaseValue];
932 | return false;
933 | }
934 | else if ($.isPlainObject(object[value]) && (depth != maxDepth)) {
935 | object = object[value];
936 | }
937 | else if (object[value] !== undefined) {
938 | found = object[value];
939 | return false;
940 | }
941 | else {
942 | module.error(error.method, query);
943 | return false;
944 | }
945 | });
946 | }
947 | if ($.isFunction(found)) {
948 | response = found.apply(context, passedArguments);
949 | }
950 | else if (found !== undefined) {
951 | response = found;
952 | }
953 | if ($.isArray(returnedValue)) {
954 | returnedValue.push(response);
955 | }
956 | else if (returnedValue !== undefined) {
957 | returnedValue = [returnedValue, response];
958 | }
959 | else if (response !== undefined) {
960 | returnedValue = response;
961 | }
962 | return found;
963 | }
964 | };
965 |
966 | if (methodInvoked) {
967 | if (instance === undefined) {
968 | module.initialize();
969 | }
970 | module.invoke(query);
971 | }
972 | else {
973 | if (instance !== undefined) {
974 | instance.invoke('destroy');
975 | }
976 | module.initialize();
977 | }
978 | })
979 | ;
980 | return (returnedValue !== undefined)
981 | ? returnedValue
982 | : this
983 | ;
984 | };
985 |
986 | $.fn.calendar.settings = {
987 |
988 | name: 'Calendar',
989 | namespace: 'calendar',
990 |
991 | silent: false,
992 | debug: false,
993 | verbose: false,
994 | performance: false,
995 |
996 | type: 'datetime', // picker type, can be 'datetime', 'date', 'time', 'month', or 'year'
997 | firstDayOfWeek: 0, // day for first day column (0 = Sunday)
998 | constantHeight: true, // add rows to shorter months to keep day calendar height consistent (6 rows)
999 | today: false, // show a 'today/now' button at the bottom of the calendar
1000 | closable: true, // close the popup after selecting a date/time
1001 | monthFirst: true, // month before day when parsing/converting date from/to text
1002 | touchReadonly: true, // set input to readonly on touch devices
1003 | inline: false, // create the calendar inline instead of inside a popup
1004 | on: null, // when to show the popup (defaults to 'focus' for input, 'click' for others)
1005 | initialDate: null, // date to display initially when no date is selected (null = now)
1006 | startMode: false, // display mode to start in, can be 'year', 'month', 'day', 'hour', 'minute' (false = 'day')
1007 | minDate: null, // minimum date/time that can be selected, dates/times before are disabled
1008 | maxDate: null, // maximum date/time that can be selected, dates/times after are disabled
1009 | ampm: true, // show am/pm in time mode
1010 | disableYear: false, // disable year selection mode
1011 | disableMonth: false, // disable month selection mode
1012 | disableMinute: false, // disable minute selection mode
1013 | formatInput: true, // format the input text upon input blur and module creation
1014 | startCalendar: null, // jquery object or selector for another calendar that represents the start date of a date range
1015 | endCalendar: null, // jquery object or selector for another calendar that represents the end date of a date range
1016 | multiMonth: 1, // show multiple months when in 'day' mode
1017 |
1018 | // popup options ('popup', 'on', 'hoverable', and show/hide callbacks are overridden)
1019 | popupOptions: {
1020 | position: 'bottom left',
1021 | lastResort: 'bottom left',
1022 | prefer: 'opposite',
1023 | hideOnScroll: false
1024 | },
1025 |
1026 | text: {
1027 | days: ['S', 'M', 'T', 'W', 'T', 'F', 'S'],
1028 | months: ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'],
1029 | monthsShort: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'],
1030 | today: 'Today',
1031 | now: 'Now',
1032 | am: 'AM',
1033 | pm: 'PM'
1034 | },
1035 |
1036 | formatter: {
1037 | header: function (date, mode, settings) {
1038 | return mode === 'year' ? settings.formatter.yearHeader(date, settings) :
1039 | mode === 'month' ? settings.formatter.monthHeader(date, settings) :
1040 | mode === 'day' ? settings.formatter.dayHeader(date, settings) :
1041 | mode === 'hour' ? settings.formatter.hourHeader(date, settings) :
1042 | settings.formatter.minuteHeader(date, settings);
1043 | },
1044 | yearHeader: function (date, settings) {
1045 | var decadeYear = Math.ceil(date.getFullYear() / 10) * 10;
1046 | return (decadeYear - 9) + ' - ' + (decadeYear + 2);
1047 | },
1048 | monthHeader: function (date, settings) {
1049 | return date.getFullYear();
1050 | },
1051 | dayHeader: function (date, settings) {
1052 | var month = settings.text.months[date.getMonth()];
1053 | var year = date.getFullYear();
1054 | return month + ' ' + year;
1055 | },
1056 | hourHeader: function (date, settings) {
1057 | return settings.formatter.date(date, settings);
1058 | },
1059 | minuteHeader: function (date, settings) {
1060 | return settings.formatter.date(date, settings);
1061 | },
1062 | dayColumnHeader: function (day, settings) {
1063 | return settings.text.days[day];
1064 | },
1065 | datetime: function (date, settings) {
1066 | if (!date) {
1067 | return '';
1068 | }
1069 | var day = settings.type === 'time' ? '' : settings.formatter.date(date, settings);
1070 | var time = settings.type.indexOf('time') < 0 ? '' : settings.formatter.time(date, settings, false);
1071 | var separator = settings.type === 'datetime' ? ' ' : '';
1072 | return day + separator + time;
1073 | },
1074 | date: function (date, settings) {
1075 | if (!date) {
1076 | return '';
1077 | }
1078 | var day = date.getDate();
1079 | var month = settings.text.months[date.getMonth()];
1080 | var year = date.getFullYear();
1081 | return settings.type === 'year' ? year :
1082 | settings.type === 'month' ? month + ' ' + year :
1083 | (settings.monthFirst ? month + ' ' + day : day + ' ' + month) + ', ' + year;
1084 | },
1085 | time: function (date, settings, forCalendar) {
1086 | if (!date) {
1087 | return '';
1088 | }
1089 | var hour = date.getHours();
1090 | var minute = date.getMinutes();
1091 | var ampm = '';
1092 | if (settings.ampm) {
1093 | ampm = ' ' + (hour < 12 ? settings.text.am : settings.text.pm);
1094 | hour = hour === 0 ? 12 : hour > 12 ? hour - 12 : hour;
1095 | }
1096 | return hour + ':' + (minute < 10 ? '0' : '') + minute + ampm;
1097 | },
1098 | today: function (settings) {
1099 | return settings.type === 'date' ? settings.text.today : settings.text.now;
1100 | },
1101 | cell: function (cell, date, cellOptions) {
1102 | }
1103 | },
1104 |
1105 | parser: {
1106 | date: function (text, settings) {
1107 | if (!text) {
1108 | return null;
1109 | }
1110 | text = ('' + text).trim().toLowerCase();
1111 | if (text.length === 0) {
1112 | return null;
1113 | }
1114 |
1115 | var i, j, k;
1116 | var minute = -1, hour = -1, day = -1, month = -1, year = -1;
1117 | var isAm = undefined;
1118 |
1119 | var isTimeOnly = settings.type === 'time';
1120 | var isDateOnly = settings.type.indexOf('time') < 0;
1121 |
1122 | var words = text.split(settings.regExp.dateWords);
1123 | var numbers = text.split(settings.regExp.dateNumbers);
1124 |
1125 | if (!isDateOnly) {
1126 | //am/pm
1127 | isAm = $.inArray(settings.text.am.toLowerCase(), words) >= 0 ? true :
1128 | $.inArray(settings.text.pm.toLowerCase(), words) >= 0 ? false : undefined;
1129 |
1130 | //time with ':'
1131 | for (i = 0; i < numbers.length; i++) {
1132 | var number = numbers[i];
1133 | if (number.indexOf(':') >= 0) {
1134 | if (hour < 0 || minute < 0) {
1135 | var parts = number.split(':');
1136 | for (k = 0; k < Math.min(2, parts.length); k++) {
1137 | j = parseInt(parts[k]);
1138 | if (isNaN(j)) {
1139 | j = 0;
1140 | }
1141 | if (k === 0) {
1142 | hour = j % 24;
1143 | } else {
1144 | minute = j % 60;
1145 | }
1146 | }
1147 | }
1148 | numbers.splice(i, 1);
1149 | }
1150 | }
1151 | }
1152 |
1153 | if (!isTimeOnly) {
1154 | //textual month
1155 | for (i = 0; i < words.length; i++) {
1156 | var word = words[i];
1157 | if (word.length <= 0) {
1158 | continue;
1159 | }
1160 | word = word.substring(0, Math.min(word.length, 3));
1161 | for (j = 0; j < settings.text.months.length; j++) {
1162 | var monthString = settings.text.months[j];
1163 | monthString = monthString.substring(0, Math.min(word.length, Math.min(monthString.length, 3))).toLowerCase();
1164 | if (monthString === word) {
1165 | month = j + 1;
1166 | break;
1167 | }
1168 | }
1169 | if (month >= 0) {
1170 | break;
1171 | }
1172 | }
1173 |
1174 | //year > 59
1175 | for (i = 0; i < numbers.length; i++) {
1176 | j = parseInt(numbers[i]);
1177 | if (isNaN(j)) {
1178 | continue;
1179 | }
1180 | if (j > 59) {
1181 | year = j;
1182 | numbers.splice(i, 1);
1183 | break;
1184 | }
1185 | }
1186 |
1187 | //numeric month
1188 | if (month < 0) {
1189 | for (i = 0; i < numbers.length; i++) {
1190 | k = i > 1 || settings.monthFirst ? i : i === 1 ? 0 : 1;
1191 | j = parseInt(numbers[k]);
1192 | if (isNaN(j)) {
1193 | continue;
1194 | }
1195 | if (1 <= j && j <= 12) {
1196 | month = j;
1197 | numbers.splice(k, 1);
1198 | break;
1199 | }
1200 | }
1201 | }
1202 |
1203 | //day
1204 | for (i = 0; i < numbers.length; i++) {
1205 | j = parseInt(numbers[i]);
1206 | if (isNaN(j)) {
1207 | continue;
1208 | }
1209 | if (1 <= j && j <= 31) {
1210 | day = j;
1211 | numbers.splice(i, 1);
1212 | break;
1213 | }
1214 | }
1215 |
1216 | //year <= 59
1217 | if (year < 0) {
1218 | for (i = numbers.length - 1; i >= 0; i--) {
1219 | j = parseInt(numbers[i]);
1220 | if (isNaN(j)) {
1221 | continue;
1222 | }
1223 | if (j < 99) {
1224 | j += 2000;
1225 | }
1226 | year = j;
1227 | numbers.splice(i, 1);
1228 | break;
1229 | }
1230 | }
1231 | }
1232 |
1233 | if (!isDateOnly) {
1234 | //hour
1235 | if (hour < 0) {
1236 | for (i = 0; i < numbers.length; i++) {
1237 | j = parseInt(numbers[i]);
1238 | if (isNaN(j)) {
1239 | continue;
1240 | }
1241 | if (0 <= j && j <= 23) {
1242 | hour = j;
1243 | numbers.splice(i, 1);
1244 | break;
1245 | }
1246 | }
1247 | }
1248 |
1249 | //minute
1250 | if (minute < 0) {
1251 | for (i = 0; i < numbers.length; i++) {
1252 | j = parseInt(numbers[i]);
1253 | if (isNaN(j)) {
1254 | continue;
1255 | }
1256 | if (0 <= j && j <= 59) {
1257 | minute = j;
1258 | numbers.splice(i, 1);
1259 | break;
1260 | }
1261 | }
1262 | }
1263 | }
1264 |
1265 | if (minute < 0 && hour < 0 && day < 0 && month < 0 && year < 0) {
1266 | return null;
1267 | }
1268 |
1269 | if (minute < 0) {
1270 | minute = 0;
1271 | }
1272 | if (hour < 0) {
1273 | hour = 0;
1274 | }
1275 | if (day < 0) {
1276 | day = 1;
1277 | }
1278 | if (month < 0) {
1279 | month = 1;
1280 | }
1281 | if (year < 0) {
1282 | year = new Date().getFullYear();
1283 | }
1284 |
1285 | if (isAm !== undefined) {
1286 | if (isAm) {
1287 | if (hour === 12) {
1288 | hour = 0;
1289 | }
1290 | } else if (hour < 12) {
1291 | hour += 12;
1292 | }
1293 | }
1294 |
1295 | var date = new Date(year, month - 1, day, hour, minute);
1296 | if (date.getMonth() !== month - 1 || date.getFullYear() !== year) {
1297 | //month or year don't match up, switch to last day of the month
1298 | date = new Date(year, month, 0, hour, minute);
1299 | }
1300 | return isNaN(date.getTime()) ? null : date;
1301 | }
1302 | },
1303 |
1304 | // callback when date changes, return false to cancel the change
1305 | onChange: function (date, text, mode) {
1306 | return true;
1307 | },
1308 |
1309 | // callback before show animation, return false to prevent show
1310 | onShow: function () {
1311 | },
1312 |
1313 | // callback after show animation
1314 | onVisible: function () {
1315 | },
1316 |
1317 | // callback before hide animation, return false to prevent hide
1318 | onHide: function () {
1319 | },
1320 |
1321 | // callback after hide animation
1322 | onHidden: function () {
1323 | },
1324 |
1325 | // is the given date disabled?
1326 | isDisabled: function (date, mode) {
1327 | return false;
1328 | },
1329 |
1330 | selector: {
1331 | popup: '.ui.popup',
1332 | input: 'input',
1333 | activator: 'input'
1334 | },
1335 |
1336 | regExp: {
1337 | dateWords: /[^A-Za-z\u00C0-\u024F]+/g,
1338 | dateNumbers: /[^\d:]+/g
1339 | },
1340 |
1341 | error: {
1342 | popup: 'UI Popup, a required component is not included in this page',
1343 | method: 'The method you called is not defined.'
1344 | },
1345 |
1346 | className: {
1347 | calendar: 'calendar',
1348 | active: 'active',
1349 | popup: 'ui popup',
1350 | grid: 'ui equal width grid',
1351 | column: 'column',
1352 | table: 'ui celled center aligned unstackable table',
1353 | prev: 'prev link',
1354 | next: 'next link',
1355 | prevIcon: 'chevron left icon',
1356 | nextIcon: 'chevron right icon',
1357 | link: 'link',
1358 | cell: 'link',
1359 | disabledCell: 'disabled',
1360 | adjacentCell: 'adjacent',
1361 | activeCell: 'active',
1362 | rangeCell: 'range',
1363 | focusCell: 'focus',
1364 | todayCell: 'today',
1365 | today: 'today link'
1366 | },
1367 |
1368 | metadata: {
1369 | date: 'date',
1370 | focusDate: 'focusDate',
1371 | startDate: 'startDate',
1372 | endDate: 'endDate',
1373 | mode: 'mode',
1374 | monthOffset: 'monthOffset'
1375 | }
1376 | };
1377 |
1378 | })(jQuery, window, document);
1379 |
--------------------------------------------------------------------------------