iqvoc 4.2.0 → 4.3.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (148) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +15 -0
  3. data/Gemfile +15 -12
  4. data/Gemfile.lock +124 -90
  5. data/README.md +17 -1
  6. data/app/assets/images/iqvoc_logo.svg +41 -0
  7. data/app/assets/javascripts/framework.js +1 -1
  8. data/app/assets/javascripts/iqvoc/concept_mapper.js +62 -0
  9. data/app/assets/javascripts/iqvoc/concept_mapping_manager.js +137 -0
  10. data/app/assets/javascripts/iqvoc/entityselect.js.erb +51 -19
  11. data/app/assets/javascripts/iqvoc/federated_concept_mapper.js +75 -0
  12. data/app/assets/javascripts/iqvoc/iqvoc.js +16 -4
  13. data/app/assets/javascripts/iqvoc/label_resolver.js +23 -0
  14. data/app/assets/javascripts/iqvoc/manifest.js +4 -0
  15. data/app/assets/javascripts/iqvoc/onebox.js.erb +4 -4
  16. data/app/assets/javascripts/iqvoc/quicksearch.js +1 -1
  17. data/app/assets/stylesheets/framework.css.scss +2 -1
  18. data/app/assets/stylesheets/iqvoc/_settings.css.scss +12 -0
  19. data/app/assets/stylesheets/iqvoc/components/_components.css.scss +237 -0
  20. data/app/assets/stylesheets/iqvoc/{entity_select.css.scss → components/_entity_select.css.scss} +0 -2
  21. data/app/assets/stylesheets/iqvoc/{forms.css.scss → components/_forms.css.scss} +0 -0
  22. data/app/assets/stylesheets/iqvoc/{note.css.scss → components/_notes.css.scss} +2 -10
  23. data/app/assets/stylesheets/iqvoc/{panel.css.scss → components/_panels.css.scss} +3 -5
  24. data/app/assets/stylesheets/iqvoc/{sidebar.css.scss → components/_sidebars.css.scss} +0 -0
  25. data/app/assets/stylesheets/iqvoc/{visualization.css.scss → components/_visualization.css.scss} +0 -0
  26. data/app/assets/stylesheets/iqvoc/{bootstrap_extensions.css.scss → hacks/_bootstrap_extensions.css.scss} +0 -0
  27. data/app/assets/stylesheets/iqvoc/{hacks.css.scss → hacks/_hacks.css.scss} +0 -0
  28. data/app/assets/stylesheets/iqvoc/{jquery-ui_extensions.css.scss → hacks/_jquery-ui_extensions.css.scss} +0 -0
  29. data/app/assets/stylesheets/iqvoc/manifest.css.scss +10 -10
  30. data/app/controllers/concepts/alphabetical_controller.rb +23 -9
  31. data/app/controllers/concepts/scheme_controller.rb +19 -0
  32. data/app/controllers/concepts_controller.rb +13 -1
  33. data/app/controllers/concerns/dataset_initialization.rb +18 -0
  34. data/app/controllers/dashboard_controller.rb +17 -0
  35. data/app/controllers/hierarchy_controller.rb +65 -6
  36. data/app/controllers/{import_controller.rb → imports_controller.rb} +14 -11
  37. data/app/controllers/rdf_controller.rb +6 -0
  38. data/app/controllers/remote_labels_controller.rb +31 -0
  39. data/app/controllers/search_results_controller.rb +95 -14
  40. data/app/helpers/application_helper.rb +6 -4
  41. data/app/helpers/dashboard_helper.rb +3 -3
  42. data/app/helpers/link_helper.rb +14 -0
  43. data/app/helpers/search_results_helper.rb +5 -1
  44. data/app/jobs/import_job.rb +19 -0
  45. data/app/models/concept/base.rb +2 -2
  46. data/app/models/dataset/adaptors/iqvoc/alphabetical_search_adaptor.rb +38 -0
  47. data/app/models/dataset/adaptors/iqvoc/http_adaptor.rb +39 -0
  48. data/app/models/dataset/adaptors/iqvoc/label_adaptor.rb +15 -0
  49. data/app/models/dataset/adaptors/iqvoc/search_adaptor.rb +60 -0
  50. data/app/models/dataset/iqvoc_dataset.rb +39 -0
  51. data/app/models/import.rb +16 -0
  52. data/app/models/labeling/skos/base.rb +2 -1
  53. data/app/models/note/base.rb +2 -2
  54. data/app/models/note/skos/change_note.rb +3 -2
  55. data/app/presenters/alphabetical_search_result.rb +33 -0
  56. data/app/presenters/alphabetical_search_result_remote.rb +37 -0
  57. data/app/presenters/search_result.rb +33 -0
  58. data/app/presenters/search_result_collection.rb +8 -0
  59. data/app/presenters/search_result_remote.rb +52 -0
  60. data/app/views/collections/_sidebar.html.erb +3 -3
  61. data/app/views/concepts/_form.html.erb +1 -1
  62. data/app/views/concepts/alphabetical/_search_result.html.erb +16 -0
  63. data/app/views/concepts/alphabetical/_search_result_remote.html.erb +14 -0
  64. data/app/views/concepts/alphabetical/index.html.erb +5 -3
  65. data/app/views/concepts/expired/index.html.erb +5 -2
  66. data/app/views/concepts/scheme/_sidebar.html.erb +3 -3
  67. data/app/views/concepts/sidebars/_singular.html.erb +4 -4
  68. data/app/views/dashboard/_sidebar.html.erb +7 -4
  69. data/app/views/dashboard/index.html.erb +1 -1
  70. data/app/views/dashboard/reset.html.erb +6 -0
  71. data/app/views/imports/index.html.erb +44 -0
  72. data/app/views/imports/show.html.erb +7 -0
  73. data/app/views/layouts/application.html.erb +7 -1
  74. data/app/views/partials/labeling/skos/_search_result.html.erb +12 -16
  75. data/app/views/partials/match/_edit_base.html.erb +1 -1
  76. data/app/views/partials/note/_search_result.html.erb +8 -5
  77. data/app/views/partials/note/skos/change_note/_search_result.html.erb +7 -10
  78. data/app/views/partials/note/skos/definition/_search_result.html.erb +5 -5
  79. data/app/views/rdf/dataset.iqrdf +9 -0
  80. data/app/views/search_results/_search_result_remote.html.erb +13 -0
  81. data/app/views/search_results/_sidebar.html.erb +3 -3
  82. data/app/views/search_results/index.html.erb +4 -4
  83. data/app/views/search_results/index.iqrdf +7 -7
  84. data/app/views/search_results/sections/_datasets.html.erb +17 -0
  85. data/app/views/search_results/sections/_klass.html.erb +2 -2
  86. data/app/views/search_results/sections/_languages.html.erb +3 -3
  87. data/app/views/users/_sidebar.html.erb +1 -1
  88. data/config/application.rb +0 -2
  89. data/config/engine.rb +5 -0
  90. data/config/environments/heroku.rb +62 -16
  91. data/config/initializers/apipie.rb +17 -0
  92. data/config/initializers/secret_token.rb +25 -9
  93. data/config/locales/activerecord.de.yml +5 -0
  94. data/config/locales/activerecord.en.yml +5 -0
  95. data/config/locales/de.yml +14 -0
  96. data/config/locales/en.yml +14 -0
  97. data/config/locales/pt.yml +1 -0
  98. data/config/routes.rb +7 -4
  99. data/db/migrate/20131220134356_create_delayed_jobs.rb +22 -0
  100. data/db/migrate/20131220144601_create_imports.rb +11 -0
  101. data/db/schema.rb +26 -1
  102. data/iqvoc.gemspec +12 -3
  103. data/lib/iqvoc/ability.rb +2 -0
  104. data/lib/iqvoc/configuration/core.rb +36 -9
  105. data/lib/iqvoc/controller_extensions.rb +4 -0
  106. data/lib/iqvoc/environments/production.rb +1 -1
  107. data/lib/iqvoc/skos_importer.rb +31 -19
  108. data/lib/iqvoc/version.rb +1 -1
  109. data/lib/tasks/importer.rake +10 -2
  110. data/lib/tasks/release.rake +1 -1
  111. data/public/404.html +43 -11
  112. data/public/422.html +43 -11
  113. data/public/500.html +43 -12
  114. data/test/functional/{rdf_test.rb → rdf_rendering_test.rb} +1 -1
  115. data/test/integration/alphabetical_test.rb +5 -5
  116. data/test/integration/search_test.rb +16 -16
  117. data/test/unit/skos_import_test.rb +9 -9
  118. data/vendor/assets/images/animated-overlay.gif +0 -0
  119. data/vendor/assets/images/ui-bg_flat_0_aaaaaa_40x100.png +0 -0
  120. data/vendor/assets/images/ui-bg_flat_55_fbec88_40x100.png +0 -0
  121. data/vendor/assets/images/ui-bg_glass_75_d0e5f5_1x400.png +0 -0
  122. data/vendor/assets/images/ui-bg_glass_85_dfeffc_1x400.png +0 -0
  123. data/vendor/assets/images/ui-bg_glass_95_fef1ec_1x400.png +0 -0
  124. data/vendor/assets/images/ui-bg_gloss-wave_55_5c9ccc_500x100.png +0 -0
  125. data/vendor/assets/images/ui-bg_inset-hard_100_f5f8f9_1x100.png +0 -0
  126. data/vendor/assets/images/ui-bg_inset-hard_100_fcfdfd_1x100.png +0 -0
  127. data/vendor/assets/images/ui-icons_217bc0_256x240.png +0 -0
  128. data/vendor/assets/images/ui-icons_2e83ff_256x240.png +0 -0
  129. data/vendor/assets/images/ui-icons_469bdd_256x240.png +0 -0
  130. data/vendor/assets/images/ui-icons_6da8d5_256x240.png +0 -0
  131. data/vendor/assets/images/ui-icons_cd0a0a_256x240.png +0 -0
  132. data/vendor/assets/images/ui-icons_d8e7f3_256x240.png +0 -0
  133. data/vendor/assets/images/ui-icons_f9bd01_256x240.png +0 -0
  134. data/vendor/assets/javascripts/jquery-ui.custom.js +4538 -0
  135. data/vendor/assets/stylesheets/jquery-ui-1.10.3.custom.css.scss +724 -0
  136. metadata +214 -64
  137. data/app/assets/images/arrow_down.gif +0 -0
  138. data/app/assets/images/arrow_up.gif +0 -0
  139. data/app/assets/images/iqvoc_logo.png +0 -0
  140. data/app/assets/images/spinner_16x16.gif +0 -0
  141. data/app/assets/images/spinner_24x24.gif +0 -0
  142. data/app/assets/stylesheets/iqvoc/components.css.scss +0 -155
  143. data/app/assets/stylesheets/iqvoc/layout.css.scss +0 -0
  144. data/app/views/concepts/alphabetical/_pref_labeling.html.erb +0 -19
  145. data/app/views/import/import.html.erb +0 -7
  146. data/app/views/import/index.html.erb +0 -17
  147. data/vendor/assets/javascripts/jquery-ui-1.8.23.custom.js +0 -3399
  148. data/vendor/assets/stylesheets/jquery-ui-1.8.23.custom.css.scss +0 -405
Binary file
Binary file
Binary file
Binary file
Binary file
@@ -1,155 +0,0 @@
1
- .navbar {
2
- .quicksearch {
3
- }
4
- }
5
-
6
- .onebox {
7
- padding-top: 80px;
8
- margin-top: 2em;
9
- text-align: center;
10
-
11
- background: asset-data-url("iqvoc_logo.png") top center no-repeat;
12
-
13
- .logo {
14
- margin: 2em 0 1em 0;
15
- }
16
-
17
- input {
18
- min-width: 60%;
19
- }
20
-
21
- ol {
22
- margin-left: 0;
23
- list-style: none;
24
- text-align: left;
25
- }
26
-
27
- .pagination {
28
- text-align: left;
29
- }
30
- }
31
-
32
- tr.highlightable {
33
- cursor: pointer;
34
- }
35
-
36
- .alert {
37
- p {
38
- margin: 0 0 10px 0;
39
- }
40
- ul {
41
- margin-left: 30px;
42
- margin-bottom: 0px;
43
- }
44
- }
45
-
46
- .sorting-controls {
47
- margin-left: 2px;
48
- }
49
-
50
- img.spinner {
51
- margin-left: -25px;
52
- }
53
-
54
- .arrow_down {
55
- margin-top: 3px;
56
- }
57
-
58
- .arrow_up {
59
- margin-top: 2px;
60
- }
61
-
62
- dl {
63
- dt {
64
- margin-top: 10px;
65
- }
66
- }
67
-
68
- .letter-selector {
69
- $active: white;
70
- margin: 0;
71
- li {
72
- a {
73
- color: #BFBFBF;
74
- font-weight: bold;
75
- }
76
- -webkit-border-radius: 4px;
77
- -moz-border-radius: 4px;
78
- border-radius: 4px;
79
- display: inline-block;
80
- margin-right: 2px;
81
- padding: 2px 6px;
82
- &:last-child {
83
- margin-right: 0;
84
- }
85
- &.active {
86
- background-color: $active;
87
- }
88
- }
89
- }
90
-
91
- .translation {
92
- margin-bottom: 15px;
93
- }
94
-
95
- .nav-list {
96
- li {
97
- a {
98
- &.inline-language-selector {
99
- display: inline;
100
- margin: inherit;
101
- padding: inherit;
102
- &:hover {
103
- background: inherit;
104
- }
105
- }
106
- }
107
- }
108
- }
109
-
110
- ol.concepts {
111
- li {
112
- margin-bottom: 15px;
113
- p {
114
- margin: 0;
115
- }
116
- p.term {
117
- a {
118
- font-weight: bold;
119
- }
120
- }
121
- p.uri {
122
- color: green;
123
- }
124
- }
125
- }
126
-
127
- .lang-widget {
128
- padding: 0 15px 20px 15px;
129
-
130
- .lang-widget-item {
131
- white-space: nowrap;
132
-
133
- label {
134
- margin: 0;
135
- padding: 2px 10px;
136
-
137
- input {
138
- margin-top: -2px;
139
- margin-right: 0.5em;
140
- display: inline;
141
- }
142
-
143
- a {
144
- padding-left: 0;
145
- display: inline;
146
- }
147
- }
148
- }
149
-
150
- .lang-widget-header {
151
- margin-top: 10px;
152
- margin-bottom: 0;
153
- font-size: 18px;
154
- }
155
- }
File without changes
@@ -1,19 +0,0 @@
1
- <li>
2
- <p class="term">
3
- <%= link_to pref_labeling.target.to_s, concept_path(:id => pref_labeling.owner), :alt => pref_labeling.owner.origin %>
4
- <% if pref_labeling.owner.additional_info.present? %>
5
- (<%= pref_labeling.owner.additional_info %>)
6
- <% end %>
7
- </p>
8
-
9
- <p class="uri"><%= rdf_url(:id => pref_labeling.owner.origin, :lang => nil, :format => nil) %></p>
10
- <% if pref_labeling.owner.respond_to?(Note::SKOS::Definition.name.to_relation_name) &&
11
- pref_labeling.owner.send(Note::SKOS::Definition.name.to_relation_name).any? %>
12
- <% pref_labeling.owner.send(Note::SKOS::Definition.name.to_relation_name).each do |definition| %>
13
- <p class="definition" lang="<%= definition.language %>">
14
- <%= definition.value %>
15
- </p>
16
- <% end %>
17
- <% end %>
18
-
19
- </li>
@@ -1,7 +0,0 @@
1
- <%= page_header :title => 'Import' %>
2
- <%= render 'dashboard/sidebar' %>
3
-
4
- <div class="panel">
5
- <h2><%= t 'txt.views.import.output' %></h2>
6
- <pre><%= @messages %></pre>
7
- </div>
@@ -1,17 +0,0 @@
1
- <%= page_header :title => 'Import' %>
2
- <%= render 'dashboard/sidebar' %>
3
-
4
- <%= form_tag import_url, :method => :post, :multipart => true , :class => "form-horizontal" do %>
5
- <%= input_block :label => 'NTriples File' do %>
6
- <%= file_field_tag 'ntriples_file' %>
7
- <% end %>
8
-
9
- <%= input_block :label => 'Default namespace' do %>
10
- <%= text_field_tag 'default_namespace',
11
- root_url(:format => nil, :lang => nil, :trailing_slash => true).gsub(/\/\/$/, "/") %>
12
- <% end %>
13
-
14
- <div class="form-actions">
15
- <%= submit_tag 'Import', :class => 'btn btn-primary' %>
16
- </div>
17
- <% end %>
@@ -1,3399 +0,0 @@
1
- /*!
2
- * jQuery UI 1.8.23
3
- *
4
- * Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)
5
- * Dual licensed under the MIT or GPL Version 2 licenses.
6
- * http://jquery.org/license
7
- *
8
- * http://docs.jquery.com/UI
9
- */
10
- (function( $, undefined ) {
11
-
12
- // prevent duplicate loading
13
- // this is only a problem because we proxy existing functions
14
- // and we don't want to double proxy them
15
- $.ui = $.ui || {};
16
- if ( $.ui.version ) {
17
- return;
18
- }
19
-
20
- $.extend( $.ui, {
21
- version: "1.8.23",
22
-
23
- keyCode: {
24
- ALT: 18,
25
- BACKSPACE: 8,
26
- CAPS_LOCK: 20,
27
- COMMA: 188,
28
- COMMAND: 91,
29
- COMMAND_LEFT: 91, // COMMAND
30
- COMMAND_RIGHT: 93,
31
- CONTROL: 17,
32
- DELETE: 46,
33
- DOWN: 40,
34
- END: 35,
35
- ENTER: 13,
36
- ESCAPE: 27,
37
- HOME: 36,
38
- INSERT: 45,
39
- LEFT: 37,
40
- MENU: 93, // COMMAND_RIGHT
41
- NUMPAD_ADD: 107,
42
- NUMPAD_DECIMAL: 110,
43
- NUMPAD_DIVIDE: 111,
44
- NUMPAD_ENTER: 108,
45
- NUMPAD_MULTIPLY: 106,
46
- NUMPAD_SUBTRACT: 109,
47
- PAGE_DOWN: 34,
48
- PAGE_UP: 33,
49
- PERIOD: 190,
50
- RIGHT: 39,
51
- SHIFT: 16,
52
- SPACE: 32,
53
- TAB: 9,
54
- UP: 38,
55
- WINDOWS: 91 // COMMAND
56
- }
57
- });
58
-
59
- // plugins
60
- $.fn.extend({
61
- propAttr: $.fn.prop || $.fn.attr,
62
-
63
- _focus: $.fn.focus,
64
- focus: function( delay, fn ) {
65
- return typeof delay === "number" ?
66
- this.each(function() {
67
- var elem = this;
68
- setTimeout(function() {
69
- $( elem ).focus();
70
- if ( fn ) {
71
- fn.call( elem );
72
- }
73
- }, delay );
74
- }) :
75
- this._focus.apply( this, arguments );
76
- },
77
-
78
- scrollParent: function() {
79
- var scrollParent;
80
- if (($.browser.msie && (/(static|relative)/).test(this.css('position'))) || (/absolute/).test(this.css('position'))) {
81
- scrollParent = this.parents().filter(function() {
82
- return (/(relative|absolute|fixed)/).test($.curCSS(this,'position',1)) && (/(auto|scroll)/).test($.curCSS(this,'overflow',1)+$.curCSS(this,'overflow-y',1)+$.curCSS(this,'overflow-x',1));
83
- }).eq(0);
84
- } else {
85
- scrollParent = this.parents().filter(function() {
86
- return (/(auto|scroll)/).test($.curCSS(this,'overflow',1)+$.curCSS(this,'overflow-y',1)+$.curCSS(this,'overflow-x',1));
87
- }).eq(0);
88
- }
89
-
90
- return (/fixed/).test(this.css('position')) || !scrollParent.length ? $(document) : scrollParent;
91
- },
92
-
93
- zIndex: function( zIndex ) {
94
- if ( zIndex !== undefined ) {
95
- return this.css( "zIndex", zIndex );
96
- }
97
-
98
- if ( this.length ) {
99
- var elem = $( this[ 0 ] ), position, value;
100
- while ( elem.length && elem[ 0 ] !== document ) {
101
- // Ignore z-index if position is set to a value where z-index is ignored by the browser
102
- // This makes behavior of this function consistent across browsers
103
- // WebKit always returns auto if the element is positioned
104
- position = elem.css( "position" );
105
- if ( position === "absolute" || position === "relative" || position === "fixed" ) {
106
- // IE returns 0 when zIndex is not specified
107
- // other browsers return a string
108
- // we ignore the case of nested elements with an explicit value of 0
109
- // <div style="z-index: -10;"><div style="z-index: 0;"></div></div>
110
- value = parseInt( elem.css( "zIndex" ), 10 );
111
- if ( !isNaN( value ) && value !== 0 ) {
112
- return value;
113
- }
114
- }
115
- elem = elem.parent();
116
- }
117
- }
118
-
119
- return 0;
120
- },
121
-
122
- disableSelection: function() {
123
- return this.bind( ( $.support.selectstart ? "selectstart" : "mousedown" ) +
124
- ".ui-disableSelection", function( event ) {
125
- event.preventDefault();
126
- });
127
- },
128
-
129
- enableSelection: function() {
130
- return this.unbind( ".ui-disableSelection" );
131
- }
132
- });
133
-
134
- // support: jQuery <1.8
135
- if ( !$( "<a>" ).outerWidth( 1 ).jquery ) {
136
- $.each( [ "Width", "Height" ], function( i, name ) {
137
- var side = name === "Width" ? [ "Left", "Right" ] : [ "Top", "Bottom" ],
138
- type = name.toLowerCase(),
139
- orig = {
140
- innerWidth: $.fn.innerWidth,
141
- innerHeight: $.fn.innerHeight,
142
- outerWidth: $.fn.outerWidth,
143
- outerHeight: $.fn.outerHeight
144
- };
145
-
146
- function reduce( elem, size, border, margin ) {
147
- $.each( side, function() {
148
- size -= parseFloat( $.curCSS( elem, "padding" + this, true) ) || 0;
149
- if ( border ) {
150
- size -= parseFloat( $.curCSS( elem, "border" + this + "Width", true) ) || 0;
151
- }
152
- if ( margin ) {
153
- size -= parseFloat( $.curCSS( elem, "margin" + this, true) ) || 0;
154
- }
155
- });
156
- return size;
157
- }
158
-
159
- $.fn[ "inner" + name ] = function( size ) {
160
- if ( size === undefined ) {
161
- return orig[ "inner" + name ].call( this );
162
- }
163
-
164
- return this.each(function() {
165
- $( this ).css( type, reduce( this, size ) + "px" );
166
- });
167
- };
168
-
169
- $.fn[ "outer" + name] = function( size, margin ) {
170
- if ( typeof size !== "number" ) {
171
- return orig[ "outer" + name ].call( this, size );
172
- }
173
-
174
- return this.each(function() {
175
- $( this).css( type, reduce( this, size, true, margin ) + "px" );
176
- });
177
- };
178
- });
179
- }
180
-
181
- // selectors
182
- function focusable( element, isTabIndexNotNaN ) {
183
- var nodeName = element.nodeName.toLowerCase();
184
- if ( "area" === nodeName ) {
185
- var map = element.parentNode,
186
- mapName = map.name,
187
- img;
188
- if ( !element.href || !mapName || map.nodeName.toLowerCase() !== "map" ) {
189
- return false;
190
- }
191
- img = $( "img[usemap=#" + mapName + "]" )[0];
192
- return !!img && visible( img );
193
- }
194
- return ( /input|select|textarea|button|object/.test( nodeName )
195
- ? !element.disabled
196
- : "a" == nodeName
197
- ? element.href || isTabIndexNotNaN
198
- : isTabIndexNotNaN)
199
- // the element and all of its ancestors must be visible
200
- && visible( element );
201
- }
202
-
203
- function visible( element ) {
204
- return !$( element ).parents().andSelf().filter(function() {
205
- return $.curCSS( this, "visibility" ) === "hidden" ||
206
- $.expr.filters.hidden( this );
207
- }).length;
208
- }
209
-
210
- $.extend( $.expr[ ":" ], {
211
- data: $.expr.createPseudo ?
212
- $.expr.createPseudo(function( dataName ) {
213
- return function( elem ) {
214
- return !!$.data( elem, dataName );
215
- };
216
- }) :
217
- // support: jQuery <1.8
218
- function( elem, i, match ) {
219
- return !!$.data( elem, match[ 3 ] );
220
- },
221
-
222
- focusable: function( element ) {
223
- return focusable( element, !isNaN( $.attr( element, "tabindex" ) ) );
224
- },
225
-
226
- tabbable: function( element ) {
227
- var tabIndex = $.attr( element, "tabindex" ),
228
- isTabIndexNaN = isNaN( tabIndex );
229
- return ( isTabIndexNaN || tabIndex >= 0 ) && focusable( element, !isTabIndexNaN );
230
- }
231
- });
232
-
233
- // support
234
- $(function() {
235
- var body = document.body,
236
- div = body.appendChild( div = document.createElement( "div" ) );
237
-
238
- // access offsetHeight before setting the style to prevent a layout bug
239
- // in IE 9 which causes the elemnt to continue to take up space even
240
- // after it is removed from the DOM (#8026)
241
- div.offsetHeight;
242
-
243
- $.extend( div.style, {
244
- minHeight: "100px",
245
- height: "auto",
246
- padding: 0,
247
- borderWidth: 0
248
- });
249
-
250
- $.support.minHeight = div.offsetHeight === 100;
251
- $.support.selectstart = "onselectstart" in div;
252
-
253
- // set display to none to avoid a layout bug in IE
254
- // http://dev.jquery.com/ticket/4014
255
- body.removeChild( div ).style.display = "none";
256
- });
257
-
258
- // jQuery <1.4.3 uses curCSS, in 1.4.3 - 1.7.2 curCSS = css, 1.8+ only has css
259
- if ( !$.curCSS ) {
260
- $.curCSS = $.css;
261
- }
262
-
263
-
264
-
265
-
266
-
267
- // deprecated
268
- $.extend( $.ui, {
269
- // $.ui.plugin is deprecated. Use the proxy pattern instead.
270
- plugin: {
271
- add: function( module, option, set ) {
272
- var proto = $.ui[ module ].prototype;
273
- for ( var i in set ) {
274
- proto.plugins[ i ] = proto.plugins[ i ] || [];
275
- proto.plugins[ i ].push( [ option, set[ i ] ] );
276
- }
277
- },
278
- call: function( instance, name, args ) {
279
- var set = instance.plugins[ name ];
280
- if ( !set || !instance.element[ 0 ].parentNode ) {
281
- return;
282
- }
283
-
284
- for ( var i = 0; i < set.length; i++ ) {
285
- if ( instance.options[ set[ i ][ 0 ] ] ) {
286
- set[ i ][ 1 ].apply( instance.element, args );
287
- }
288
- }
289
- }
290
- },
291
-
292
- // will be deprecated when we switch to jQuery 1.4 - use jQuery.contains()
293
- contains: function( a, b ) {
294
- return document.compareDocumentPosition ?
295
- a.compareDocumentPosition( b ) & 16 :
296
- a !== b && a.contains( b );
297
- },
298
-
299
- // only used by resizable
300
- hasScroll: function( el, a ) {
301
-
302
- //If overflow is hidden, the element might have extra content, but the user wants to hide it
303
- if ( $( el ).css( "overflow" ) === "hidden") {
304
- return false;
305
- }
306
-
307
- var scroll = ( a && a === "left" ) ? "scrollLeft" : "scrollTop",
308
- has = false;
309
-
310
- if ( el[ scroll ] > 0 ) {
311
- return true;
312
- }
313
-
314
- // TODO: determine which cases actually cause this to happen
315
- // if the element doesn't have the scroll set, see if it's possible to
316
- // set the scroll
317
- el[ scroll ] = 1;
318
- has = ( el[ scroll ] > 0 );
319
- el[ scroll ] = 0;
320
- return has;
321
- },
322
-
323
- // these are odd functions, fix the API or move into individual plugins
324
- isOverAxis: function( x, reference, size ) {
325
- //Determines when x coordinate is over "b" element axis
326
- return ( x > reference ) && ( x < ( reference + size ) );
327
- },
328
- isOver: function( y, x, top, left, height, width ) {
329
- //Determines when x, y coordinates is over "b" element
330
- return $.ui.isOverAxis( y, top, height ) && $.ui.isOverAxis( x, left, width );
331
- }
332
- });
333
-
334
- })( jQuery );
335
- /*!
336
- * jQuery UI Widget 1.8.23
337
- *
338
- * Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)
339
- * Dual licensed under the MIT or GPL Version 2 licenses.
340
- * http://jquery.org/license
341
- *
342
- * http://docs.jquery.com/UI/Widget
343
- */
344
- (function( $, undefined ) {
345
-
346
- // jQuery 1.4+
347
- if ( $.cleanData ) {
348
- var _cleanData = $.cleanData;
349
- $.cleanData = function( elems ) {
350
- for ( var i = 0, elem; (elem = elems[i]) != null; i++ ) {
351
- try {
352
- $( elem ).triggerHandler( "remove" );
353
- // http://bugs.jquery.com/ticket/8235
354
- } catch( e ) {}
355
- }
356
- _cleanData( elems );
357
- };
358
- } else {
359
- var _remove = $.fn.remove;
360
- $.fn.remove = function( selector, keepData ) {
361
- return this.each(function() {
362
- if ( !keepData ) {
363
- if ( !selector || $.filter( selector, [ this ] ).length ) {
364
- $( "*", this ).add( [ this ] ).each(function() {
365
- try {
366
- $( this ).triggerHandler( "remove" );
367
- // http://bugs.jquery.com/ticket/8235
368
- } catch( e ) {}
369
- });
370
- }
371
- }
372
- return _remove.call( $(this), selector, keepData );
373
- });
374
- };
375
- }
376
-
377
- $.widget = function( name, base, prototype ) {
378
- var namespace = name.split( "." )[ 0 ],
379
- fullName;
380
- name = name.split( "." )[ 1 ];
381
- fullName = namespace + "-" + name;
382
-
383
- if ( !prototype ) {
384
- prototype = base;
385
- base = $.Widget;
386
- }
387
-
388
- // create selector for plugin
389
- $.expr[ ":" ][ fullName ] = function( elem ) {
390
- return !!$.data( elem, name );
391
- };
392
-
393
- $[ namespace ] = $[ namespace ] || {};
394
- $[ namespace ][ name ] = function( options, element ) {
395
- // allow instantiation without initializing for simple inheritance
396
- if ( arguments.length ) {
397
- this._createWidget( options, element );
398
- }
399
- };
400
-
401
- var basePrototype = new base();
402
- // we need to make the options hash a property directly on the new instance
403
- // otherwise we'll modify the options hash on the prototype that we're
404
- // inheriting from
405
- // $.each( basePrototype, function( key, val ) {
406
- // if ( $.isPlainObject(val) ) {
407
- // basePrototype[ key ] = $.extend( {}, val );
408
- // }
409
- // });
410
- basePrototype.options = $.extend( true, {}, basePrototype.options );
411
- $[ namespace ][ name ].prototype = $.extend( true, basePrototype, {
412
- namespace: namespace,
413
- widgetName: name,
414
- widgetEventPrefix: $[ namespace ][ name ].prototype.widgetEventPrefix || name,
415
- widgetBaseClass: fullName
416
- }, prototype );
417
-
418
- $.widget.bridge( name, $[ namespace ][ name ] );
419
- };
420
-
421
- $.widget.bridge = function( name, object ) {
422
- $.fn[ name ] = function( options ) {
423
- var isMethodCall = typeof options === "string",
424
- args = Array.prototype.slice.call( arguments, 1 ),
425
- returnValue = this;
426
-
427
- // allow multiple hashes to be passed on init
428
- options = !isMethodCall && args.length ?
429
- $.extend.apply( null, [ true, options ].concat(args) ) :
430
- options;
431
-
432
- // prevent calls to internal methods
433
- if ( isMethodCall && options.charAt( 0 ) === "_" ) {
434
- return returnValue;
435
- }
436
-
437
- if ( isMethodCall ) {
438
- this.each(function() {
439
- var instance = $.data( this, name ),
440
- methodValue = instance && $.isFunction( instance[options] ) ?
441
- instance[ options ].apply( instance, args ) :
442
- instance;
443
- // TODO: add this back in 1.9 and use $.error() (see #5972)
444
- // if ( !instance ) {
445
- // throw "cannot call methods on " + name + " prior to initialization; " +
446
- // "attempted to call method '" + options + "'";
447
- // }
448
- // if ( !$.isFunction( instance[options] ) ) {
449
- // throw "no such method '" + options + "' for " + name + " widget instance";
450
- // }
451
- // var methodValue = instance[ options ].apply( instance, args );
452
- if ( methodValue !== instance && methodValue !== undefined ) {
453
- returnValue = methodValue;
454
- return false;
455
- }
456
- });
457
- } else {
458
- this.each(function() {
459
- var instance = $.data( this, name );
460
- if ( instance ) {
461
- instance.option( options || {} )._init();
462
- } else {
463
- $.data( this, name, new object( options, this ) );
464
- }
465
- });
466
- }
467
-
468
- return returnValue;
469
- };
470
- };
471
-
472
- $.Widget = function( options, element ) {
473
- // allow instantiation without initializing for simple inheritance
474
- if ( arguments.length ) {
475
- this._createWidget( options, element );
476
- }
477
- };
478
-
479
- $.Widget.prototype = {
480
- widgetName: "widget",
481
- widgetEventPrefix: "",
482
- options: {
483
- disabled: false
484
- },
485
- _createWidget: function( options, element ) {
486
- // $.widget.bridge stores the plugin instance, but we do it anyway
487
- // so that it's stored even before the _create function runs
488
- $.data( element, this.widgetName, this );
489
- this.element = $( element );
490
- this.options = $.extend( true, {},
491
- this.options,
492
- this._getCreateOptions(),
493
- options );
494
-
495
- var self = this;
496
- this.element.bind( "remove." + this.widgetName, function() {
497
- self.destroy();
498
- });
499
-
500
- this._create();
501
- this._trigger( "create" );
502
- this._init();
503
- },
504
- _getCreateOptions: function() {
505
- return $.metadata && $.metadata.get( this.element[0] )[ this.widgetName ];
506
- },
507
- _create: function() {},
508
- _init: function() {},
509
-
510
- destroy: function() {
511
- this.element
512
- .unbind( "." + this.widgetName )
513
- .removeData( this.widgetName );
514
- this.widget()
515
- .unbind( "." + this.widgetName )
516
- .removeAttr( "aria-disabled" )
517
- .removeClass(
518
- this.widgetBaseClass + "-disabled " +
519
- "ui-state-disabled" );
520
- },
521
-
522
- widget: function() {
523
- return this.element;
524
- },
525
-
526
- option: function( key, value ) {
527
- var options = key;
528
-
529
- if ( arguments.length === 0 ) {
530
- // don't return a reference to the internal hash
531
- return $.extend( {}, this.options );
532
- }
533
-
534
- if (typeof key === "string" ) {
535
- if ( value === undefined ) {
536
- return this.options[ key ];
537
- }
538
- options = {};
539
- options[ key ] = value;
540
- }
541
-
542
- this._setOptions( options );
543
-
544
- return this;
545
- },
546
- _setOptions: function( options ) {
547
- var self = this;
548
- $.each( options, function( key, value ) {
549
- self._setOption( key, value );
550
- });
551
-
552
- return this;
553
- },
554
- _setOption: function( key, value ) {
555
- this.options[ key ] = value;
556
-
557
- if ( key === "disabled" ) {
558
- this.widget()
559
- [ value ? "addClass" : "removeClass"](
560
- this.widgetBaseClass + "-disabled" + " " +
561
- "ui-state-disabled" )
562
- .attr( "aria-disabled", value );
563
- }
564
-
565
- return this;
566
- },
567
-
568
- enable: function() {
569
- return this._setOption( "disabled", false );
570
- },
571
- disable: function() {
572
- return this._setOption( "disabled", true );
573
- },
574
-
575
- _trigger: function( type, event, data ) {
576
- var prop, orig,
577
- callback = this.options[ type ];
578
-
579
- data = data || {};
580
- event = $.Event( event );
581
- event.type = ( type === this.widgetEventPrefix ?
582
- type :
583
- this.widgetEventPrefix + type ).toLowerCase();
584
- // the original event may come from any element
585
- // so we need to reset the target on the new event
586
- event.target = this.element[ 0 ];
587
-
588
- // copy original event properties over to the new event
589
- orig = event.originalEvent;
590
- if ( orig ) {
591
- for ( prop in orig ) {
592
- if ( !( prop in event ) ) {
593
- event[ prop ] = orig[ prop ];
594
- }
595
- }
596
- }
597
-
598
- this.element.trigger( event, data );
599
-
600
- return !( $.isFunction(callback) &&
601
- callback.call( this.element[0], event, data ) === false ||
602
- event.isDefaultPrevented() );
603
- }
604
- };
605
-
606
- })( jQuery );
607
- /*!
608
- * jQuery UI Position 1.8.23
609
- *
610
- * Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)
611
- * Dual licensed under the MIT or GPL Version 2 licenses.
612
- * http://jquery.org/license
613
- *
614
- * http://docs.jquery.com/UI/Position
615
- */
616
- (function( $, undefined ) {
617
-
618
- $.ui = $.ui || {};
619
-
620
- var horizontalPositions = /left|center|right/,
621
- verticalPositions = /top|center|bottom/,
622
- center = "center",
623
- support = {},
624
- _position = $.fn.position,
625
- _offset = $.fn.offset;
626
-
627
- $.fn.position = function( options ) {
628
- if ( !options || !options.of ) {
629
- return _position.apply( this, arguments );
630
- }
631
-
632
- // make a copy, we don't want to modify arguments
633
- options = $.extend( {}, options );
634
-
635
- var target = $( options.of ),
636
- targetElem = target[0],
637
- collision = ( options.collision || "flip" ).split( " " ),
638
- offset = options.offset ? options.offset.split( " " ) : [ 0, 0 ],
639
- targetWidth,
640
- targetHeight,
641
- basePosition;
642
-
643
- if ( targetElem.nodeType === 9 ) {
644
- targetWidth = target.width();
645
- targetHeight = target.height();
646
- basePosition = { top: 0, left: 0 };
647
- // TODO: use $.isWindow() in 1.9
648
- } else if ( targetElem.setTimeout ) {
649
- targetWidth = target.width();
650
- targetHeight = target.height();
651
- basePosition = { top: target.scrollTop(), left: target.scrollLeft() };
652
- } else if ( targetElem.preventDefault ) {
653
- // force left top to allow flipping
654
- options.at = "left top";
655
- targetWidth = targetHeight = 0;
656
- basePosition = { top: options.of.pageY, left: options.of.pageX };
657
- } else {
658
- targetWidth = target.outerWidth();
659
- targetHeight = target.outerHeight();
660
- basePosition = target.offset();
661
- }
662
-
663
- // force my and at to have valid horizontal and veritcal positions
664
- // if a value is missing or invalid, it will be converted to center
665
- $.each( [ "my", "at" ], function() {
666
- var pos = ( options[this] || "" ).split( " " );
667
- if ( pos.length === 1) {
668
- pos = horizontalPositions.test( pos[0] ) ?
669
- pos.concat( [center] ) :
670
- verticalPositions.test( pos[0] ) ?
671
- [ center ].concat( pos ) :
672
- [ center, center ];
673
- }
674
- pos[ 0 ] = horizontalPositions.test( pos[0] ) ? pos[ 0 ] : center;
675
- pos[ 1 ] = verticalPositions.test( pos[1] ) ? pos[ 1 ] : center;
676
- options[ this ] = pos;
677
- });
678
-
679
- // normalize collision option
680
- if ( collision.length === 1 ) {
681
- collision[ 1 ] = collision[ 0 ];
682
- }
683
-
684
- // normalize offset option
685
- offset[ 0 ] = parseInt( offset[0], 10 ) || 0;
686
- if ( offset.length === 1 ) {
687
- offset[ 1 ] = offset[ 0 ];
688
- }
689
- offset[ 1 ] = parseInt( offset[1], 10 ) || 0;
690
-
691
- if ( options.at[0] === "right" ) {
692
- basePosition.left += targetWidth;
693
- } else if ( options.at[0] === center ) {
694
- basePosition.left += targetWidth / 2;
695
- }
696
-
697
- if ( options.at[1] === "bottom" ) {
698
- basePosition.top += targetHeight;
699
- } else if ( options.at[1] === center ) {
700
- basePosition.top += targetHeight / 2;
701
- }
702
-
703
- basePosition.left += offset[ 0 ];
704
- basePosition.top += offset[ 1 ];
705
-
706
- return this.each(function() {
707
- var elem = $( this ),
708
- elemWidth = elem.outerWidth(),
709
- elemHeight = elem.outerHeight(),
710
- marginLeft = parseInt( $.curCSS( this, "marginLeft", true ) ) || 0,
711
- marginTop = parseInt( $.curCSS( this, "marginTop", true ) ) || 0,
712
- collisionWidth = elemWidth + marginLeft +
713
- ( parseInt( $.curCSS( this, "marginRight", true ) ) || 0 ),
714
- collisionHeight = elemHeight + marginTop +
715
- ( parseInt( $.curCSS( this, "marginBottom", true ) ) || 0 ),
716
- position = $.extend( {}, basePosition ),
717
- collisionPosition;
718
-
719
- if ( options.my[0] === "right" ) {
720
- position.left -= elemWidth;
721
- } else if ( options.my[0] === center ) {
722
- position.left -= elemWidth / 2;
723
- }
724
-
725
- if ( options.my[1] === "bottom" ) {
726
- position.top -= elemHeight;
727
- } else if ( options.my[1] === center ) {
728
- position.top -= elemHeight / 2;
729
- }
730
-
731
- // prevent fractions if jQuery version doesn't support them (see #5280)
732
- if ( !support.fractions ) {
733
- position.left = Math.round( position.left );
734
- position.top = Math.round( position.top );
735
- }
736
-
737
- collisionPosition = {
738
- left: position.left - marginLeft,
739
- top: position.top - marginTop
740
- };
741
-
742
- $.each( [ "left", "top" ], function( i, dir ) {
743
- if ( $.ui.position[ collision[i] ] ) {
744
- $.ui.position[ collision[i] ][ dir ]( position, {
745
- targetWidth: targetWidth,
746
- targetHeight: targetHeight,
747
- elemWidth: elemWidth,
748
- elemHeight: elemHeight,
749
- collisionPosition: collisionPosition,
750
- collisionWidth: collisionWidth,
751
- collisionHeight: collisionHeight,
752
- offset: offset,
753
- my: options.my,
754
- at: options.at
755
- });
756
- }
757
- });
758
-
759
- if ( $.fn.bgiframe ) {
760
- elem.bgiframe();
761
- }
762
- elem.offset( $.extend( position, { using: options.using } ) );
763
- });
764
- };
765
-
766
- $.ui.position = {
767
- fit: {
768
- left: function( position, data ) {
769
- var win = $( window ),
770
- over = data.collisionPosition.left + data.collisionWidth - win.width() - win.scrollLeft();
771
- position.left = over > 0 ? position.left - over : Math.max( position.left - data.collisionPosition.left, position.left );
772
- },
773
- top: function( position, data ) {
774
- var win = $( window ),
775
- over = data.collisionPosition.top + data.collisionHeight - win.height() - win.scrollTop();
776
- position.top = over > 0 ? position.top - over : Math.max( position.top - data.collisionPosition.top, position.top );
777
- }
778
- },
779
-
780
- flip: {
781
- left: function( position, data ) {
782
- if ( data.at[0] === center ) {
783
- return;
784
- }
785
- var win = $( window ),
786
- over = data.collisionPosition.left + data.collisionWidth - win.width() - win.scrollLeft(),
787
- myOffset = data.my[ 0 ] === "left" ?
788
- -data.elemWidth :
789
- data.my[ 0 ] === "right" ?
790
- data.elemWidth :
791
- 0,
792
- atOffset = data.at[ 0 ] === "left" ?
793
- data.targetWidth :
794
- -data.targetWidth,
795
- offset = -2 * data.offset[ 0 ];
796
- position.left += data.collisionPosition.left < 0 ?
797
- myOffset + atOffset + offset :
798
- over > 0 ?
799
- myOffset + atOffset + offset :
800
- 0;
801
- },
802
- top: function( position, data ) {
803
- if ( data.at[1] === center ) {
804
- return;
805
- }
806
- var win = $( window ),
807
- over = data.collisionPosition.top + data.collisionHeight - win.height() - win.scrollTop(),
808
- myOffset = data.my[ 1 ] === "top" ?
809
- -data.elemHeight :
810
- data.my[ 1 ] === "bottom" ?
811
- data.elemHeight :
812
- 0,
813
- atOffset = data.at[ 1 ] === "top" ?
814
- data.targetHeight :
815
- -data.targetHeight,
816
- offset = -2 * data.offset[ 1 ];
817
- position.top += data.collisionPosition.top < 0 ?
818
- myOffset + atOffset + offset :
819
- over > 0 ?
820
- myOffset + atOffset + offset :
821
- 0;
822
- }
823
- }
824
- };
825
-
826
- // offset setter from jQuery 1.4
827
- if ( !$.offset.setOffset ) {
828
- $.offset.setOffset = function( elem, options ) {
829
- // set position first, in-case top/left are set even on static elem
830
- if ( /static/.test( $.curCSS( elem, "position" ) ) ) {
831
- elem.style.position = "relative";
832
- }
833
- var curElem = $( elem ),
834
- curOffset = curElem.offset(),
835
- curTop = parseInt( $.curCSS( elem, "top", true ), 10 ) || 0,
836
- curLeft = parseInt( $.curCSS( elem, "left", true ), 10) || 0,
837
- props = {
838
- top: (options.top - curOffset.top) + curTop,
839
- left: (options.left - curOffset.left) + curLeft
840
- };
841
-
842
- if ( 'using' in options ) {
843
- options.using.call( elem, props );
844
- } else {
845
- curElem.css( props );
846
- }
847
- };
848
-
849
- $.fn.offset = function( options ) {
850
- var elem = this[ 0 ];
851
- if ( !elem || !elem.ownerDocument ) { return null; }
852
- if ( options ) {
853
- if ( $.isFunction( options ) ) {
854
- return this.each(function( i ) {
855
- $( this ).offset( options.call( this, i, $( this ).offset() ) );
856
- });
857
- }
858
- return this.each(function() {
859
- $.offset.setOffset( this, options );
860
- });
861
- }
862
- return _offset.call( this );
863
- };
864
- }
865
-
866
- // jQuery <1.4.3 uses curCSS, in 1.4.3 - 1.7.2 curCSS = css, 1.8+ only has css
867
- if ( !$.curCSS ) {
868
- $.curCSS = $.css;
869
- }
870
-
871
- // fraction support test (older versions of jQuery don't support fractions)
872
- (function () {
873
- var body = document.getElementsByTagName( "body" )[ 0 ],
874
- div = document.createElement( "div" ),
875
- testElement, testElementParent, testElementStyle, offset, offsetTotal;
876
-
877
- //Create a "fake body" for testing based on method used in jQuery.support
878
- testElement = document.createElement( body ? "div" : "body" );
879
- testElementStyle = {
880
- visibility: "hidden",
881
- width: 0,
882
- height: 0,
883
- border: 0,
884
- margin: 0,
885
- background: "none"
886
- };
887
- if ( body ) {
888
- $.extend( testElementStyle, {
889
- position: "absolute",
890
- left: "-1000px",
891
- top: "-1000px"
892
- });
893
- }
894
- for ( var i in testElementStyle ) {
895
- testElement.style[ i ] = testElementStyle[ i ];
896
- }
897
- testElement.appendChild( div );
898
- testElementParent = body || document.documentElement;
899
- testElementParent.insertBefore( testElement, testElementParent.firstChild );
900
-
901
- div.style.cssText = "position: absolute; left: 10.7432222px; top: 10.432325px; height: 30px; width: 201px;";
902
-
903
- offset = $( div ).offset( function( _, offset ) {
904
- return offset;
905
- }).offset();
906
-
907
- testElement.innerHTML = "";
908
- testElementParent.removeChild( testElement );
909
-
910
- offsetTotal = offset.top + offset.left + ( body ? 2000 : 0 );
911
- support.fractions = offsetTotal > 21 && offsetTotal < 22;
912
- })();
913
-
914
- }( jQuery ));
915
- /*!
916
- * jQuery UI Autocomplete 1.8.23
917
- *
918
- * Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)
919
- * Dual licensed under the MIT or GPL Version 2 licenses.
920
- * http://jquery.org/license
921
- *
922
- * http://docs.jquery.com/UI/Autocomplete
923
- *
924
- * Depends:
925
- * jquery.ui.core.js
926
- * jquery.ui.widget.js
927
- * jquery.ui.position.js
928
- */
929
- (function( $, undefined ) {
930
-
931
- // used to prevent race conditions with remote data sources
932
- var requestIndex = 0;
933
-
934
- $.widget( "ui.autocomplete", {
935
- options: {
936
- appendTo: "body",
937
- autoFocus: false,
938
- delay: 300,
939
- minLength: 1,
940
- position: {
941
- my: "left top",
942
- at: "left bottom",
943
- collision: "none"
944
- },
945
- source: null
946
- },
947
-
948
- pending: 0,
949
-
950
- _create: function() {
951
- var self = this,
952
- doc = this.element[ 0 ].ownerDocument,
953
- suppressKeyPress;
954
- this.isMultiLine = this.element.is( "textarea" );
955
-
956
- this.element
957
- .addClass( "ui-autocomplete-input" )
958
- .attr( "autocomplete", "off" )
959
- // TODO verify these actually work as intended
960
- .attr({
961
- role: "textbox",
962
- "aria-autocomplete": "list",
963
- "aria-haspopup": "true"
964
- })
965
- .bind( "keydown.autocomplete", function( event ) {
966
- if ( self.options.disabled || self.element.propAttr( "readOnly" ) ) {
967
- return;
968
- }
969
-
970
- suppressKeyPress = false;
971
- var keyCode = $.ui.keyCode;
972
- switch( event.keyCode ) {
973
- case keyCode.PAGE_UP:
974
- self._move( "previousPage", event );
975
- break;
976
- case keyCode.PAGE_DOWN:
977
- self._move( "nextPage", event );
978
- break;
979
- case keyCode.UP:
980
- self._keyEvent( "previous", event );
981
- break;
982
- case keyCode.DOWN:
983
- self._keyEvent( "next", event );
984
- break;
985
- case keyCode.ENTER:
986
- case keyCode.NUMPAD_ENTER:
987
- // when menu is open and has focus
988
- if ( self.menu.active ) {
989
- // #6055 - Opera still allows the keypress to occur
990
- // which causes forms to submit
991
- suppressKeyPress = true;
992
- event.preventDefault();
993
- }
994
- //passthrough - ENTER and TAB both select the current element
995
- case keyCode.TAB:
996
- if ( !self.menu.active ) {
997
- return;
998
- }
999
- self.menu.select( event );
1000
- break;
1001
- case keyCode.ESCAPE:
1002
- self.element.val( self.term );
1003
- self.close( event );
1004
- break;
1005
- default:
1006
- // keypress is triggered before the input value is changed
1007
- clearTimeout( self.searching );
1008
- self.searching = setTimeout(function() {
1009
- // only search if the value has changed
1010
- if ( self.term != self.element.val() ) {
1011
- self.selectedItem = null;
1012
- self.search( null, event );
1013
- }
1014
- }, self.options.delay );
1015
- break;
1016
- }
1017
- })
1018
- .bind( "keypress.autocomplete", function( event ) {
1019
- if ( suppressKeyPress ) {
1020
- suppressKeyPress = false;
1021
- event.preventDefault();
1022
- }
1023
- })
1024
- .bind( "focus.autocomplete", function() {
1025
- if ( self.options.disabled ) {
1026
- return;
1027
- }
1028
-
1029
- self.selectedItem = null;
1030
- self.previous = self.element.val();
1031
- })
1032
- .bind( "blur.autocomplete", function( event ) {
1033
- if ( self.options.disabled ) {
1034
- return;
1035
- }
1036
-
1037
- clearTimeout( self.searching );
1038
- // clicks on the menu (or a button to trigger a search) will cause a blur event
1039
- self.closing = setTimeout(function() {
1040
- self.close( event );
1041
- self._change( event );
1042
- }, 150 );
1043
- });
1044
- this._initSource();
1045
- this.menu = $( "<ul></ul>" )
1046
- .addClass( "ui-autocomplete" )
1047
- .appendTo( $( this.options.appendTo || "body", doc )[0] )
1048
- // prevent the close-on-blur in case of a "slow" click on the menu (long mousedown)
1049
- .mousedown(function( event ) {
1050
- // clicking on the scrollbar causes focus to shift to the body
1051
- // but we can't detect a mouseup or a click immediately afterward
1052
- // so we have to track the next mousedown and close the menu if
1053
- // the user clicks somewhere outside of the autocomplete
1054
- var menuElement = self.menu.element[ 0 ];
1055
- if ( !$( event.target ).closest( ".ui-menu-item" ).length ) {
1056
- setTimeout(function() {
1057
- $( document ).one( 'mousedown', function( event ) {
1058
- if ( event.target !== self.element[ 0 ] &&
1059
- event.target !== menuElement &&
1060
- !$.ui.contains( menuElement, event.target ) ) {
1061
- self.close();
1062
- }
1063
- });
1064
- }, 1 );
1065
- }
1066
-
1067
- // use another timeout to make sure the blur-event-handler on the input was already triggered
1068
- setTimeout(function() {
1069
- clearTimeout( self.closing );
1070
- }, 13);
1071
- })
1072
- .menu({
1073
- focus: function( event, ui ) {
1074
- var item = ui.item.data( "item.autocomplete" );
1075
- if ( false !== self._trigger( "focus", event, { item: item } ) ) {
1076
- // use value to match what will end up in the input, if it was a key event
1077
- if ( /^key/.test(event.originalEvent.type) ) {
1078
- self.element.val( item.value );
1079
- }
1080
- }
1081
- },
1082
- selected: function( event, ui ) {
1083
- var item = ui.item.data( "item.autocomplete" ),
1084
- previous = self.previous;
1085
-
1086
- // only trigger when focus was lost (click on menu)
1087
- if ( self.element[0] !== doc.activeElement ) {
1088
- self.element.focus();
1089
- self.previous = previous;
1090
- // #6109 - IE triggers two focus events and the second
1091
- // is asynchronous, so we need to reset the previous
1092
- // term synchronously and asynchronously :-(
1093
- setTimeout(function() {
1094
- self.previous = previous;
1095
- self.selectedItem = item;
1096
- }, 1);
1097
- }
1098
-
1099
- if ( false !== self._trigger( "select", event, { item: item } ) ) {
1100
- self.element.val( item.value );
1101
- }
1102
- // reset the term after the select event
1103
- // this allows custom select handling to work properly
1104
- self.term = self.element.val();
1105
-
1106
- self.close( event );
1107
- self.selectedItem = item;
1108
- },
1109
- blur: function( event, ui ) {
1110
- // don't set the value of the text field if it's already correct
1111
- // this prevents moving the cursor unnecessarily
1112
- if ( self.menu.element.is(":visible") &&
1113
- ( self.element.val() !== self.term ) ) {
1114
- self.element.val( self.term );
1115
- }
1116
- }
1117
- })
1118
- .zIndex( this.element.zIndex() + 1 )
1119
- // workaround for jQuery bug #5781 http://dev.jquery.com/ticket/5781
1120
- .css({ top: 0, left: 0 })
1121
- .hide()
1122
- .data( "menu" );
1123
- if ( $.fn.bgiframe ) {
1124
- this.menu.element.bgiframe();
1125
- }
1126
- // turning off autocomplete prevents the browser from remembering the
1127
- // value when navigating through history, so we re-enable autocomplete
1128
- // if the page is unloaded before the widget is destroyed. #7790
1129
- self.beforeunloadHandler = function() {
1130
- self.element.removeAttr( "autocomplete" );
1131
- };
1132
- $( window ).bind( "beforeunload", self.beforeunloadHandler );
1133
- },
1134
-
1135
- destroy: function() {
1136
- this.element
1137
- .removeClass( "ui-autocomplete-input" )
1138
- .removeAttr( "autocomplete" )
1139
- .removeAttr( "role" )
1140
- .removeAttr( "aria-autocomplete" )
1141
- .removeAttr( "aria-haspopup" );
1142
- this.menu.element.remove();
1143
- $( window ).unbind( "beforeunload", this.beforeunloadHandler );
1144
- $.Widget.prototype.destroy.call( this );
1145
- },
1146
-
1147
- _setOption: function( key, value ) {
1148
- $.Widget.prototype._setOption.apply( this, arguments );
1149
- if ( key === "source" ) {
1150
- this._initSource();
1151
- }
1152
- if ( key === "appendTo" ) {
1153
- this.menu.element.appendTo( $( value || "body", this.element[0].ownerDocument )[0] )
1154
- }
1155
- if ( key === "disabled" && value && this.xhr ) {
1156
- this.xhr.abort();
1157
- }
1158
- },
1159
-
1160
- _initSource: function() {
1161
- var self = this,
1162
- array,
1163
- url;
1164
- if ( $.isArray(this.options.source) ) {
1165
- array = this.options.source;
1166
- this.source = function( request, response ) {
1167
- response( $.ui.autocomplete.filter(array, request.term) );
1168
- };
1169
- } else if ( typeof this.options.source === "string" ) {
1170
- url = this.options.source;
1171
- this.source = function( request, response ) {
1172
- if ( self.xhr ) {
1173
- self.xhr.abort();
1174
- }
1175
- self.xhr = $.ajax({
1176
- url: url,
1177
- data: request,
1178
- dataType: "json",
1179
- success: function( data, status ) {
1180
- response( data );
1181
- },
1182
- error: function() {
1183
- response( [] );
1184
- }
1185
- });
1186
- };
1187
- } else {
1188
- this.source = this.options.source;
1189
- }
1190
- },
1191
-
1192
- search: function( value, event ) {
1193
- value = value != null ? value : this.element.val();
1194
-
1195
- // always save the actual value, not the one passed as an argument
1196
- this.term = this.element.val();
1197
-
1198
- if ( value.length < this.options.minLength ) {
1199
- return this.close( event );
1200
- }
1201
-
1202
- clearTimeout( this.closing );
1203
- if ( this._trigger( "search", event ) === false ) {
1204
- return;
1205
- }
1206
-
1207
- return this._search( value );
1208
- },
1209
-
1210
- _search: function( value ) {
1211
- this.pending++;
1212
- this.element.addClass( "ui-autocomplete-loading" );
1213
-
1214
- this.source( { term: value }, this._response() );
1215
- },
1216
-
1217
- _response: function() {
1218
- var that = this,
1219
- index = ++requestIndex;
1220
-
1221
- return function( content ) {
1222
- if ( index === requestIndex ) {
1223
- that.__response( content );
1224
- }
1225
-
1226
- that.pending--;
1227
- if ( !that.pending ) {
1228
- that.element.removeClass( "ui-autocomplete-loading" );
1229
- }
1230
- };
1231
- },
1232
-
1233
- __response: function( content ) {
1234
- if ( !this.options.disabled && content && content.length ) {
1235
- content = this._normalize( content );
1236
- this._suggest( content );
1237
- this._trigger( "open" );
1238
- } else {
1239
- this.close();
1240
- }
1241
- },
1242
-
1243
- close: function( event ) {
1244
- clearTimeout( this.closing );
1245
- if ( this.menu.element.is(":visible") ) {
1246
- this.menu.element.hide();
1247
- this.menu.deactivate();
1248
- this._trigger( "close", event );
1249
- }
1250
- },
1251
-
1252
- _change: function( event ) {
1253
- if ( this.previous !== this.element.val() ) {
1254
- this._trigger( "change", event, { item: this.selectedItem } );
1255
- }
1256
- },
1257
-
1258
- _normalize: function( items ) {
1259
- // assume all items have the right format when the first item is complete
1260
- if ( items.length && items[0].label && items[0].value ) {
1261
- return items;
1262
- }
1263
- return $.map( items, function(item) {
1264
- if ( typeof item === "string" ) {
1265
- return {
1266
- label: item,
1267
- value: item
1268
- };
1269
- }
1270
- return $.extend({
1271
- label: item.label || item.value,
1272
- value: item.value || item.label
1273
- }, item );
1274
- });
1275
- },
1276
-
1277
- _suggest: function( items ) {
1278
- var ul = this.menu.element
1279
- .empty()
1280
- .zIndex( this.element.zIndex() + 1 );
1281
- this._renderMenu( ul, items );
1282
- // TODO refresh should check if the active item is still in the dom, removing the need for a manual deactivate
1283
- this.menu.deactivate();
1284
- this.menu.refresh();
1285
-
1286
- // size and position menu
1287
- ul.show();
1288
- this._resizeMenu();
1289
- ul.position( $.extend({
1290
- of: this.element
1291
- }, this.options.position ));
1292
-
1293
- if ( this.options.autoFocus ) {
1294
- this.menu.next( new $.Event("mouseover") );
1295
- }
1296
- },
1297
-
1298
- _resizeMenu: function() {
1299
- var ul = this.menu.element;
1300
- ul.outerWidth( Math.max(
1301
- // Firefox wraps long text (possibly a rounding bug)
1302
- // so we add 1px to avoid the wrapping (#7513)
1303
- ul.width( "" ).outerWidth() + 1,
1304
- this.element.outerWidth()
1305
- ) );
1306
- },
1307
-
1308
- _renderMenu: function( ul, items ) {
1309
- var self = this;
1310
- $.each( items, function( index, item ) {
1311
- self._renderItem( ul, item );
1312
- });
1313
- },
1314
-
1315
- _renderItem: function( ul, item) {
1316
- return $( "<li></li>" )
1317
- .data( "item.autocomplete", item )
1318
- .append( $( "<a></a>" ).text( item.label ) )
1319
- .appendTo( ul );
1320
- },
1321
-
1322
- _move: function( direction, event ) {
1323
- if ( !this.menu.element.is(":visible") ) {
1324
- this.search( null, event );
1325
- return;
1326
- }
1327
- if ( this.menu.first() && /^previous/.test(direction) ||
1328
- this.menu.last() && /^next/.test(direction) ) {
1329
- this.element.val( this.term );
1330
- this.menu.deactivate();
1331
- return;
1332
- }
1333
- this.menu[ direction ]( event );
1334
- },
1335
-
1336
- widget: function() {
1337
- return this.menu.element;
1338
- },
1339
- _keyEvent: function( keyEvent, event ) {
1340
- if ( !this.isMultiLine || this.menu.element.is( ":visible" ) ) {
1341
- this._move( keyEvent, event );
1342
-
1343
- // prevents moving cursor to beginning/end of the text field in some browsers
1344
- event.preventDefault();
1345
- }
1346
- }
1347
- });
1348
-
1349
- $.extend( $.ui.autocomplete, {
1350
- escapeRegex: function( value ) {
1351
- return value.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&");
1352
- },
1353
- filter: function(array, term) {
1354
- var matcher = new RegExp( $.ui.autocomplete.escapeRegex(term), "i" );
1355
- return $.grep( array, function(value) {
1356
- return matcher.test( value.label || value.value || value );
1357
- });
1358
- }
1359
- });
1360
-
1361
- }( jQuery ));
1362
-
1363
- /*
1364
- * jQuery UI Menu (not officially released)
1365
- *
1366
- * This widget isn't yet finished and the API is subject to change. We plan to finish
1367
- * it for the next release. You're welcome to give it a try anyway and give us feedback,
1368
- * as long as you're okay with migrating your code later on. We can help with that, too.
1369
- *
1370
- * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
1371
- * Dual licensed under the MIT or GPL Version 2 licenses.
1372
- * http://jquery.org/license
1373
- *
1374
- * http://docs.jquery.com/UI/Menu
1375
- *
1376
- * Depends:
1377
- * jquery.ui.core.js
1378
- * jquery.ui.widget.js
1379
- */
1380
- (function($) {
1381
-
1382
- $.widget("ui.menu", {
1383
- _create: function() {
1384
- var self = this;
1385
- this.element
1386
- .addClass("ui-menu ui-widget ui-widget-content ui-corner-all")
1387
- .attr({
1388
- role: "listbox",
1389
- "aria-activedescendant": "ui-active-menuitem"
1390
- })
1391
- .click(function( event ) {
1392
- if ( !$( event.target ).closest( ".ui-menu-item a" ).length ) {
1393
- return;
1394
- }
1395
- // temporary
1396
- event.preventDefault();
1397
- self.select( event );
1398
- });
1399
- this.refresh();
1400
- },
1401
-
1402
- refresh: function() {
1403
- var self = this;
1404
-
1405
- // don't refresh list items that are already adapted
1406
- var items = this.element.children("li:not(.ui-menu-item):has(a)")
1407
- .addClass("ui-menu-item")
1408
- .attr("role", "menuitem");
1409
-
1410
- items.children("a")
1411
- .addClass("ui-corner-all")
1412
- .attr("tabindex", -1)
1413
- // mouseenter doesn't work with event delegation
1414
- .mouseenter(function( event ) {
1415
- self.activate( event, $(this).parent() );
1416
- })
1417
- .mouseleave(function() {
1418
- self.deactivate();
1419
- });
1420
- },
1421
-
1422
- activate: function( event, item ) {
1423
- this.deactivate();
1424
- if (this.hasScroll()) {
1425
- var offset = item.offset().top - this.element.offset().top,
1426
- scroll = this.element.scrollTop(),
1427
- elementHeight = this.element.height();
1428
- if (offset < 0) {
1429
- this.element.scrollTop( scroll + offset);
1430
- } else if (offset >= elementHeight) {
1431
- this.element.scrollTop( scroll + offset - elementHeight + item.height());
1432
- }
1433
- }
1434
- this.active = item.eq(0)
1435
- .children("a")
1436
- .addClass("ui-state-hover")
1437
- .attr("id", "ui-active-menuitem")
1438
- .end();
1439
- this._trigger("focus", event, { item: item });
1440
- },
1441
-
1442
- deactivate: function() {
1443
- if (!this.active) { return; }
1444
-
1445
- this.active.children("a")
1446
- .removeClass("ui-state-hover")
1447
- .removeAttr("id");
1448
- this._trigger("blur");
1449
- this.active = null;
1450
- },
1451
-
1452
- next: function(event) {
1453
- this.move("next", ".ui-menu-item:first", event);
1454
- },
1455
-
1456
- previous: function(event) {
1457
- this.move("prev", ".ui-menu-item:last", event);
1458
- },
1459
-
1460
- first: function() {
1461
- return this.active && !this.active.prevAll(".ui-menu-item").length;
1462
- },
1463
-
1464
- last: function() {
1465
- return this.active && !this.active.nextAll(".ui-menu-item").length;
1466
- },
1467
-
1468
- move: function(direction, edge, event) {
1469
- if (!this.active) {
1470
- this.activate(event, this.element.children(edge));
1471
- return;
1472
- }
1473
- var next = this.active[direction + "All"](".ui-menu-item").eq(0);
1474
- if (next.length) {
1475
- this.activate(event, next);
1476
- } else {
1477
- this.activate(event, this.element.children(edge));
1478
- }
1479
- },
1480
-
1481
- // TODO merge with previousPage
1482
- nextPage: function(event) {
1483
- if (this.hasScroll()) {
1484
- // TODO merge with no-scroll-else
1485
- if (!this.active || this.last()) {
1486
- this.activate(event, this.element.children(".ui-menu-item:first"));
1487
- return;
1488
- }
1489
- var base = this.active.offset().top,
1490
- height = this.element.height(),
1491
- result = this.element.children(".ui-menu-item").filter(function() {
1492
- var close = $(this).offset().top - base - height + $(this).height();
1493
- // TODO improve approximation
1494
- return close < 10 && close > -10;
1495
- });
1496
-
1497
- // TODO try to catch this earlier when scrollTop indicates the last page anyway
1498
- if (!result.length) {
1499
- result = this.element.children(".ui-menu-item:last");
1500
- }
1501
- this.activate(event, result);
1502
- } else {
1503
- this.activate(event, this.element.children(".ui-menu-item")
1504
- .filter(!this.active || this.last() ? ":first" : ":last"));
1505
- }
1506
- },
1507
-
1508
- // TODO merge with nextPage
1509
- previousPage: function(event) {
1510
- if (this.hasScroll()) {
1511
- // TODO merge with no-scroll-else
1512
- if (!this.active || this.first()) {
1513
- this.activate(event, this.element.children(".ui-menu-item:last"));
1514
- return;
1515
- }
1516
-
1517
- var base = this.active.offset().top,
1518
- height = this.element.height(),
1519
- result = this.element.children(".ui-menu-item").filter(function() {
1520
- var close = $(this).offset().top - base + height - $(this).height();
1521
- // TODO improve approximation
1522
- return close < 10 && close > -10;
1523
- });
1524
-
1525
- // TODO try to catch this earlier when scrollTop indicates the last page anyway
1526
- if (!result.length) {
1527
- result = this.element.children(".ui-menu-item:first");
1528
- }
1529
- this.activate(event, result);
1530
- } else {
1531
- this.activate(event, this.element.children(".ui-menu-item")
1532
- .filter(!this.active || this.first() ? ":last" : ":first"));
1533
- }
1534
- },
1535
-
1536
- hasScroll: function() {
1537
- return this.element.height() < this.element[ $.fn.prop ? "prop" : "attr" ]("scrollHeight");
1538
- },
1539
-
1540
- select: function( event ) {
1541
- this._trigger("selected", event, { item: this.active });
1542
- }
1543
- });
1544
-
1545
- }(jQuery));
1546
- /*!
1547
- * jQuery UI Datepicker 1.8.23
1548
- *
1549
- * Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)
1550
- * Dual licensed under the MIT or GPL Version 2 licenses.
1551
- * http://jquery.org/license
1552
- *
1553
- * http://docs.jquery.com/UI/Datepicker
1554
- *
1555
- * Depends:
1556
- * jquery.ui.core.js
1557
- */
1558
- (function( $, undefined ) {
1559
-
1560
- $.extend($.ui, { datepicker: { version: "1.8.23" } });
1561
-
1562
- var PROP_NAME = 'datepicker';
1563
- var dpuuid = new Date().getTime();
1564
- var instActive;
1565
-
1566
- /* Date picker manager.
1567
- Use the singleton instance of this class, $.datepicker, to interact with the date picker.
1568
- Settings for (groups of) date pickers are maintained in an instance object,
1569
- allowing multiple different settings on the same page. */
1570
-
1571
- function Datepicker() {
1572
- this.debug = false; // Change this to true to start debugging
1573
- this._curInst = null; // The current instance in use
1574
- this._keyEvent = false; // If the last event was a key event
1575
- this._disabledInputs = []; // List of date picker inputs that have been disabled
1576
- this._datepickerShowing = false; // True if the popup picker is showing , false if not
1577
- this._inDialog = false; // True if showing within a "dialog", false if not
1578
- this._mainDivId = 'ui-datepicker-div'; // The ID of the main datepicker division
1579
- this._inlineClass = 'ui-datepicker-inline'; // The name of the inline marker class
1580
- this._appendClass = 'ui-datepicker-append'; // The name of the append marker class
1581
- this._triggerClass = 'ui-datepicker-trigger'; // The name of the trigger marker class
1582
- this._dialogClass = 'ui-datepicker-dialog'; // The name of the dialog marker class
1583
- this._disableClass = 'ui-datepicker-disabled'; // The name of the disabled covering marker class
1584
- this._unselectableClass = 'ui-datepicker-unselectable'; // The name of the unselectable cell marker class
1585
- this._currentClass = 'ui-datepicker-current-day'; // The name of the current day marker class
1586
- this._dayOverClass = 'ui-datepicker-days-cell-over'; // The name of the day hover marker class
1587
- this.regional = []; // Available regional settings, indexed by language code
1588
- this.regional[''] = { // Default regional settings
1589
- closeText: 'Done', // Display text for close link
1590
- prevText: 'Prev', // Display text for previous month link
1591
- nextText: 'Next', // Display text for next month link
1592
- currentText: 'Today', // Display text for current month link
1593
- monthNames: ['January','February','March','April','May','June',
1594
- 'July','August','September','October','November','December'], // Names of months for drop-down and formatting
1595
- monthNamesShort: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'], // For formatting
1596
- dayNames: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'], // For formatting
1597
- dayNamesShort: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'], // For formatting
1598
- dayNamesMin: ['Su','Mo','Tu','We','Th','Fr','Sa'], // Column headings for days starting at Sunday
1599
- weekHeader: 'Wk', // Column header for week of the year
1600
- dateFormat: 'mm/dd/yy', // See format options on parseDate
1601
- firstDay: 0, // The first day of the week, Sun = 0, Mon = 1, ...
1602
- isRTL: false, // True if right-to-left language, false if left-to-right
1603
- showMonthAfterYear: false, // True if the year select precedes month, false for month then year
1604
- yearSuffix: '' // Additional text to append to the year in the month headers
1605
- };
1606
- this._defaults = { // Global defaults for all the date picker instances
1607
- showOn: 'focus', // 'focus' for popup on focus,
1608
- // 'button' for trigger button, or 'both' for either
1609
- showAnim: 'fadeIn', // Name of jQuery animation for popup
1610
- showOptions: {}, // Options for enhanced animations
1611
- defaultDate: null, // Used when field is blank: actual date,
1612
- // +/-number for offset from today, null for today
1613
- appendText: '', // Display text following the input box, e.g. showing the format
1614
- buttonText: '...', // Text for trigger button
1615
- buttonImage: '', // URL for trigger button image
1616
- buttonImageOnly: false, // True if the image appears alone, false if it appears on a button
1617
- hideIfNoPrevNext: false, // True to hide next/previous month links
1618
- // if not applicable, false to just disable them
1619
- navigationAsDateFormat: false, // True if date formatting applied to prev/today/next links
1620
- gotoCurrent: false, // True if today link goes back to current selection instead
1621
- changeMonth: false, // True if month can be selected directly, false if only prev/next
1622
- changeYear: false, // True if year can be selected directly, false if only prev/next
1623
- yearRange: 'c-10:c+10', // Range of years to display in drop-down,
1624
- // either relative to today's year (-nn:+nn), relative to currently displayed year
1625
- // (c-nn:c+nn), absolute (nnnn:nnnn), or a combination of the above (nnnn:-n)
1626
- showOtherMonths: false, // True to show dates in other months, false to leave blank
1627
- selectOtherMonths: false, // True to allow selection of dates in other months, false for unselectable
1628
- showWeek: false, // True to show week of the year, false to not show it
1629
- calculateWeek: this.iso8601Week, // How to calculate the week of the year,
1630
- // takes a Date and returns the number of the week for it
1631
- shortYearCutoff: '+10', // Short year values < this are in the current century,
1632
- // > this are in the previous century,
1633
- // string value starting with '+' for current year + value
1634
- minDate: null, // The earliest selectable date, or null for no limit
1635
- maxDate: null, // The latest selectable date, or null for no limit
1636
- duration: 'fast', // Duration of display/closure
1637
- beforeShowDay: null, // Function that takes a date and returns an array with
1638
- // [0] = true if selectable, false if not, [1] = custom CSS class name(s) or '',
1639
- // [2] = cell title (optional), e.g. $.datepicker.noWeekends
1640
- beforeShow: null, // Function that takes an input field and
1641
- // returns a set of custom settings for the date picker
1642
- onSelect: null, // Define a callback function when a date is selected
1643
- onChangeMonthYear: null, // Define a callback function when the month or year is changed
1644
- onClose: null, // Define a callback function when the datepicker is closed
1645
- numberOfMonths: 1, // Number of months to show at a time
1646
- showCurrentAtPos: 0, // The position in multipe months at which to show the current month (starting at 0)
1647
- stepMonths: 1, // Number of months to step back/forward
1648
- stepBigMonths: 12, // Number of months to step back/forward for the big links
1649
- altField: '', // Selector for an alternate field to store selected dates into
1650
- altFormat: '', // The date format to use for the alternate field
1651
- constrainInput: true, // The input is constrained by the current date format
1652
- showButtonPanel: false, // True to show button panel, false to not show it
1653
- autoSize: false, // True to size the input for the date format, false to leave as is
1654
- disabled: false // The initial disabled state
1655
- };
1656
- $.extend(this._defaults, this.regional['']);
1657
- this.dpDiv = bindHover($('<div id="' + this._mainDivId + '" class="ui-datepicker ui-widget ui-widget-content ui-helper-clearfix ui-corner-all"></div>'));
1658
- }
1659
-
1660
- $.extend(Datepicker.prototype, {
1661
- /* Class name added to elements to indicate already configured with a date picker. */
1662
- markerClassName: 'hasDatepicker',
1663
-
1664
- //Keep track of the maximum number of rows displayed (see #7043)
1665
- maxRows: 4,
1666
-
1667
- /* Debug logging (if enabled). */
1668
- log: function () {
1669
- if (this.debug)
1670
- console.log.apply('', arguments);
1671
- },
1672
-
1673
- // TODO rename to "widget" when switching to widget factory
1674
- _widgetDatepicker: function() {
1675
- return this.dpDiv;
1676
- },
1677
-
1678
- /* Override the default settings for all instances of the date picker.
1679
- @param settings object - the new settings to use as defaults (anonymous object)
1680
- @return the manager object */
1681
- setDefaults: function(settings) {
1682
- extendRemove(this._defaults, settings || {});
1683
- return this;
1684
- },
1685
-
1686
- /* Attach the date picker to a jQuery selection.
1687
- @param target element - the target input field or division or span
1688
- @param settings object - the new settings to use for this date picker instance (anonymous) */
1689
- _attachDatepicker: function(target, settings) {
1690
- // check for settings on the control itself - in namespace 'date:'
1691
- var inlineSettings = null;
1692
- for (var attrName in this._defaults) {
1693
- var attrValue = target.getAttribute('date:' + attrName);
1694
- if (attrValue) {
1695
- inlineSettings = inlineSettings || {};
1696
- try {
1697
- inlineSettings[attrName] = eval(attrValue);
1698
- } catch (err) {
1699
- inlineSettings[attrName] = attrValue;
1700
- }
1701
- }
1702
- }
1703
- var nodeName = target.nodeName.toLowerCase();
1704
- var inline = (nodeName == 'div' || nodeName == 'span');
1705
- if (!target.id) {
1706
- this.uuid += 1;
1707
- target.id = 'dp' + this.uuid;
1708
- }
1709
- var inst = this._newInst($(target), inline);
1710
- inst.settings = $.extend({}, settings || {}, inlineSettings || {});
1711
- if (nodeName == 'input') {
1712
- this._connectDatepicker(target, inst);
1713
- } else if (inline) {
1714
- this._inlineDatepicker(target, inst);
1715
- }
1716
- },
1717
-
1718
- /* Create a new instance object. */
1719
- _newInst: function(target, inline) {
1720
- var id = target[0].id.replace(/([^A-Za-z0-9_-])/g, '\\\\$1'); // escape jQuery meta chars
1721
- return {id: id, input: target, // associated target
1722
- selectedDay: 0, selectedMonth: 0, selectedYear: 0, // current selection
1723
- drawMonth: 0, drawYear: 0, // month being drawn
1724
- inline: inline, // is datepicker inline or not
1725
- dpDiv: (!inline ? this.dpDiv : // presentation div
1726
- bindHover($('<div class="' + this._inlineClass + ' ui-datepicker ui-widget ui-widget-content ui-helper-clearfix ui-corner-all"></div>')))};
1727
- },
1728
-
1729
- /* Attach the date picker to an input field. */
1730
- _connectDatepicker: function(target, inst) {
1731
- var input = $(target);
1732
- inst.append = $([]);
1733
- inst.trigger = $([]);
1734
- if (input.hasClass(this.markerClassName))
1735
- return;
1736
- this._attachments(input, inst);
1737
- input.addClass(this.markerClassName).keydown(this._doKeyDown).
1738
- keypress(this._doKeyPress).keyup(this._doKeyUp).
1739
- bind("setData.datepicker", function(event, key, value) {
1740
- inst.settings[key] = value;
1741
- }).bind("getData.datepicker", function(event, key) {
1742
- return this._get(inst, key);
1743
- });
1744
- this._autoSize(inst);
1745
- $.data(target, PROP_NAME, inst);
1746
- //If disabled option is true, disable the datepicker once it has been attached to the input (see ticket #5665)
1747
- if( inst.settings.disabled ) {
1748
- this._disableDatepicker( target );
1749
- }
1750
- },
1751
-
1752
- /* Make attachments based on settings. */
1753
- _attachments: function(input, inst) {
1754
- var appendText = this._get(inst, 'appendText');
1755
- var isRTL = this._get(inst, 'isRTL');
1756
- if (inst.append)
1757
- inst.append.remove();
1758
- if (appendText) {
1759
- inst.append = $('<span class="' + this._appendClass + '">' + appendText + '</span>');
1760
- input[isRTL ? 'before' : 'after'](inst.append);
1761
- }
1762
- input.unbind('focus', this._showDatepicker);
1763
- if (inst.trigger)
1764
- inst.trigger.remove();
1765
- var showOn = this._get(inst, 'showOn');
1766
- if (showOn == 'focus' || showOn == 'both') // pop-up date picker when in the marked field
1767
- input.focus(this._showDatepicker);
1768
- if (showOn == 'button' || showOn == 'both') { // pop-up date picker when button clicked
1769
- var buttonText = this._get(inst, 'buttonText');
1770
- var buttonImage = this._get(inst, 'buttonImage');
1771
- inst.trigger = $(this._get(inst, 'buttonImageOnly') ?
1772
- $('<img/>').addClass(this._triggerClass).
1773
- attr({ src: buttonImage, alt: buttonText, title: buttonText }) :
1774
- $('<button type="button"></button>').addClass(this._triggerClass).
1775
- html(buttonImage == '' ? buttonText : $('<img/>').attr(
1776
- { src:buttonImage, alt:buttonText, title:buttonText })));
1777
- input[isRTL ? 'before' : 'after'](inst.trigger);
1778
- inst.trigger.click(function() {
1779
- if ($.datepicker._datepickerShowing && $.datepicker._lastInput == input[0])
1780
- $.datepicker._hideDatepicker();
1781
- else if ($.datepicker._datepickerShowing && $.datepicker._lastInput != input[0]) {
1782
- $.datepicker._hideDatepicker();
1783
- $.datepicker._showDatepicker(input[0]);
1784
- } else
1785
- $.datepicker._showDatepicker(input[0]);
1786
- return false;
1787
- });
1788
- }
1789
- },
1790
-
1791
- /* Apply the maximum length for the date format. */
1792
- _autoSize: function(inst) {
1793
- if (this._get(inst, 'autoSize') && !inst.inline) {
1794
- var date = new Date(2009, 12 - 1, 20); // Ensure double digits
1795
- var dateFormat = this._get(inst, 'dateFormat');
1796
- if (dateFormat.match(/[DM]/)) {
1797
- var findMax = function(names) {
1798
- var max = 0;
1799
- var maxI = 0;
1800
- for (var i = 0; i < names.length; i++) {
1801
- if (names[i].length > max) {
1802
- max = names[i].length;
1803
- maxI = i;
1804
- }
1805
- }
1806
- return maxI;
1807
- };
1808
- date.setMonth(findMax(this._get(inst, (dateFormat.match(/MM/) ?
1809
- 'monthNames' : 'monthNamesShort'))));
1810
- date.setDate(findMax(this._get(inst, (dateFormat.match(/DD/) ?
1811
- 'dayNames' : 'dayNamesShort'))) + 20 - date.getDay());
1812
- }
1813
- inst.input.attr('size', this._formatDate(inst, date).length);
1814
- }
1815
- },
1816
-
1817
- /* Attach an inline date picker to a div. */
1818
- _inlineDatepicker: function(target, inst) {
1819
- var divSpan = $(target);
1820
- if (divSpan.hasClass(this.markerClassName))
1821
- return;
1822
- divSpan.addClass(this.markerClassName).append(inst.dpDiv).
1823
- bind("setData.datepicker", function(event, key, value){
1824
- inst.settings[key] = value;
1825
- }).bind("getData.datepicker", function(event, key){
1826
- return this._get(inst, key);
1827
- });
1828
- $.data(target, PROP_NAME, inst);
1829
- this._setDate(inst, this._getDefaultDate(inst), true);
1830
- this._updateDatepicker(inst);
1831
- this._updateAlternate(inst);
1832
- //If disabled option is true, disable the datepicker before showing it (see ticket #5665)
1833
- if( inst.settings.disabled ) {
1834
- this._disableDatepicker( target );
1835
- }
1836
- // Set display:block in place of inst.dpDiv.show() which won't work on disconnected elements
1837
- // http://bugs.jqueryui.com/ticket/7552 - A Datepicker created on a detached div has zero height
1838
- inst.dpDiv.css( "display", "block" );
1839
- },
1840
-
1841
- /* Pop-up the date picker in a "dialog" box.
1842
- @param input element - ignored
1843
- @param date string or Date - the initial date to display
1844
- @param onSelect function - the function to call when a date is selected
1845
- @param settings object - update the dialog date picker instance's settings (anonymous object)
1846
- @param pos int[2] - coordinates for the dialog's position within the screen or
1847
- event - with x/y coordinates or
1848
- leave empty for default (screen centre)
1849
- @return the manager object */
1850
- _dialogDatepicker: function(input, date, onSelect, settings, pos) {
1851
- var inst = this._dialogInst; // internal instance
1852
- if (!inst) {
1853
- this.uuid += 1;
1854
- var id = 'dp' + this.uuid;
1855
- this._dialogInput = $('<input type="text" id="' + id +
1856
- '" style="position: absolute; top: -100px; width: 0px;"/>');
1857
- this._dialogInput.keydown(this._doKeyDown);
1858
- $('body').append(this._dialogInput);
1859
- inst = this._dialogInst = this._newInst(this._dialogInput, false);
1860
- inst.settings = {};
1861
- $.data(this._dialogInput[0], PROP_NAME, inst);
1862
- }
1863
- extendRemove(inst.settings, settings || {});
1864
- date = (date && date.constructor == Date ? this._formatDate(inst, date) : date);
1865
- this._dialogInput.val(date);
1866
-
1867
- this._pos = (pos ? (pos.length ? pos : [pos.pageX, pos.pageY]) : null);
1868
- if (!this._pos) {
1869
- var browserWidth = document.documentElement.clientWidth;
1870
- var browserHeight = document.documentElement.clientHeight;
1871
- var scrollX = document.documentElement.scrollLeft || document.body.scrollLeft;
1872
- var scrollY = document.documentElement.scrollTop || document.body.scrollTop;
1873
- this._pos = // should use actual width/height below
1874
- [(browserWidth / 2) - 100 + scrollX, (browserHeight / 2) - 150 + scrollY];
1875
- }
1876
-
1877
- // move input on screen for focus, but hidden behind dialog
1878
- this._dialogInput.css('left', (this._pos[0] + 20) + 'px').css('top', this._pos[1] + 'px');
1879
- inst.settings.onSelect = onSelect;
1880
- this._inDialog = true;
1881
- this.dpDiv.addClass(this._dialogClass);
1882
- this._showDatepicker(this._dialogInput[0]);
1883
- if ($.blockUI)
1884
- $.blockUI(this.dpDiv);
1885
- $.data(this._dialogInput[0], PROP_NAME, inst);
1886
- return this;
1887
- },
1888
-
1889
- /* Detach a datepicker from its control.
1890
- @param target element - the target input field or division or span */
1891
- _destroyDatepicker: function(target) {
1892
- var $target = $(target);
1893
- var inst = $.data(target, PROP_NAME);
1894
- if (!$target.hasClass(this.markerClassName)) {
1895
- return;
1896
- }
1897
- var nodeName = target.nodeName.toLowerCase();
1898
- $.removeData(target, PROP_NAME);
1899
- if (nodeName == 'input') {
1900
- inst.append.remove();
1901
- inst.trigger.remove();
1902
- $target.removeClass(this.markerClassName).
1903
- unbind('focus', this._showDatepicker).
1904
- unbind('keydown', this._doKeyDown).
1905
- unbind('keypress', this._doKeyPress).
1906
- unbind('keyup', this._doKeyUp);
1907
- } else if (nodeName == 'div' || nodeName == 'span')
1908
- $target.removeClass(this.markerClassName).empty();
1909
- },
1910
-
1911
- /* Enable the date picker to a jQuery selection.
1912
- @param target element - the target input field or division or span */
1913
- _enableDatepicker: function(target) {
1914
- var $target = $(target);
1915
- var inst = $.data(target, PROP_NAME);
1916
- if (!$target.hasClass(this.markerClassName)) {
1917
- return;
1918
- }
1919
- var nodeName = target.nodeName.toLowerCase();
1920
- if (nodeName == 'input') {
1921
- target.disabled = false;
1922
- inst.trigger.filter('button').
1923
- each(function() { this.disabled = false; }).end().
1924
- filter('img').css({opacity: '1.0', cursor: ''});
1925
- }
1926
- else if (nodeName == 'div' || nodeName == 'span') {
1927
- var inline = $target.children('.' + this._inlineClass);
1928
- inline.children().removeClass('ui-state-disabled');
1929
- inline.find("select.ui-datepicker-month, select.ui-datepicker-year").
1930
- removeAttr("disabled");
1931
- }
1932
- this._disabledInputs = $.map(this._disabledInputs,
1933
- function(value) { return (value == target ? null : value); }); // delete entry
1934
- },
1935
-
1936
- /* Disable the date picker to a jQuery selection.
1937
- @param target element - the target input field or division or span */
1938
- _disableDatepicker: function(target) {
1939
- var $target = $(target);
1940
- var inst = $.data(target, PROP_NAME);
1941
- if (!$target.hasClass(this.markerClassName)) {
1942
- return;
1943
- }
1944
- var nodeName = target.nodeName.toLowerCase();
1945
- if (nodeName == 'input') {
1946
- target.disabled = true;
1947
- inst.trigger.filter('button').
1948
- each(function() { this.disabled = true; }).end().
1949
- filter('img').css({opacity: '0.5', cursor: 'default'});
1950
- }
1951
- else if (nodeName == 'div' || nodeName == 'span') {
1952
- var inline = $target.children('.' + this._inlineClass);
1953
- inline.children().addClass('ui-state-disabled');
1954
- inline.find("select.ui-datepicker-month, select.ui-datepicker-year").
1955
- attr("disabled", "disabled");
1956
- }
1957
- this._disabledInputs = $.map(this._disabledInputs,
1958
- function(value) { return (value == target ? null : value); }); // delete entry
1959
- this._disabledInputs[this._disabledInputs.length] = target;
1960
- },
1961
-
1962
- /* Is the first field in a jQuery collection disabled as a datepicker?
1963
- @param target element - the target input field or division or span
1964
- @return boolean - true if disabled, false if enabled */
1965
- _isDisabledDatepicker: function(target) {
1966
- if (!target) {
1967
- return false;
1968
- }
1969
- for (var i = 0; i < this._disabledInputs.length; i++) {
1970
- if (this._disabledInputs[i] == target)
1971
- return true;
1972
- }
1973
- return false;
1974
- },
1975
-
1976
- /* Retrieve the instance data for the target control.
1977
- @param target element - the target input field or division or span
1978
- @return object - the associated instance data
1979
- @throws error if a jQuery problem getting data */
1980
- _getInst: function(target) {
1981
- try {
1982
- return $.data(target, PROP_NAME);
1983
- }
1984
- catch (err) {
1985
- throw 'Missing instance data for this datepicker';
1986
- }
1987
- },
1988
-
1989
- /* Update or retrieve the settings for a date picker attached to an input field or division.
1990
- @param target element - the target input field or division or span
1991
- @param name object - the new settings to update or
1992
- string - the name of the setting to change or retrieve,
1993
- when retrieving also 'all' for all instance settings or
1994
- 'defaults' for all global defaults
1995
- @param value any - the new value for the setting
1996
- (omit if above is an object or to retrieve a value) */
1997
- _optionDatepicker: function(target, name, value) {
1998
- var inst = this._getInst(target);
1999
- if (arguments.length == 2 && typeof name == 'string') {
2000
- return (name == 'defaults' ? $.extend({}, $.datepicker._defaults) :
2001
- (inst ? (name == 'all' ? $.extend({}, inst.settings) :
2002
- this._get(inst, name)) : null));
2003
- }
2004
- var settings = name || {};
2005
- if (typeof name == 'string') {
2006
- settings = {};
2007
- settings[name] = value;
2008
- }
2009
- if (inst) {
2010
- if (this._curInst == inst) {
2011
- this._hideDatepicker();
2012
- }
2013
- var date = this._getDateDatepicker(target, true);
2014
- var minDate = this._getMinMaxDate(inst, 'min');
2015
- var maxDate = this._getMinMaxDate(inst, 'max');
2016
- extendRemove(inst.settings, settings);
2017
- // reformat the old minDate/maxDate values if dateFormat changes and a new minDate/maxDate isn't provided
2018
- if (minDate !== null && settings['dateFormat'] !== undefined && settings['minDate'] === undefined)
2019
- inst.settings.minDate = this._formatDate(inst, minDate);
2020
- if (maxDate !== null && settings['dateFormat'] !== undefined && settings['maxDate'] === undefined)
2021
- inst.settings.maxDate = this._formatDate(inst, maxDate);
2022
- this._attachments($(target), inst);
2023
- this._autoSize(inst);
2024
- this._setDate(inst, date);
2025
- this._updateAlternate(inst);
2026
- this._updateDatepicker(inst);
2027
- }
2028
- },
2029
-
2030
- // change method deprecated
2031
- _changeDatepicker: function(target, name, value) {
2032
- this._optionDatepicker(target, name, value);
2033
- },
2034
-
2035
- /* Redraw the date picker attached to an input field or division.
2036
- @param target element - the target input field or division or span */
2037
- _refreshDatepicker: function(target) {
2038
- var inst = this._getInst(target);
2039
- if (inst) {
2040
- this._updateDatepicker(inst);
2041
- }
2042
- },
2043
-
2044
- /* Set the dates for a jQuery selection.
2045
- @param target element - the target input field or division or span
2046
- @param date Date - the new date */
2047
- _setDateDatepicker: function(target, date) {
2048
- var inst = this._getInst(target);
2049
- if (inst) {
2050
- this._setDate(inst, date);
2051
- this._updateDatepicker(inst);
2052
- this._updateAlternate(inst);
2053
- }
2054
- },
2055
-
2056
- /* Get the date(s) for the first entry in a jQuery selection.
2057
- @param target element - the target input field or division or span
2058
- @param noDefault boolean - true if no default date is to be used
2059
- @return Date - the current date */
2060
- _getDateDatepicker: function(target, noDefault) {
2061
- var inst = this._getInst(target);
2062
- if (inst && !inst.inline)
2063
- this._setDateFromField(inst, noDefault);
2064
- return (inst ? this._getDate(inst) : null);
2065
- },
2066
-
2067
- /* Handle keystrokes. */
2068
- _doKeyDown: function(event) {
2069
- var inst = $.datepicker._getInst(event.target);
2070
- var handled = true;
2071
- var isRTL = inst.dpDiv.is('.ui-datepicker-rtl');
2072
- inst._keyEvent = true;
2073
- if ($.datepicker._datepickerShowing)
2074
- switch (event.keyCode) {
2075
- case 9: $.datepicker._hideDatepicker();
2076
- handled = false;
2077
- break; // hide on tab out
2078
- case 13: var sel = $('td.' + $.datepicker._dayOverClass + ':not(.' +
2079
- $.datepicker._currentClass + ')', inst.dpDiv);
2080
- if (sel[0])
2081
- $.datepicker._selectDay(event.target, inst.selectedMonth, inst.selectedYear, sel[0]);
2082
- var onSelect = $.datepicker._get(inst, 'onSelect');
2083
- if (onSelect) {
2084
- var dateStr = $.datepicker._formatDate(inst);
2085
-
2086
- // trigger custom callback
2087
- onSelect.apply((inst.input ? inst.input[0] : null), [dateStr, inst]);
2088
- }
2089
- else
2090
- $.datepicker._hideDatepicker();
2091
- return false; // don't submit the form
2092
- break; // select the value on enter
2093
- case 27: $.datepicker._hideDatepicker();
2094
- break; // hide on escape
2095
- case 33: $.datepicker._adjustDate(event.target, (event.ctrlKey ?
2096
- -$.datepicker._get(inst, 'stepBigMonths') :
2097
- -$.datepicker._get(inst, 'stepMonths')), 'M');
2098
- break; // previous month/year on page up/+ ctrl
2099
- case 34: $.datepicker._adjustDate(event.target, (event.ctrlKey ?
2100
- +$.datepicker._get(inst, 'stepBigMonths') :
2101
- +$.datepicker._get(inst, 'stepMonths')), 'M');
2102
- break; // next month/year on page down/+ ctrl
2103
- case 35: if (event.ctrlKey || event.metaKey) $.datepicker._clearDate(event.target);
2104
- handled = event.ctrlKey || event.metaKey;
2105
- break; // clear on ctrl or command +end
2106
- case 36: if (event.ctrlKey || event.metaKey) $.datepicker._gotoToday(event.target);
2107
- handled = event.ctrlKey || event.metaKey;
2108
- break; // current on ctrl or command +home
2109
- case 37: if (event.ctrlKey || event.metaKey) $.datepicker._adjustDate(event.target, (isRTL ? +1 : -1), 'D');
2110
- handled = event.ctrlKey || event.metaKey;
2111
- // -1 day on ctrl or command +left
2112
- if (event.originalEvent.altKey) $.datepicker._adjustDate(event.target, (event.ctrlKey ?
2113
- -$.datepicker._get(inst, 'stepBigMonths') :
2114
- -$.datepicker._get(inst, 'stepMonths')), 'M');
2115
- // next month/year on alt +left on Mac
2116
- break;
2117
- case 38: if (event.ctrlKey || event.metaKey) $.datepicker._adjustDate(event.target, -7, 'D');
2118
- handled = event.ctrlKey || event.metaKey;
2119
- break; // -1 week on ctrl or command +up
2120
- case 39: if (event.ctrlKey || event.metaKey) $.datepicker._adjustDate(event.target, (isRTL ? -1 : +1), 'D');
2121
- handled = event.ctrlKey || event.metaKey;
2122
- // +1 day on ctrl or command +right
2123
- if (event.originalEvent.altKey) $.datepicker._adjustDate(event.target, (event.ctrlKey ?
2124
- +$.datepicker._get(inst, 'stepBigMonths') :
2125
- +$.datepicker._get(inst, 'stepMonths')), 'M');
2126
- // next month/year on alt +right
2127
- break;
2128
- case 40: if (event.ctrlKey || event.metaKey) $.datepicker._adjustDate(event.target, +7, 'D');
2129
- handled = event.ctrlKey || event.metaKey;
2130
- break; // +1 week on ctrl or command +down
2131
- default: handled = false;
2132
- }
2133
- else if (event.keyCode == 36 && event.ctrlKey) // display the date picker on ctrl+home
2134
- $.datepicker._showDatepicker(this);
2135
- else {
2136
- handled = false;
2137
- }
2138
- if (handled) {
2139
- event.preventDefault();
2140
- event.stopPropagation();
2141
- }
2142
- },
2143
-
2144
- /* Filter entered characters - based on date format. */
2145
- _doKeyPress: function(event) {
2146
- var inst = $.datepicker._getInst(event.target);
2147
- if ($.datepicker._get(inst, 'constrainInput')) {
2148
- var chars = $.datepicker._possibleChars($.datepicker._get(inst, 'dateFormat'));
2149
- var chr = String.fromCharCode(event.charCode == undefined ? event.keyCode : event.charCode);
2150
- return event.ctrlKey || event.metaKey || (chr < ' ' || !chars || chars.indexOf(chr) > -1);
2151
- }
2152
- },
2153
-
2154
- /* Synchronise manual entry and field/alternate field. */
2155
- _doKeyUp: function(event) {
2156
- var inst = $.datepicker._getInst(event.target);
2157
- if (inst.input.val() != inst.lastVal) {
2158
- try {
2159
- var date = $.datepicker.parseDate($.datepicker._get(inst, 'dateFormat'),
2160
- (inst.input ? inst.input.val() : null),
2161
- $.datepicker._getFormatConfig(inst));
2162
- if (date) { // only if valid
2163
- $.datepicker._setDateFromField(inst);
2164
- $.datepicker._updateAlternate(inst);
2165
- $.datepicker._updateDatepicker(inst);
2166
- }
2167
- }
2168
- catch (err) {
2169
- $.datepicker.log(err);
2170
- }
2171
- }
2172
- return true;
2173
- },
2174
-
2175
- /* Pop-up the date picker for a given input field.
2176
- If false returned from beforeShow event handler do not show.
2177
- @param input element - the input field attached to the date picker or
2178
- event - if triggered by focus */
2179
- _showDatepicker: function(input) {
2180
- input = input.target || input;
2181
- if (input.nodeName.toLowerCase() != 'input') // find from button/image trigger
2182
- input = $('input', input.parentNode)[0];
2183
- if ($.datepicker._isDisabledDatepicker(input) || $.datepicker._lastInput == input) // already here
2184
- return;
2185
- var inst = $.datepicker._getInst(input);
2186
- if ($.datepicker._curInst && $.datepicker._curInst != inst) {
2187
- $.datepicker._curInst.dpDiv.stop(true, true);
2188
- if ( inst && $.datepicker._datepickerShowing ) {
2189
- $.datepicker._hideDatepicker( $.datepicker._curInst.input[0] );
2190
- }
2191
- }
2192
- var beforeShow = $.datepicker._get(inst, 'beforeShow');
2193
- var beforeShowSettings = beforeShow ? beforeShow.apply(input, [input, inst]) : {};
2194
- if(beforeShowSettings === false){
2195
- //false
2196
- return;
2197
- }
2198
- extendRemove(inst.settings, beforeShowSettings);
2199
- inst.lastVal = null;
2200
- $.datepicker._lastInput = input;
2201
- $.datepicker._setDateFromField(inst);
2202
- if ($.datepicker._inDialog) // hide cursor
2203
- input.value = '';
2204
- if (!$.datepicker._pos) { // position below input
2205
- $.datepicker._pos = $.datepicker._findPos(input);
2206
- $.datepicker._pos[1] += input.offsetHeight; // add the height
2207
- }
2208
- var isFixed = false;
2209
- $(input).parents().each(function() {
2210
- isFixed |= $(this).css('position') == 'fixed';
2211
- return !isFixed;
2212
- });
2213
- if (isFixed && $.browser.opera) { // correction for Opera when fixed and scrolled
2214
- $.datepicker._pos[0] -= document.documentElement.scrollLeft;
2215
- $.datepicker._pos[1] -= document.documentElement.scrollTop;
2216
- }
2217
- var offset = {left: $.datepicker._pos[0], top: $.datepicker._pos[1]};
2218
- $.datepicker._pos = null;
2219
- //to avoid flashes on Firefox
2220
- inst.dpDiv.empty();
2221
- // determine sizing offscreen
2222
- inst.dpDiv.css({position: 'absolute', display: 'block', top: '-1000px'});
2223
- $.datepicker._updateDatepicker(inst);
2224
- // fix width for dynamic number of date pickers
2225
- // and adjust position before showing
2226
- offset = $.datepicker._checkOffset(inst, offset, isFixed);
2227
- inst.dpDiv.css({position: ($.datepicker._inDialog && $.blockUI ?
2228
- 'static' : (isFixed ? 'fixed' : 'absolute')), display: 'none',
2229
- left: offset.left + 'px', top: offset.top + 'px'});
2230
- if (!inst.inline) {
2231
- var showAnim = $.datepicker._get(inst, 'showAnim');
2232
- var duration = $.datepicker._get(inst, 'duration');
2233
- var postProcess = function() {
2234
- var cover = inst.dpDiv.find('iframe.ui-datepicker-cover'); // IE6- only
2235
- if( !! cover.length ){
2236
- var borders = $.datepicker._getBorders(inst.dpDiv);
2237
- cover.css({left: -borders[0], top: -borders[1],
2238
- width: inst.dpDiv.outerWidth(), height: inst.dpDiv.outerHeight()});
2239
- }
2240
- };
2241
- inst.dpDiv.zIndex($(input).zIndex()+1);
2242
- $.datepicker._datepickerShowing = true;
2243
- if ($.effects && $.effects[showAnim])
2244
- inst.dpDiv.show(showAnim, $.datepicker._get(inst, 'showOptions'), duration, postProcess);
2245
- else
2246
- inst.dpDiv[showAnim || 'show']((showAnim ? duration : null), postProcess);
2247
- if (!showAnim || !duration)
2248
- postProcess();
2249
- if (inst.input.is(':visible') && !inst.input.is(':disabled'))
2250
- inst.input.focus();
2251
- $.datepicker._curInst = inst;
2252
- }
2253
- },
2254
-
2255
- /* Generate the date picker content. */
2256
- _updateDatepicker: function(inst) {
2257
- var self = this;
2258
- self.maxRows = 4; //Reset the max number of rows being displayed (see #7043)
2259
- var borders = $.datepicker._getBorders(inst.dpDiv);
2260
- instActive = inst; // for delegate hover events
2261
- inst.dpDiv.empty().append(this._generateHTML(inst));
2262
- this._attachHandlers(inst);
2263
- var cover = inst.dpDiv.find('iframe.ui-datepicker-cover'); // IE6- only
2264
- if( !!cover.length ){ //avoid call to outerXXXX() when not in IE6
2265
- cover.css({left: -borders[0], top: -borders[1], width: inst.dpDiv.outerWidth(), height: inst.dpDiv.outerHeight()})
2266
- }
2267
- inst.dpDiv.find('.' + this._dayOverClass + ' a').mouseover();
2268
- var numMonths = this._getNumberOfMonths(inst);
2269
- var cols = numMonths[1];
2270
- var width = 17;
2271
- inst.dpDiv.removeClass('ui-datepicker-multi-2 ui-datepicker-multi-3 ui-datepicker-multi-4').width('');
2272
- if (cols > 1)
2273
- inst.dpDiv.addClass('ui-datepicker-multi-' + cols).css('width', (width * cols) + 'em');
2274
- inst.dpDiv[(numMonths[0] != 1 || numMonths[1] != 1 ? 'add' : 'remove') +
2275
- 'Class']('ui-datepicker-multi');
2276
- inst.dpDiv[(this._get(inst, 'isRTL') ? 'add' : 'remove') +
2277
- 'Class']('ui-datepicker-rtl');
2278
- if (inst == $.datepicker._curInst && $.datepicker._datepickerShowing && inst.input &&
2279
- // #6694 - don't focus the input if it's already focused
2280
- // this breaks the change event in IE
2281
- inst.input.is(':visible') && !inst.input.is(':disabled') && inst.input[0] != document.activeElement)
2282
- inst.input.focus();
2283
- // deffered render of the years select (to avoid flashes on Firefox)
2284
- if( inst.yearshtml ){
2285
- var origyearshtml = inst.yearshtml;
2286
- setTimeout(function(){
2287
- //assure that inst.yearshtml didn't change.
2288
- if( origyearshtml === inst.yearshtml && inst.yearshtml ){
2289
- inst.dpDiv.find('select.ui-datepicker-year:first').replaceWith(inst.yearshtml);
2290
- }
2291
- origyearshtml = inst.yearshtml = null;
2292
- }, 0);
2293
- }
2294
- },
2295
-
2296
- /* Retrieve the size of left and top borders for an element.
2297
- @param elem (jQuery object) the element of interest
2298
- @return (number[2]) the left and top borders */
2299
- _getBorders: function(elem) {
2300
- var convert = function(value) {
2301
- return {thin: 1, medium: 2, thick: 3}[value] || value;
2302
- };
2303
- return [parseFloat(convert(elem.css('border-left-width'))),
2304
- parseFloat(convert(elem.css('border-top-width')))];
2305
- },
2306
-
2307
- /* Check positioning to remain on screen. */
2308
- _checkOffset: function(inst, offset, isFixed) {
2309
- var dpWidth = inst.dpDiv.outerWidth();
2310
- var dpHeight = inst.dpDiv.outerHeight();
2311
- var inputWidth = inst.input ? inst.input.outerWidth() : 0;
2312
- var inputHeight = inst.input ? inst.input.outerHeight() : 0;
2313
- var viewWidth = document.documentElement.clientWidth + (isFixed ? 0 : $(document).scrollLeft());
2314
- var viewHeight = document.documentElement.clientHeight + (isFixed ? 0 : $(document).scrollTop());
2315
-
2316
- offset.left -= (this._get(inst, 'isRTL') ? (dpWidth - inputWidth) : 0);
2317
- offset.left -= (isFixed && offset.left == inst.input.offset().left) ? $(document).scrollLeft() : 0;
2318
- offset.top -= (isFixed && offset.top == (inst.input.offset().top + inputHeight)) ? $(document).scrollTop() : 0;
2319
-
2320
- // now check if datepicker is showing outside window viewport - move to a better place if so.
2321
- offset.left -= Math.min(offset.left, (offset.left + dpWidth > viewWidth && viewWidth > dpWidth) ?
2322
- Math.abs(offset.left + dpWidth - viewWidth) : 0);
2323
- offset.top -= Math.min(offset.top, (offset.top + dpHeight > viewHeight && viewHeight > dpHeight) ?
2324
- Math.abs(dpHeight + inputHeight) : 0);
2325
-
2326
- return offset;
2327
- },
2328
-
2329
- /* Find an object's position on the screen. */
2330
- _findPos: function(obj) {
2331
- var inst = this._getInst(obj);
2332
- var isRTL = this._get(inst, 'isRTL');
2333
- while (obj && (obj.type == 'hidden' || obj.nodeType != 1 || $.expr.filters.hidden(obj))) {
2334
- obj = obj[isRTL ? 'previousSibling' : 'nextSibling'];
2335
- }
2336
- var position = $(obj).offset();
2337
- return [position.left, position.top];
2338
- },
2339
-
2340
- /* Hide the date picker from view.
2341
- @param input element - the input field attached to the date picker */
2342
- _hideDatepicker: function(input) {
2343
- var inst = this._curInst;
2344
- if (!inst || (input && inst != $.data(input, PROP_NAME)))
2345
- return;
2346
- if (this._datepickerShowing) {
2347
- var showAnim = this._get(inst, 'showAnim');
2348
- var duration = this._get(inst, 'duration');
2349
- var postProcess = function() {
2350
- $.datepicker._tidyDialog(inst);
2351
- };
2352
- if ($.effects && $.effects[showAnim])
2353
- inst.dpDiv.hide(showAnim, $.datepicker._get(inst, 'showOptions'), duration, postProcess);
2354
- else
2355
- inst.dpDiv[(showAnim == 'slideDown' ? 'slideUp' :
2356
- (showAnim == 'fadeIn' ? 'fadeOut' : 'hide'))]((showAnim ? duration : null), postProcess);
2357
- if (!showAnim)
2358
- postProcess();
2359
- this._datepickerShowing = false;
2360
- var onClose = this._get(inst, 'onClose');
2361
- if (onClose)
2362
- onClose.apply((inst.input ? inst.input[0] : null),
2363
- [(inst.input ? inst.input.val() : ''), inst]);
2364
- this._lastInput = null;
2365
- if (this._inDialog) {
2366
- this._dialogInput.css({ position: 'absolute', left: '0', top: '-100px' });
2367
- if ($.blockUI) {
2368
- $.unblockUI();
2369
- $('body').append(this.dpDiv);
2370
- }
2371
- }
2372
- this._inDialog = false;
2373
- }
2374
- },
2375
-
2376
- /* Tidy up after a dialog display. */
2377
- _tidyDialog: function(inst) {
2378
- inst.dpDiv.removeClass(this._dialogClass).unbind('.ui-datepicker-calendar');
2379
- },
2380
-
2381
- /* Close date picker if clicked elsewhere. */
2382
- _checkExternalClick: function(event) {
2383
- if (!$.datepicker._curInst)
2384
- return;
2385
-
2386
- var $target = $(event.target),
2387
- inst = $.datepicker._getInst($target[0]);
2388
-
2389
- if ( ( ( $target[0].id != $.datepicker._mainDivId &&
2390
- $target.parents('#' + $.datepicker._mainDivId).length == 0 &&
2391
- !$target.hasClass($.datepicker.markerClassName) &&
2392
- !$target.closest("." + $.datepicker._triggerClass).length &&
2393
- $.datepicker._datepickerShowing && !($.datepicker._inDialog && $.blockUI) ) ) ||
2394
- ( $target.hasClass($.datepicker.markerClassName) && $.datepicker._curInst != inst ) )
2395
- $.datepicker._hideDatepicker();
2396
- },
2397
-
2398
- /* Adjust one of the date sub-fields. */
2399
- _adjustDate: function(id, offset, period) {
2400
- var target = $(id);
2401
- var inst = this._getInst(target[0]);
2402
- if (this._isDisabledDatepicker(target[0])) {
2403
- return;
2404
- }
2405
- this._adjustInstDate(inst, offset +
2406
- (period == 'M' ? this._get(inst, 'showCurrentAtPos') : 0), // undo positioning
2407
- period);
2408
- this._updateDatepicker(inst);
2409
- },
2410
-
2411
- /* Action for current link. */
2412
- _gotoToday: function(id) {
2413
- var target = $(id);
2414
- var inst = this._getInst(target[0]);
2415
- if (this._get(inst, 'gotoCurrent') && inst.currentDay) {
2416
- inst.selectedDay = inst.currentDay;
2417
- inst.drawMonth = inst.selectedMonth = inst.currentMonth;
2418
- inst.drawYear = inst.selectedYear = inst.currentYear;
2419
- }
2420
- else {
2421
- var date = new Date();
2422
- inst.selectedDay = date.getDate();
2423
- inst.drawMonth = inst.selectedMonth = date.getMonth();
2424
- inst.drawYear = inst.selectedYear = date.getFullYear();
2425
- }
2426
- this._notifyChange(inst);
2427
- this._adjustDate(target);
2428
- },
2429
-
2430
- /* Action for selecting a new month/year. */
2431
- _selectMonthYear: function(id, select, period) {
2432
- var target = $(id);
2433
- var inst = this._getInst(target[0]);
2434
- inst['selected' + (period == 'M' ? 'Month' : 'Year')] =
2435
- inst['draw' + (period == 'M' ? 'Month' : 'Year')] =
2436
- parseInt(select.options[select.selectedIndex].value,10);
2437
- this._notifyChange(inst);
2438
- this._adjustDate(target);
2439
- },
2440
-
2441
- /* Action for selecting a day. */
2442
- _selectDay: function(id, month, year, td) {
2443
- var target = $(id);
2444
- if ($(td).hasClass(this._unselectableClass) || this._isDisabledDatepicker(target[0])) {
2445
- return;
2446
- }
2447
- var inst = this._getInst(target[0]);
2448
- inst.selectedDay = inst.currentDay = $('a', td).html();
2449
- inst.selectedMonth = inst.currentMonth = month;
2450
- inst.selectedYear = inst.currentYear = year;
2451
- this._selectDate(id, this._formatDate(inst,
2452
- inst.currentDay, inst.currentMonth, inst.currentYear));
2453
- },
2454
-
2455
- /* Erase the input field and hide the date picker. */
2456
- _clearDate: function(id) {
2457
- var target = $(id);
2458
- var inst = this._getInst(target[0]);
2459
- this._selectDate(target, '');
2460
- },
2461
-
2462
- /* Update the input field with the selected date. */
2463
- _selectDate: function(id, dateStr) {
2464
- var target = $(id);
2465
- var inst = this._getInst(target[0]);
2466
- dateStr = (dateStr != null ? dateStr : this._formatDate(inst));
2467
- if (inst.input)
2468
- inst.input.val(dateStr);
2469
- this._updateAlternate(inst);
2470
- var onSelect = this._get(inst, 'onSelect');
2471
- if (onSelect)
2472
- onSelect.apply((inst.input ? inst.input[0] : null), [dateStr, inst]); // trigger custom callback
2473
- else if (inst.input)
2474
- inst.input.trigger('change'); // fire the change event
2475
- if (inst.inline)
2476
- this._updateDatepicker(inst);
2477
- else {
2478
- this._hideDatepicker();
2479
- this._lastInput = inst.input[0];
2480
- if (typeof(inst.input[0]) != 'object')
2481
- inst.input.focus(); // restore focus
2482
- this._lastInput = null;
2483
- }
2484
- },
2485
-
2486
- /* Update any alternate field to synchronise with the main field. */
2487
- _updateAlternate: function(inst) {
2488
- var altField = this._get(inst, 'altField');
2489
- if (altField) { // update alternate field too
2490
- var altFormat = this._get(inst, 'altFormat') || this._get(inst, 'dateFormat');
2491
- var date = this._getDate(inst);
2492
- var dateStr = this.formatDate(altFormat, date, this._getFormatConfig(inst));
2493
- $(altField).each(function() { $(this).val(dateStr); });
2494
- }
2495
- },
2496
-
2497
- /* Set as beforeShowDay function to prevent selection of weekends.
2498
- @param date Date - the date to customise
2499
- @return [boolean, string] - is this date selectable?, what is its CSS class? */
2500
- noWeekends: function(date) {
2501
- var day = date.getDay();
2502
- return [(day > 0 && day < 6), ''];
2503
- },
2504
-
2505
- /* Set as calculateWeek to determine the week of the year based on the ISO 8601 definition.
2506
- @param date Date - the date to get the week for
2507
- @return number - the number of the week within the year that contains this date */
2508
- iso8601Week: function(date) {
2509
- var checkDate = new Date(date.getTime());
2510
- // Find Thursday of this week starting on Monday
2511
- checkDate.setDate(checkDate.getDate() + 4 - (checkDate.getDay() || 7));
2512
- var time = checkDate.getTime();
2513
- checkDate.setMonth(0); // Compare with Jan 1
2514
- checkDate.setDate(1);
2515
- return Math.floor(Math.round((time - checkDate) / 86400000) / 7) + 1;
2516
- },
2517
-
2518
- /* Parse a string value into a date object.
2519
- See formatDate below for the possible formats.
2520
-
2521
- @param format string - the expected format of the date
2522
- @param value string - the date in the above format
2523
- @param settings Object - attributes include:
2524
- shortYearCutoff number - the cutoff year for determining the century (optional)
2525
- dayNamesShort string[7] - abbreviated names of the days from Sunday (optional)
2526
- dayNames string[7] - names of the days from Sunday (optional)
2527
- monthNamesShort string[12] - abbreviated names of the months (optional)
2528
- monthNames string[12] - names of the months (optional)
2529
- @return Date - the extracted date value or null if value is blank */
2530
- parseDate: function (format, value, settings) {
2531
- if (format == null || value == null)
2532
- throw 'Invalid arguments';
2533
- value = (typeof value == 'object' ? value.toString() : value + '');
2534
- if (value == '')
2535
- return null;
2536
- var shortYearCutoff = (settings ? settings.shortYearCutoff : null) || this._defaults.shortYearCutoff;
2537
- shortYearCutoff = (typeof shortYearCutoff != 'string' ? shortYearCutoff :
2538
- new Date().getFullYear() % 100 + parseInt(shortYearCutoff, 10));
2539
- var dayNamesShort = (settings ? settings.dayNamesShort : null) || this._defaults.dayNamesShort;
2540
- var dayNames = (settings ? settings.dayNames : null) || this._defaults.dayNames;
2541
- var monthNamesShort = (settings ? settings.monthNamesShort : null) || this._defaults.monthNamesShort;
2542
- var monthNames = (settings ? settings.monthNames : null) || this._defaults.monthNames;
2543
- var year = -1;
2544
- var month = -1;
2545
- var day = -1;
2546
- var doy = -1;
2547
- var literal = false;
2548
- // Check whether a format character is doubled
2549
- var lookAhead = function(match) {
2550
- var matches = (iFormat + 1 < format.length && format.charAt(iFormat + 1) == match);
2551
- if (matches)
2552
- iFormat++;
2553
- return matches;
2554
- };
2555
- // Extract a number from the string value
2556
- var getNumber = function(match) {
2557
- var isDoubled = lookAhead(match);
2558
- var size = (match == '@' ? 14 : (match == '!' ? 20 :
2559
- (match == 'y' && isDoubled ? 4 : (match == 'o' ? 3 : 2))));
2560
- var digits = new RegExp('^\\d{1,' + size + '}');
2561
- var num = value.substring(iValue).match(digits);
2562
- if (!num)
2563
- throw 'Missing number at position ' + iValue;
2564
- iValue += num[0].length;
2565
- return parseInt(num[0], 10);
2566
- };
2567
- // Extract a name from the string value and convert to an index
2568
- var getName = function(match, shortNames, longNames) {
2569
- var names = $.map(lookAhead(match) ? longNames : shortNames, function (v, k) {
2570
- return [ [k, v] ];
2571
- }).sort(function (a, b) {
2572
- return -(a[1].length - b[1].length);
2573
- });
2574
- var index = -1;
2575
- $.each(names, function (i, pair) {
2576
- var name = pair[1];
2577
- if (value.substr(iValue, name.length).toLowerCase() == name.toLowerCase()) {
2578
- index = pair[0];
2579
- iValue += name.length;
2580
- return false;
2581
- }
2582
- });
2583
- if (index != -1)
2584
- return index + 1;
2585
- else
2586
- throw 'Unknown name at position ' + iValue;
2587
- };
2588
- // Confirm that a literal character matches the string value
2589
- var checkLiteral = function() {
2590
- if (value.charAt(iValue) != format.charAt(iFormat))
2591
- throw 'Unexpected literal at position ' + iValue;
2592
- iValue++;
2593
- };
2594
- var iValue = 0;
2595
- for (var iFormat = 0; iFormat < format.length; iFormat++) {
2596
- if (literal)
2597
- if (format.charAt(iFormat) == "'" && !lookAhead("'"))
2598
- literal = false;
2599
- else
2600
- checkLiteral();
2601
- else
2602
- switch (format.charAt(iFormat)) {
2603
- case 'd':
2604
- day = getNumber('d');
2605
- break;
2606
- case 'D':
2607
- getName('D', dayNamesShort, dayNames);
2608
- break;
2609
- case 'o':
2610
- doy = getNumber('o');
2611
- break;
2612
- case 'm':
2613
- month = getNumber('m');
2614
- break;
2615
- case 'M':
2616
- month = getName('M', monthNamesShort, monthNames);
2617
- break;
2618
- case 'y':
2619
- year = getNumber('y');
2620
- break;
2621
- case '@':
2622
- var date = new Date(getNumber('@'));
2623
- year = date.getFullYear();
2624
- month = date.getMonth() + 1;
2625
- day = date.getDate();
2626
- break;
2627
- case '!':
2628
- var date = new Date((getNumber('!') - this._ticksTo1970) / 10000);
2629
- year = date.getFullYear();
2630
- month = date.getMonth() + 1;
2631
- day = date.getDate();
2632
- break;
2633
- case "'":
2634
- if (lookAhead("'"))
2635
- checkLiteral();
2636
- else
2637
- literal = true;
2638
- break;
2639
- default:
2640
- checkLiteral();
2641
- }
2642
- }
2643
- if (iValue < value.length){
2644
- throw "Extra/unparsed characters found in date: " + value.substring(iValue);
2645
- }
2646
- if (year == -1)
2647
- year = new Date().getFullYear();
2648
- else if (year < 100)
2649
- year += new Date().getFullYear() - new Date().getFullYear() % 100 +
2650
- (year <= shortYearCutoff ? 0 : -100);
2651
- if (doy > -1) {
2652
- month = 1;
2653
- day = doy;
2654
- do {
2655
- var dim = this._getDaysInMonth(year, month - 1);
2656
- if (day <= dim)
2657
- break;
2658
- month++;
2659
- day -= dim;
2660
- } while (true);
2661
- }
2662
- var date = this._daylightSavingAdjust(new Date(year, month - 1, day));
2663
- if (date.getFullYear() != year || date.getMonth() + 1 != month || date.getDate() != day)
2664
- throw 'Invalid date'; // E.g. 31/02/00
2665
- return date;
2666
- },
2667
-
2668
- /* Standard date formats. */
2669
- ATOM: 'yy-mm-dd', // RFC 3339 (ISO 8601)
2670
- COOKIE: 'D, dd M yy',
2671
- ISO_8601: 'yy-mm-dd',
2672
- RFC_822: 'D, d M y',
2673
- RFC_850: 'DD, dd-M-y',
2674
- RFC_1036: 'D, d M y',
2675
- RFC_1123: 'D, d M yy',
2676
- RFC_2822: 'D, d M yy',
2677
- RSS: 'D, d M y', // RFC 822
2678
- TICKS: '!',
2679
- TIMESTAMP: '@',
2680
- W3C: 'yy-mm-dd', // ISO 8601
2681
-
2682
- _ticksTo1970: (((1970 - 1) * 365 + Math.floor(1970 / 4) - Math.floor(1970 / 100) +
2683
- Math.floor(1970 / 400)) * 24 * 60 * 60 * 10000000),
2684
-
2685
- /* Format a date object into a string value.
2686
- The format can be combinations of the following:
2687
- d - day of month (no leading zero)
2688
- dd - day of month (two digit)
2689
- o - day of year (no leading zeros)
2690
- oo - day of year (three digit)
2691
- D - day name short
2692
- DD - day name long
2693
- m - month of year (no leading zero)
2694
- mm - month of year (two digit)
2695
- M - month name short
2696
- MM - month name long
2697
- y - year (two digit)
2698
- yy - year (four digit)
2699
- @ - Unix timestamp (ms since 01/01/1970)
2700
- ! - Windows ticks (100ns since 01/01/0001)
2701
- '...' - literal text
2702
- '' - single quote
2703
-
2704
- @param format string - the desired format of the date
2705
- @param date Date - the date value to format
2706
- @param settings Object - attributes include:
2707
- dayNamesShort string[7] - abbreviated names of the days from Sunday (optional)
2708
- dayNames string[7] - names of the days from Sunday (optional)
2709
- monthNamesShort string[12] - abbreviated names of the months (optional)
2710
- monthNames string[12] - names of the months (optional)
2711
- @return string - the date in the above format */
2712
- formatDate: function (format, date, settings) {
2713
- if (!date)
2714
- return '';
2715
- var dayNamesShort = (settings ? settings.dayNamesShort : null) || this._defaults.dayNamesShort;
2716
- var dayNames = (settings ? settings.dayNames : null) || this._defaults.dayNames;
2717
- var monthNamesShort = (settings ? settings.monthNamesShort : null) || this._defaults.monthNamesShort;
2718
- var monthNames = (settings ? settings.monthNames : null) || this._defaults.monthNames;
2719
- // Check whether a format character is doubled
2720
- var lookAhead = function(match) {
2721
- var matches = (iFormat + 1 < format.length && format.charAt(iFormat + 1) == match);
2722
- if (matches)
2723
- iFormat++;
2724
- return matches;
2725
- };
2726
- // Format a number, with leading zero if necessary
2727
- var formatNumber = function(match, value, len) {
2728
- var num = '' + value;
2729
- if (lookAhead(match))
2730
- while (num.length < len)
2731
- num = '0' + num;
2732
- return num;
2733
- };
2734
- // Format a name, short or long as requested
2735
- var formatName = function(match, value, shortNames, longNames) {
2736
- return (lookAhead(match) ? longNames[value] : shortNames[value]);
2737
- };
2738
- var output = '';
2739
- var literal = false;
2740
- if (date)
2741
- for (var iFormat = 0; iFormat < format.length; iFormat++) {
2742
- if (literal)
2743
- if (format.charAt(iFormat) == "'" && !lookAhead("'"))
2744
- literal = false;
2745
- else
2746
- output += format.charAt(iFormat);
2747
- else
2748
- switch (format.charAt(iFormat)) {
2749
- case 'd':
2750
- output += formatNumber('d', date.getDate(), 2);
2751
- break;
2752
- case 'D':
2753
- output += formatName('D', date.getDay(), dayNamesShort, dayNames);
2754
- break;
2755
- case 'o':
2756
- output += formatNumber('o',
2757
- Math.round((new Date(date.getFullYear(), date.getMonth(), date.getDate()).getTime() - new Date(date.getFullYear(), 0, 0).getTime()) / 86400000), 3);
2758
- break;
2759
- case 'm':
2760
- output += formatNumber('m', date.getMonth() + 1, 2);
2761
- break;
2762
- case 'M':
2763
- output += formatName('M', date.getMonth(), monthNamesShort, monthNames);
2764
- break;
2765
- case 'y':
2766
- output += (lookAhead('y') ? date.getFullYear() :
2767
- (date.getYear() % 100 < 10 ? '0' : '') + date.getYear() % 100);
2768
- break;
2769
- case '@':
2770
- output += date.getTime();
2771
- break;
2772
- case '!':
2773
- output += date.getTime() * 10000 + this._ticksTo1970;
2774
- break;
2775
- case "'":
2776
- if (lookAhead("'"))
2777
- output += "'";
2778
- else
2779
- literal = true;
2780
- break;
2781
- default:
2782
- output += format.charAt(iFormat);
2783
- }
2784
- }
2785
- return output;
2786
- },
2787
-
2788
- /* Extract all possible characters from the date format. */
2789
- _possibleChars: function (format) {
2790
- var chars = '';
2791
- var literal = false;
2792
- // Check whether a format character is doubled
2793
- var lookAhead = function(match) {
2794
- var matches = (iFormat + 1 < format.length && format.charAt(iFormat + 1) == match);
2795
- if (matches)
2796
- iFormat++;
2797
- return matches;
2798
- };
2799
- for (var iFormat = 0; iFormat < format.length; iFormat++)
2800
- if (literal)
2801
- if (format.charAt(iFormat) == "'" && !lookAhead("'"))
2802
- literal = false;
2803
- else
2804
- chars += format.charAt(iFormat);
2805
- else
2806
- switch (format.charAt(iFormat)) {
2807
- case 'd': case 'm': case 'y': case '@':
2808
- chars += '0123456789';
2809
- break;
2810
- case 'D': case 'M':
2811
- return null; // Accept anything
2812
- case "'":
2813
- if (lookAhead("'"))
2814
- chars += "'";
2815
- else
2816
- literal = true;
2817
- break;
2818
- default:
2819
- chars += format.charAt(iFormat);
2820
- }
2821
- return chars;
2822
- },
2823
-
2824
- /* Get a setting value, defaulting if necessary. */
2825
- _get: function(inst, name) {
2826
- return inst.settings[name] !== undefined ?
2827
- inst.settings[name] : this._defaults[name];
2828
- },
2829
-
2830
- /* Parse existing date and initialise date picker. */
2831
- _setDateFromField: function(inst, noDefault) {
2832
- if (inst.input.val() == inst.lastVal) {
2833
- return;
2834
- }
2835
- var dateFormat = this._get(inst, 'dateFormat');
2836
- var dates = inst.lastVal = inst.input ? inst.input.val() : null;
2837
- var date, defaultDate;
2838
- date = defaultDate = this._getDefaultDate(inst);
2839
- var settings = this._getFormatConfig(inst);
2840
- try {
2841
- date = this.parseDate(dateFormat, dates, settings) || defaultDate;
2842
- } catch (event) {
2843
- this.log(event);
2844
- dates = (noDefault ? '' : dates);
2845
- }
2846
- inst.selectedDay = date.getDate();
2847
- inst.drawMonth = inst.selectedMonth = date.getMonth();
2848
- inst.drawYear = inst.selectedYear = date.getFullYear();
2849
- inst.currentDay = (dates ? date.getDate() : 0);
2850
- inst.currentMonth = (dates ? date.getMonth() : 0);
2851
- inst.currentYear = (dates ? date.getFullYear() : 0);
2852
- this._adjustInstDate(inst);
2853
- },
2854
-
2855
- /* Retrieve the default date shown on opening. */
2856
- _getDefaultDate: function(inst) {
2857
- return this._restrictMinMax(inst,
2858
- this._determineDate(inst, this._get(inst, 'defaultDate'), new Date()));
2859
- },
2860
-
2861
- /* A date may be specified as an exact value or a relative one. */
2862
- _determineDate: function(inst, date, defaultDate) {
2863
- var offsetNumeric = function(offset) {
2864
- var date = new Date();
2865
- date.setDate(date.getDate() + offset);
2866
- return date;
2867
- };
2868
- var offsetString = function(offset) {
2869
- try {
2870
- return $.datepicker.parseDate($.datepicker._get(inst, 'dateFormat'),
2871
- offset, $.datepicker._getFormatConfig(inst));
2872
- }
2873
- catch (e) {
2874
- // Ignore
2875
- }
2876
- var date = (offset.toLowerCase().match(/^c/) ?
2877
- $.datepicker._getDate(inst) : null) || new Date();
2878
- var year = date.getFullYear();
2879
- var month = date.getMonth();
2880
- var day = date.getDate();
2881
- var pattern = /([+-]?[0-9]+)\s*(d|D|w|W|m|M|y|Y)?/g;
2882
- var matches = pattern.exec(offset);
2883
- while (matches) {
2884
- switch (matches[2] || 'd') {
2885
- case 'd' : case 'D' :
2886
- day += parseInt(matches[1],10); break;
2887
- case 'w' : case 'W' :
2888
- day += parseInt(matches[1],10) * 7; break;
2889
- case 'm' : case 'M' :
2890
- month += parseInt(matches[1],10);
2891
- day = Math.min(day, $.datepicker._getDaysInMonth(year, month));
2892
- break;
2893
- case 'y': case 'Y' :
2894
- year += parseInt(matches[1],10);
2895
- day = Math.min(day, $.datepicker._getDaysInMonth(year, month));
2896
- break;
2897
- }
2898
- matches = pattern.exec(offset);
2899
- }
2900
- return new Date(year, month, day);
2901
- };
2902
- var newDate = (date == null || date === '' ? defaultDate : (typeof date == 'string' ? offsetString(date) :
2903
- (typeof date == 'number' ? (isNaN(date) ? defaultDate : offsetNumeric(date)) : new Date(date.getTime()))));
2904
- newDate = (newDate && newDate.toString() == 'Invalid Date' ? defaultDate : newDate);
2905
- if (newDate) {
2906
- newDate.setHours(0);
2907
- newDate.setMinutes(0);
2908
- newDate.setSeconds(0);
2909
- newDate.setMilliseconds(0);
2910
- }
2911
- return this._daylightSavingAdjust(newDate);
2912
- },
2913
-
2914
- /* Handle switch to/from daylight saving.
2915
- Hours may be non-zero on daylight saving cut-over:
2916
- > 12 when midnight changeover, but then cannot generate
2917
- midnight datetime, so jump to 1AM, otherwise reset.
2918
- @param date (Date) the date to check
2919
- @return (Date) the corrected date */
2920
- _daylightSavingAdjust: function(date) {
2921
- if (!date) return null;
2922
- date.setHours(date.getHours() > 12 ? date.getHours() + 2 : 0);
2923
- return date;
2924
- },
2925
-
2926
- /* Set the date(s) directly. */
2927
- _setDate: function(inst, date, noChange) {
2928
- var clear = !date;
2929
- var origMonth = inst.selectedMonth;
2930
- var origYear = inst.selectedYear;
2931
- var newDate = this._restrictMinMax(inst, this._determineDate(inst, date, new Date()));
2932
- inst.selectedDay = inst.currentDay = newDate.getDate();
2933
- inst.drawMonth = inst.selectedMonth = inst.currentMonth = newDate.getMonth();
2934
- inst.drawYear = inst.selectedYear = inst.currentYear = newDate.getFullYear();
2935
- if ((origMonth != inst.selectedMonth || origYear != inst.selectedYear) && !noChange)
2936
- this._notifyChange(inst);
2937
- this._adjustInstDate(inst);
2938
- if (inst.input) {
2939
- inst.input.val(clear ? '' : this._formatDate(inst));
2940
- }
2941
- },
2942
-
2943
- /* Retrieve the date(s) directly. */
2944
- _getDate: function(inst) {
2945
- var startDate = (!inst.currentYear || (inst.input && inst.input.val() == '') ? null :
2946
- this._daylightSavingAdjust(new Date(
2947
- inst.currentYear, inst.currentMonth, inst.currentDay)));
2948
- return startDate;
2949
- },
2950
-
2951
- /* Attach the onxxx handlers. These are declared statically so
2952
- * they work with static code transformers like Caja.
2953
- */
2954
- _attachHandlers: function(inst) {
2955
- var stepMonths = this._get(inst, 'stepMonths');
2956
- var id = '#' + inst.id.replace( /\\\\/g, "\\" );
2957
- inst.dpDiv.find('[data-handler]').map(function () {
2958
- var handler = {
2959
- prev: function () {
2960
- window['DP_jQuery_' + dpuuid].datepicker._adjustDate(id, -stepMonths, 'M');
2961
- },
2962
- next: function () {
2963
- window['DP_jQuery_' + dpuuid].datepicker._adjustDate(id, +stepMonths, 'M');
2964
- },
2965
- hide: function () {
2966
- window['DP_jQuery_' + dpuuid].datepicker._hideDatepicker();
2967
- },
2968
- today: function () {
2969
- window['DP_jQuery_' + dpuuid].datepicker._gotoToday(id);
2970
- },
2971
- selectDay: function () {
2972
- window['DP_jQuery_' + dpuuid].datepicker._selectDay(id, +this.getAttribute('data-month'), +this.getAttribute('data-year'), this);
2973
- return false;
2974
- },
2975
- selectMonth: function () {
2976
- window['DP_jQuery_' + dpuuid].datepicker._selectMonthYear(id, this, 'M');
2977
- return false;
2978
- },
2979
- selectYear: function () {
2980
- window['DP_jQuery_' + dpuuid].datepicker._selectMonthYear(id, this, 'Y');
2981
- return false;
2982
- }
2983
- };
2984
- $(this).bind(this.getAttribute('data-event'), handler[this.getAttribute('data-handler')]);
2985
- });
2986
- },
2987
-
2988
- /* Generate the HTML for the current state of the date picker. */
2989
- _generateHTML: function(inst) {
2990
- var today = new Date();
2991
- today = this._daylightSavingAdjust(
2992
- new Date(today.getFullYear(), today.getMonth(), today.getDate())); // clear time
2993
- var isRTL = this._get(inst, 'isRTL');
2994
- var showButtonPanel = this._get(inst, 'showButtonPanel');
2995
- var hideIfNoPrevNext = this._get(inst, 'hideIfNoPrevNext');
2996
- var navigationAsDateFormat = this._get(inst, 'navigationAsDateFormat');
2997
- var numMonths = this._getNumberOfMonths(inst);
2998
- var showCurrentAtPos = this._get(inst, 'showCurrentAtPos');
2999
- var stepMonths = this._get(inst, 'stepMonths');
3000
- var isMultiMonth = (numMonths[0] != 1 || numMonths[1] != 1);
3001
- var currentDate = this._daylightSavingAdjust((!inst.currentDay ? new Date(9999, 9, 9) :
3002
- new Date(inst.currentYear, inst.currentMonth, inst.currentDay)));
3003
- var minDate = this._getMinMaxDate(inst, 'min');
3004
- var maxDate = this._getMinMaxDate(inst, 'max');
3005
- var drawMonth = inst.drawMonth - showCurrentAtPos;
3006
- var drawYear = inst.drawYear;
3007
- if (drawMonth < 0) {
3008
- drawMonth += 12;
3009
- drawYear--;
3010
- }
3011
- if (maxDate) {
3012
- var maxDraw = this._daylightSavingAdjust(new Date(maxDate.getFullYear(),
3013
- maxDate.getMonth() - (numMonths[0] * numMonths[1]) + 1, maxDate.getDate()));
3014
- maxDraw = (minDate && maxDraw < minDate ? minDate : maxDraw);
3015
- while (this._daylightSavingAdjust(new Date(drawYear, drawMonth, 1)) > maxDraw) {
3016
- drawMonth--;
3017
- if (drawMonth < 0) {
3018
- drawMonth = 11;
3019
- drawYear--;
3020
- }
3021
- }
3022
- }
3023
- inst.drawMonth = drawMonth;
3024
- inst.drawYear = drawYear;
3025
- var prevText = this._get(inst, 'prevText');
3026
- prevText = (!navigationAsDateFormat ? prevText : this.formatDate(prevText,
3027
- this._daylightSavingAdjust(new Date(drawYear, drawMonth - stepMonths, 1)),
3028
- this._getFormatConfig(inst)));
3029
- var prev = (this._canAdjustMonth(inst, -1, drawYear, drawMonth) ?
3030
- '<a class="ui-datepicker-prev ui-corner-all" data-handler="prev" data-event="click"' +
3031
- ' title="' + prevText + '"><span class="ui-icon ui-icon-circle-triangle-' + ( isRTL ? 'e' : 'w') + '">' + prevText + '</span></a>' :
3032
- (hideIfNoPrevNext ? '' : '<a class="ui-datepicker-prev ui-corner-all ui-state-disabled" title="'+ prevText +'"><span class="ui-icon ui-icon-circle-triangle-' + ( isRTL ? 'e' : 'w') + '">' + prevText + '</span></a>'));
3033
- var nextText = this._get(inst, 'nextText');
3034
- nextText = (!navigationAsDateFormat ? nextText : this.formatDate(nextText,
3035
- this._daylightSavingAdjust(new Date(drawYear, drawMonth + stepMonths, 1)),
3036
- this._getFormatConfig(inst)));
3037
- var next = (this._canAdjustMonth(inst, +1, drawYear, drawMonth) ?
3038
- '<a class="ui-datepicker-next ui-corner-all" data-handler="next" data-event="click"' +
3039
- ' title="' + nextText + '"><span class="ui-icon ui-icon-circle-triangle-' + ( isRTL ? 'w' : 'e') + '">' + nextText + '</span></a>' :
3040
- (hideIfNoPrevNext ? '' : '<a class="ui-datepicker-next ui-corner-all ui-state-disabled" title="'+ nextText + '"><span class="ui-icon ui-icon-circle-triangle-' + ( isRTL ? 'w' : 'e') + '">' + nextText + '</span></a>'));
3041
- var currentText = this._get(inst, 'currentText');
3042
- var gotoDate = (this._get(inst, 'gotoCurrent') && inst.currentDay ? currentDate : today);
3043
- currentText = (!navigationAsDateFormat ? currentText :
3044
- this.formatDate(currentText, gotoDate, this._getFormatConfig(inst)));
3045
- var controls = (!inst.inline ? '<button type="button" class="ui-datepicker-close ui-state-default ui-priority-primary ui-corner-all" data-handler="hide" data-event="click">' +
3046
- this._get(inst, 'closeText') + '</button>' : '');
3047
- var buttonPanel = (showButtonPanel) ? '<div class="ui-datepicker-buttonpane ui-widget-content">' + (isRTL ? controls : '') +
3048
- (this._isInRange(inst, gotoDate) ? '<button type="button" class="ui-datepicker-current ui-state-default ui-priority-secondary ui-corner-all" data-handler="today" data-event="click"' +
3049
- '>' + currentText + '</button>' : '') + (isRTL ? '' : controls) + '</div>' : '';
3050
- var firstDay = parseInt(this._get(inst, 'firstDay'),10);
3051
- firstDay = (isNaN(firstDay) ? 0 : firstDay);
3052
- var showWeek = this._get(inst, 'showWeek');
3053
- var dayNames = this._get(inst, 'dayNames');
3054
- var dayNamesShort = this._get(inst, 'dayNamesShort');
3055
- var dayNamesMin = this._get(inst, 'dayNamesMin');
3056
- var monthNames = this._get(inst, 'monthNames');
3057
- var monthNamesShort = this._get(inst, 'monthNamesShort');
3058
- var beforeShowDay = this._get(inst, 'beforeShowDay');
3059
- var showOtherMonths = this._get(inst, 'showOtherMonths');
3060
- var selectOtherMonths = this._get(inst, 'selectOtherMonths');
3061
- var calculateWeek = this._get(inst, 'calculateWeek') || this.iso8601Week;
3062
- var defaultDate = this._getDefaultDate(inst);
3063
- var html = '';
3064
- for (var row = 0; row < numMonths[0]; row++) {
3065
- var group = '';
3066
- this.maxRows = 4;
3067
- for (var col = 0; col < numMonths[1]; col++) {
3068
- var selectedDate = this._daylightSavingAdjust(new Date(drawYear, drawMonth, inst.selectedDay));
3069
- var cornerClass = ' ui-corner-all';
3070
- var calender = '';
3071
- if (isMultiMonth) {
3072
- calender += '<div class="ui-datepicker-group';
3073
- if (numMonths[1] > 1)
3074
- switch (col) {
3075
- case 0: calender += ' ui-datepicker-group-first';
3076
- cornerClass = ' ui-corner-' + (isRTL ? 'right' : 'left'); break;
3077
- case numMonths[1]-1: calender += ' ui-datepicker-group-last';
3078
- cornerClass = ' ui-corner-' + (isRTL ? 'left' : 'right'); break;
3079
- default: calender += ' ui-datepicker-group-middle'; cornerClass = ''; break;
3080
- }
3081
- calender += '">';
3082
- }
3083
- calender += '<div class="ui-datepicker-header ui-widget-header ui-helper-clearfix' + cornerClass + '">' +
3084
- (/all|left/.test(cornerClass) && row == 0 ? (isRTL ? next : prev) : '') +
3085
- (/all|right/.test(cornerClass) && row == 0 ? (isRTL ? prev : next) : '') +
3086
- this._generateMonthYearHeader(inst, drawMonth, drawYear, minDate, maxDate,
3087
- row > 0 || col > 0, monthNames, monthNamesShort) + // draw month headers
3088
- '</div><table class="ui-datepicker-calendar"><thead>' +
3089
- '<tr>';
3090
- var thead = (showWeek ? '<th class="ui-datepicker-week-col">' + this._get(inst, 'weekHeader') + '</th>' : '');
3091
- for (var dow = 0; dow < 7; dow++) { // days of the week
3092
- var day = (dow + firstDay) % 7;
3093
- thead += '<th' + ((dow + firstDay + 6) % 7 >= 5 ? ' class="ui-datepicker-week-end"' : '') + '>' +
3094
- '<span title="' + dayNames[day] + '">' + dayNamesMin[day] + '</span></th>';
3095
- }
3096
- calender += thead + '</tr></thead><tbody>';
3097
- var daysInMonth = this._getDaysInMonth(drawYear, drawMonth);
3098
- if (drawYear == inst.selectedYear && drawMonth == inst.selectedMonth)
3099
- inst.selectedDay = Math.min(inst.selectedDay, daysInMonth);
3100
- var leadDays = (this._getFirstDayOfMonth(drawYear, drawMonth) - firstDay + 7) % 7;
3101
- var curRows = Math.ceil((leadDays + daysInMonth) / 7); // calculate the number of rows to generate
3102
- var numRows = (isMultiMonth ? this.maxRows > curRows ? this.maxRows : curRows : curRows); //If multiple months, use the higher number of rows (see #7043)
3103
- this.maxRows = numRows;
3104
- var printDate = this._daylightSavingAdjust(new Date(drawYear, drawMonth, 1 - leadDays));
3105
- for (var dRow = 0; dRow < numRows; dRow++) { // create date picker rows
3106
- calender += '<tr>';
3107
- var tbody = (!showWeek ? '' : '<td class="ui-datepicker-week-col">' +
3108
- this._get(inst, 'calculateWeek')(printDate) + '</td>');
3109
- for (var dow = 0; dow < 7; dow++) { // create date picker days
3110
- var daySettings = (beforeShowDay ?
3111
- beforeShowDay.apply((inst.input ? inst.input[0] : null), [printDate]) : [true, '']);
3112
- var otherMonth = (printDate.getMonth() != drawMonth);
3113
- var unselectable = (otherMonth && !selectOtherMonths) || !daySettings[0] ||
3114
- (minDate && printDate < minDate) || (maxDate && printDate > maxDate);
3115
- tbody += '<td class="' +
3116
- ((dow + firstDay + 6) % 7 >= 5 ? ' ui-datepicker-week-end' : '') + // highlight weekends
3117
- (otherMonth ? ' ui-datepicker-other-month' : '') + // highlight days from other months
3118
- ((printDate.getTime() == selectedDate.getTime() && drawMonth == inst.selectedMonth && inst._keyEvent) || // user pressed key
3119
- (defaultDate.getTime() == printDate.getTime() && defaultDate.getTime() == selectedDate.getTime()) ?
3120
- // or defaultDate is current printedDate and defaultDate is selectedDate
3121
- ' ' + this._dayOverClass : '') + // highlight selected day
3122
- (unselectable ? ' ' + this._unselectableClass + ' ui-state-disabled': '') + // highlight unselectable days
3123
- (otherMonth && !showOtherMonths ? '' : ' ' + daySettings[1] + // highlight custom dates
3124
- (printDate.getTime() == currentDate.getTime() ? ' ' + this._currentClass : '') + // highlight selected day
3125
- (printDate.getTime() == today.getTime() ? ' ui-datepicker-today' : '')) + '"' + // highlight today (if different)
3126
- ((!otherMonth || showOtherMonths) && daySettings[2] ? ' title="' + daySettings[2] + '"' : '') + // cell title
3127
- (unselectable ? '' : ' data-handler="selectDay" data-event="click" data-month="' + printDate.getMonth() + '" data-year="' + printDate.getFullYear() + '"') + '>' + // actions
3128
- (otherMonth && !showOtherMonths ? '&#xa0;' : // display for other months
3129
- (unselectable ? '<span class="ui-state-default">' + printDate.getDate() + '</span>' : '<a class="ui-state-default' +
3130
- (printDate.getTime() == today.getTime() ? ' ui-state-highlight' : '') +
3131
- (printDate.getTime() == currentDate.getTime() ? ' ui-state-active' : '') + // highlight selected day
3132
- (otherMonth ? ' ui-priority-secondary' : '') + // distinguish dates from other months
3133
- '" href="#">' + printDate.getDate() + '</a>')) + '</td>'; // display selectable date
3134
- printDate.setDate(printDate.getDate() + 1);
3135
- printDate = this._daylightSavingAdjust(printDate);
3136
- }
3137
- calender += tbody + '</tr>';
3138
- }
3139
- drawMonth++;
3140
- if (drawMonth > 11) {
3141
- drawMonth = 0;
3142
- drawYear++;
3143
- }
3144
- calender += '</tbody></table>' + (isMultiMonth ? '</div>' +
3145
- ((numMonths[0] > 0 && col == numMonths[1]-1) ? '<div class="ui-datepicker-row-break"></div>' : '') : '');
3146
- group += calender;
3147
- }
3148
- html += group;
3149
- }
3150
- html += buttonPanel + ($.browser.msie && parseInt($.browser.version,10) < 7 && !inst.inline ?
3151
- '<iframe src="javascript:false;" class="ui-datepicker-cover" frameborder="0"></iframe>' : '');
3152
- inst._keyEvent = false;
3153
- return html;
3154
- },
3155
-
3156
- /* Generate the month and year header. */
3157
- _generateMonthYearHeader: function(inst, drawMonth, drawYear, minDate, maxDate,
3158
- secondary, monthNames, monthNamesShort) {
3159
- var changeMonth = this._get(inst, 'changeMonth');
3160
- var changeYear = this._get(inst, 'changeYear');
3161
- var showMonthAfterYear = this._get(inst, 'showMonthAfterYear');
3162
- var html = '<div class="ui-datepicker-title">';
3163
- var monthHtml = '';
3164
- // month selection
3165
- if (secondary || !changeMonth)
3166
- monthHtml += '<span class="ui-datepicker-month">' + monthNames[drawMonth] + '</span>';
3167
- else {
3168
- var inMinYear = (minDate && minDate.getFullYear() == drawYear);
3169
- var inMaxYear = (maxDate && maxDate.getFullYear() == drawYear);
3170
- monthHtml += '<select class="ui-datepicker-month" data-handler="selectMonth" data-event="change">';
3171
- for (var month = 0; month < 12; month++) {
3172
- if ((!inMinYear || month >= minDate.getMonth()) &&
3173
- (!inMaxYear || month <= maxDate.getMonth()))
3174
- monthHtml += '<option value="' + month + '"' +
3175
- (month == drawMonth ? ' selected="selected"' : '') +
3176
- '>' + monthNamesShort[month] + '</option>';
3177
- }
3178
- monthHtml += '</select>';
3179
- }
3180
- if (!showMonthAfterYear)
3181
- html += monthHtml + (secondary || !(changeMonth && changeYear) ? '&#xa0;' : '');
3182
- // year selection
3183
- if ( !inst.yearshtml ) {
3184
- inst.yearshtml = '';
3185
- if (secondary || !changeYear)
3186
- html += '<span class="ui-datepicker-year">' + drawYear + '</span>';
3187
- else {
3188
- // determine range of years to display
3189
- var years = this._get(inst, 'yearRange').split(':');
3190
- var thisYear = new Date().getFullYear();
3191
- var determineYear = function(value) {
3192
- var year = (value.match(/c[+-].*/) ? drawYear + parseInt(value.substring(1), 10) :
3193
- (value.match(/[+-].*/) ? thisYear + parseInt(value, 10) :
3194
- parseInt(value, 10)));
3195
- return (isNaN(year) ? thisYear : year);
3196
- };
3197
- var year = determineYear(years[0]);
3198
- var endYear = Math.max(year, determineYear(years[1] || ''));
3199
- year = (minDate ? Math.max(year, minDate.getFullYear()) : year);
3200
- endYear = (maxDate ? Math.min(endYear, maxDate.getFullYear()) : endYear);
3201
- inst.yearshtml += '<select class="ui-datepicker-year" data-handler="selectYear" data-event="change">';
3202
- for (; year <= endYear; year++) {
3203
- inst.yearshtml += '<option value="' + year + '"' +
3204
- (year == drawYear ? ' selected="selected"' : '') +
3205
- '>' + year + '</option>';
3206
- }
3207
- inst.yearshtml += '</select>';
3208
-
3209
- html += inst.yearshtml;
3210
- inst.yearshtml = null;
3211
- }
3212
- }
3213
- html += this._get(inst, 'yearSuffix');
3214
- if (showMonthAfterYear)
3215
- html += (secondary || !(changeMonth && changeYear) ? '&#xa0;' : '') + monthHtml;
3216
- html += '</div>'; // Close datepicker_header
3217
- return html;
3218
- },
3219
-
3220
- /* Adjust one of the date sub-fields. */
3221
- _adjustInstDate: function(inst, offset, period) {
3222
- var year = inst.drawYear + (period == 'Y' ? offset : 0);
3223
- var month = inst.drawMonth + (period == 'M' ? offset : 0);
3224
- var day = Math.min(inst.selectedDay, this._getDaysInMonth(year, month)) +
3225
- (period == 'D' ? offset : 0);
3226
- var date = this._restrictMinMax(inst,
3227
- this._daylightSavingAdjust(new Date(year, month, day)));
3228
- inst.selectedDay = date.getDate();
3229
- inst.drawMonth = inst.selectedMonth = date.getMonth();
3230
- inst.drawYear = inst.selectedYear = date.getFullYear();
3231
- if (period == 'M' || period == 'Y')
3232
- this._notifyChange(inst);
3233
- },
3234
-
3235
- /* Ensure a date is within any min/max bounds. */
3236
- _restrictMinMax: function(inst, date) {
3237
- var minDate = this._getMinMaxDate(inst, 'min');
3238
- var maxDate = this._getMinMaxDate(inst, 'max');
3239
- var newDate = (minDate && date < minDate ? minDate : date);
3240
- newDate = (maxDate && newDate > maxDate ? maxDate : newDate);
3241
- return newDate;
3242
- },
3243
-
3244
- /* Notify change of month/year. */
3245
- _notifyChange: function(inst) {
3246
- var onChange = this._get(inst, 'onChangeMonthYear');
3247
- if (onChange)
3248
- onChange.apply((inst.input ? inst.input[0] : null),
3249
- [inst.selectedYear, inst.selectedMonth + 1, inst]);
3250
- },
3251
-
3252
- /* Determine the number of months to show. */
3253
- _getNumberOfMonths: function(inst) {
3254
- var numMonths = this._get(inst, 'numberOfMonths');
3255
- return (numMonths == null ? [1, 1] : (typeof numMonths == 'number' ? [1, numMonths] : numMonths));
3256
- },
3257
-
3258
- /* Determine the current maximum date - ensure no time components are set. */
3259
- _getMinMaxDate: function(inst, minMax) {
3260
- return this._determineDate(inst, this._get(inst, minMax + 'Date'), null);
3261
- },
3262
-
3263
- /* Find the number of days in a given month. */
3264
- _getDaysInMonth: function(year, month) {
3265
- return 32 - this._daylightSavingAdjust(new Date(year, month, 32)).getDate();
3266
- },
3267
-
3268
- /* Find the day of the week of the first of a month. */
3269
- _getFirstDayOfMonth: function(year, month) {
3270
- return new Date(year, month, 1).getDay();
3271
- },
3272
-
3273
- /* Determines if we should allow a "next/prev" month display change. */
3274
- _canAdjustMonth: function(inst, offset, curYear, curMonth) {
3275
- var numMonths = this._getNumberOfMonths(inst);
3276
- var date = this._daylightSavingAdjust(new Date(curYear,
3277
- curMonth + (offset < 0 ? offset : numMonths[0] * numMonths[1]), 1));
3278
- if (offset < 0)
3279
- date.setDate(this._getDaysInMonth(date.getFullYear(), date.getMonth()));
3280
- return this._isInRange(inst, date);
3281
- },
3282
-
3283
- /* Is the given date in the accepted range? */
3284
- _isInRange: function(inst, date) {
3285
- var minDate = this._getMinMaxDate(inst, 'min');
3286
- var maxDate = this._getMinMaxDate(inst, 'max');
3287
- return ((!minDate || date.getTime() >= minDate.getTime()) &&
3288
- (!maxDate || date.getTime() <= maxDate.getTime()));
3289
- },
3290
-
3291
- /* Provide the configuration settings for formatting/parsing. */
3292
- _getFormatConfig: function(inst) {
3293
- var shortYearCutoff = this._get(inst, 'shortYearCutoff');
3294
- shortYearCutoff = (typeof shortYearCutoff != 'string' ? shortYearCutoff :
3295
- new Date().getFullYear() % 100 + parseInt(shortYearCutoff, 10));
3296
- return {shortYearCutoff: shortYearCutoff,
3297
- dayNamesShort: this._get(inst, 'dayNamesShort'), dayNames: this._get(inst, 'dayNames'),
3298
- monthNamesShort: this._get(inst, 'monthNamesShort'), monthNames: this._get(inst, 'monthNames')};
3299
- },
3300
-
3301
- /* Format the given date for display. */
3302
- _formatDate: function(inst, day, month, year) {
3303
- if (!day) {
3304
- inst.currentDay = inst.selectedDay;
3305
- inst.currentMonth = inst.selectedMonth;
3306
- inst.currentYear = inst.selectedYear;
3307
- }
3308
- var date = (day ? (typeof day == 'object' ? day :
3309
- this._daylightSavingAdjust(new Date(year, month, day))) :
3310
- this._daylightSavingAdjust(new Date(inst.currentYear, inst.currentMonth, inst.currentDay)));
3311
- return this.formatDate(this._get(inst, 'dateFormat'), date, this._getFormatConfig(inst));
3312
- }
3313
- });
3314
-
3315
- /*
3316
- * Bind hover events for datepicker elements.
3317
- * Done via delegate so the binding only occurs once in the lifetime of the parent div.
3318
- * Global instActive, set by _updateDatepicker allows the handlers to find their way back to the active picker.
3319
- */
3320
- function bindHover(dpDiv) {
3321
- var selector = 'button, .ui-datepicker-prev, .ui-datepicker-next, .ui-datepicker-calendar td a';
3322
- return dpDiv.bind('mouseout', function(event) {
3323
- var elem = $( event.target ).closest( selector );
3324
- if ( !elem.length ) {
3325
- return;
3326
- }
3327
- elem.removeClass( "ui-state-hover ui-datepicker-prev-hover ui-datepicker-next-hover" );
3328
- })
3329
- .bind('mouseover', function(event) {
3330
- var elem = $( event.target ).closest( selector );
3331
- if ($.datepicker._isDisabledDatepicker( instActive.inline ? dpDiv.parent()[0] : instActive.input[0]) ||
3332
- !elem.length ) {
3333
- return;
3334
- }
3335
- elem.parents('.ui-datepicker-calendar').find('a').removeClass('ui-state-hover');
3336
- elem.addClass('ui-state-hover');
3337
- if (elem.hasClass('ui-datepicker-prev')) elem.addClass('ui-datepicker-prev-hover');
3338
- if (elem.hasClass('ui-datepicker-next')) elem.addClass('ui-datepicker-next-hover');
3339
- });
3340
- }
3341
-
3342
- /* jQuery extend now ignores nulls! */
3343
- function extendRemove(target, props) {
3344
- $.extend(target, props);
3345
- for (var name in props)
3346
- if (props[name] == null || props[name] == undefined)
3347
- target[name] = props[name];
3348
- return target;
3349
- };
3350
-
3351
- /* Determine whether an object is an array. */
3352
- function isArray(a) {
3353
- return (a && (($.browser.safari && typeof a == 'object' && a.length) ||
3354
- (a.constructor && a.constructor.toString().match(/\Array\(\)/))));
3355
- };
3356
-
3357
- /* Invoke the datepicker functionality.
3358
- @param options string - a command, optionally followed by additional parameters or
3359
- Object - settings for attaching new datepicker functionality
3360
- @return jQuery object */
3361
- $.fn.datepicker = function(options){
3362
-
3363
- /* Verify an empty collection wasn't passed - Fixes #6976 */
3364
- if ( !this.length ) {
3365
- return this;
3366
- }
3367
-
3368
- /* Initialise the date picker. */
3369
- if (!$.datepicker.initialized) {
3370
- $(document).mousedown($.datepicker._checkExternalClick).
3371
- find('body').append($.datepicker.dpDiv);
3372
- $.datepicker.initialized = true;
3373
- }
3374
-
3375
- var otherArgs = Array.prototype.slice.call(arguments, 1);
3376
- if (typeof options == 'string' && (options == 'isDisabled' || options == 'getDate' || options == 'widget'))
3377
- return $.datepicker['_' + options + 'Datepicker'].
3378
- apply($.datepicker, [this[0]].concat(otherArgs));
3379
- if (options == 'option' && arguments.length == 2 && typeof arguments[1] == 'string')
3380
- return $.datepicker['_' + options + 'Datepicker'].
3381
- apply($.datepicker, [this[0]].concat(otherArgs));
3382
- return this.each(function() {
3383
- typeof options == 'string' ?
3384
- $.datepicker['_' + options + 'Datepicker'].
3385
- apply($.datepicker, [this].concat(otherArgs)) :
3386
- $.datepicker._attachDatepicker(this, options);
3387
- });
3388
- };
3389
-
3390
- $.datepicker = new Datepicker(); // singleton instance
3391
- $.datepicker.initialized = false;
3392
- $.datepicker.uuid = new Date().getTime();
3393
- $.datepicker.version = "1.8.23";
3394
-
3395
- // Workaround for #4055
3396
- // Add another global to avoid noConflict issues with inline event handlers
3397
- window['DP_jQuery_' + dpuuid] = $;
3398
-
3399
- })(jQuery);