app_frame 0.5.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (70) hide show
  1. data/.document +5 -0
  2. data/.rspec +1 -0
  3. data/Gemfile +26 -0
  4. data/Gemfile.lock +181 -0
  5. data/LICENSE.txt +20 -0
  6. data/README.md +25 -0
  7. data/Rakefile +47 -0
  8. data/VERSION +1 -0
  9. data/app/assets/javascripts/app_frame/application.js +9 -0
  10. data/app/assets/stylesheets/app_frame/_devise.scss +41 -0
  11. data/app/assets/stylesheets/app_frame/_tree.scss +31 -0
  12. data/app/assets/stylesheets/app_frame/application.scss +73 -0
  13. data/app/controllers/app_frame/devise/confirmations_controller.rb +3 -0
  14. data/app/controllers/app_frame/devise/passwords_controller.rb +3 -0
  15. data/app/controllers/app_frame/devise/registrations_controller.rb +3 -0
  16. data/app/controllers/app_frame/devise/sessions_controller.rb +3 -0
  17. data/app/helpers/app_frame/bootstrap_helper.rb +36 -0
  18. data/app/helpers/app_frame/breadcrumb_helper.rb +18 -0
  19. data/app/helpers/app_frame/menu_helper.rb +43 -0
  20. data/app/helpers/app_frame/pagination_helper.rb +12 -0
  21. data/app/helpers/app_frame/resources_helper.rb +63 -0
  22. data/app/helpers/app_frame/scopes_helper.rb +94 -0
  23. data/app/helpers/app_frame/select_helper.rb +8 -0
  24. data/app/helpers/app_frame/tree_nav_helper.rb +18 -0
  25. data/app/models/menu.rb +44 -0
  26. data/app/models/settings.rb +4 -0
  27. data/app/views/app_frame/devise/confirmations/new.html.haml +8 -0
  28. data/app/views/app_frame/devise/passwords/edit.html.haml +13 -0
  29. data/app/views/app_frame/devise/passwords/new.html.haml +8 -0
  30. data/app/views/app_frame/devise/registrations/edit.html.haml +19 -0
  31. data/app/views/app_frame/devise/registrations/new.html.haml +10 -0
  32. data/app/views/app_frame/devise/sessions/new.html.haml +12 -0
  33. data/app/views/app_frame/devise/shared/_links.html.haml +14 -0
  34. data/app/views/app_frame/devise/unlocks/new.html.haml +9 -0
  35. data/app/views/application/_brand.html.haml +1 -0
  36. data/app/views/application/_breadcrumb.html.haml +12 -0
  37. data/app/views/application/_flashes.html.haml +2 -0
  38. data/app/views/application/_form.html.haml +2 -0
  39. data/app/views/application/_head.html.haml +6 -0
  40. data/app/views/application/_secondary_menu.html.haml +3 -0
  41. data/app/views/application/_show.html.haml +5 -0
  42. data/app/views/application/_sidebar.html.haml +12 -0
  43. data/app/views/application/_sub_menu.html.haml +0 -0
  44. data/app/views/application/_table.html.haml +3 -0
  45. data/app/views/application/_toolbar.html.haml +7 -0
  46. data/app/views/application/_top_menu.html.haml +1 -0
  47. data/app/views/application/edit.html.haml +8 -0
  48. data/app/views/application/index.html.haml +8 -0
  49. data/app/views/application/new.html.haml +7 -0
  50. data/app/views/application/show.html.haml +10 -0
  51. data/app/views/kaminari/app_frame/_first_page.html.haml +9 -0
  52. data/app/views/kaminari/app_frame/_gap.html.haml +8 -0
  53. data/app/views/kaminari/app_frame/_last_page.html.haml +9 -0
  54. data/app/views/kaminari/app_frame/_next_page.html.haml +9 -0
  55. data/app/views/kaminari/app_frame/_page.html.haml +10 -0
  56. data/app/views/kaminari/app_frame/_paginator.html.haml +19 -0
  57. data/app/views/kaminari/app_frame/_prev_page.html.haml +9 -0
  58. data/app/views/layouts/app_frame/default.html.haml +33 -0
  59. data/app/views/layouts/app_frame/devise.html.haml +17 -0
  60. data/app_frame.gemspec +162 -0
  61. data/lib/app_frame.rb +27 -0
  62. data/lib/app_frame/controller_methods.rb +111 -0
  63. data/lib/app_frame/view_methods.rb +19 -0
  64. data/lib/assets/images/.gitkeep +0 -0
  65. data/lib/assets/javascripts/anytime.js +3716 -0
  66. data/lib/assets/stylesheets/anytime.css +777 -0
  67. data/lib/engine.rb +197 -0
  68. data/spec/app_frame_spec.rb +7 -0
  69. data/spec/spec_helper.rb +12 -0
  70. metadata +423 -0
@@ -0,0 +1,111 @@
1
+ module AppFrame
2
+
3
+ module ControllerMethods
4
+ extend ActiveSupport::Concern
5
+
6
+ def controller
7
+ self
8
+ end
9
+
10
+ module ClassMethods
11
+ def app_frame(options = {})
12
+ layout "#{AppFrame::theme}/#{options[:layout] || 'default'}"
13
+ unless options[:resource] == false
14
+ inherit_resources
15
+ include AppFrame::ResourcesHelper
16
+ include PaginationSupport
17
+ include HasManySupport
18
+ include SearchSupport
19
+ end
20
+ end
21
+ end
22
+
23
+ module SearchSupport
24
+ extend ActiveSupport::Concern
25
+
26
+ included do
27
+ helper_method :searchable?
28
+ end
29
+
30
+ def searchable?
31
+ resource_class.respond_to?(:search)
32
+ end
33
+
34
+ def list_scope
35
+ @list_scope ||= (controller_namespaces.map(&:to_s).join("_") + "_list").to_sym
36
+ end
37
+
38
+ def end_of_association_chain
39
+ chain = super
40
+
41
+ return chain if chain.is_a?(ActiveRecord::Base)
42
+
43
+ chain = chain.search(params[:q]) if params[:q].present? && searchable?
44
+
45
+ chain = chain.admin_list if resource_class.respond_to?(list_scope)
46
+
47
+ chain
48
+ end
49
+ end
50
+
51
+ module HasManySupport
52
+ extend ActiveSupport::Concern
53
+
54
+ included do
55
+ helper_method :child_resources
56
+ end
57
+
58
+ module ClassMethods
59
+ def child_resources
60
+ @child_resources ||= []
61
+ end
62
+
63
+ def has_many(symbol, options = {})
64
+ config = {
65
+ :symbol => symbol,
66
+ :name => symbol.to_s.humanize,
67
+ :resource_class => symbol.to_s.classify.constantize,
68
+ :resource_name => symbol.to_s.classify
69
+ }.merge(options)
70
+
71
+ self.child_resources << config
72
+ end
73
+ end
74
+
75
+ def child_resources
76
+ self.class.child_resources
77
+ end
78
+ end
79
+
80
+ module PaginationSupport
81
+ extend ActiveSupport::Concern
82
+
83
+ included do
84
+ helper_method :count, :page, :per_page
85
+ end
86
+
87
+ # paginate collection
88
+ def collection
89
+ get_collection_ivar || set_collection_ivar(end_of_association_chain ? end_of_association_chain.page(page).per(per_page) : nil)
90
+ end
91
+
92
+ def page
93
+ (params[:page] || 1).to_i
94
+ end
95
+
96
+ def per_page
97
+ 20
98
+ end
99
+
100
+ def count
101
+ @count ||= if end_of_association_chain
102
+ end_of_association_chain.count
103
+ else
104
+ 0
105
+ end
106
+ end
107
+
108
+ end
109
+
110
+ end
111
+ end
@@ -0,0 +1,19 @@
1
+ module AppFrame
2
+ module ViewMethods
3
+ def self.included(klass)
4
+ klass.extend(ClassMethods)
5
+ end
6
+
7
+ def editable_attributes_for(klass)
8
+ klass.column_names - ['id', 'created_at', 'updated_at', 'type']
9
+ end
10
+
11
+ def attributes_for(klass)
12
+ klass.column_names
13
+ end
14
+
15
+ module ClassMethods
16
+
17
+ end
18
+ end
19
+ end
File without changes
@@ -0,0 +1,3716 @@
1
+ /*****************************************************************************
2
+ * FILE: anytime.js - The Any+Time(TM) JavaScript Library (source)
3
+ *
4
+ * VERSION: 4.1112K
5
+ *
6
+ * Copyright 2008-2011 Andrew M. Andrews III (www.AMA3.com). Some Rights
7
+ * Reserved. This work licensed under the Creative Commons Attribution-
8
+ * Noncommercial-Share Alike 3.0 Unported License except in jurisdicitons
9
+ * for which the license has been ported by Creative Commons International,
10
+ * where the work is licensed under the applicable ported license instead.
11
+ * For a copy of the unported license, visit
12
+ * http://creativecommons.org/licenses/by-nc-sa/3.0/
13
+ * or send a letter to Creative Commons, 171 Second Street, Suite 300,
14
+ * San Francisco, California, 94105, USA. For ported versions of the
15
+ * license, visit http://creativecommons.org/international/
16
+ *
17
+ * Alternative licensing arrangements may be made by contacting the
18
+ * author at http://www.AMA3.com/contact/
19
+ *
20
+ * The Any+Time(TM) JavaScript Library provides the following ECMAScript
21
+ * functionality:
22
+ *
23
+ * AnyTime.Converter
24
+ * Converts Dates to/from Strings, allowing a wide range of formats
25
+ * closely matching those provided by the MySQL DATE_FORMAT() function,
26
+ * with some noteworthy enhancements.
27
+ *
28
+ * AnyTime.pad()
29
+ * Pads a value with a specific number of leading zeroes.
30
+ *
31
+ * AnyTime.noPicker()
32
+ * Destroys a calendar widget previously added by AnyTime.picker().
33
+ * Can also be invoked via jQuery using $(selector).AnyTime_noPicker()
34
+ *
35
+ * AnyTime.picker()
36
+ * Attaches a calendar widget to a text field for selecting date/time
37
+ * values with fewer mouse movements than most similar pickers. Any
38
+ * format supported by AnyTime.Converter can be used for the text field.
39
+ * If JavaScript is disabled, the text field remains editable without
40
+ * any of the picker features.
41
+ * Can also be invoked via jQuery using $(selector).AnyTime_picker()
42
+ *
43
+ * IMPORTANT NOTICE: This code depends upon the jQuery JavaScript Library
44
+ * (www.jquery.com), currently version 1.4.
45
+ *
46
+ * The Any+Time(TM) code and styles in anytime.css have been tested (but not
47
+ * extensively) on Windows Vista in Internet Explorer 8.0, Firefox 3.0, Opera
48
+ * 10.10 and Safari 4.0. Minor variations in IE6+7 are to be expected, due
49
+ * to their broken box model. Please report any other problems to the author
50
+ * (URL above).
51
+ *
52
+ * Any+Time is a trademark of Andrew M. Andrews III.
53
+ * Thanks to Chu for help with a setMonth() issue!
54
+ ****************************************************************************/
55
+
56
+ var AnyTime =
57
+ {
58
+ //=============================================================================
59
+ // AnyTime.pad() pads a value with a specified number of zeroes and returns
60
+ // a string containing the padded value.
61
+ //=============================================================================
62
+
63
+ pad: function( val, len )
64
+ {
65
+ var str = String(Math.abs(val));
66
+ while ( str.length < len )
67
+ str = '0'+str;
68
+ if ( val < 0 )
69
+ str = '-'+str;
70
+ return str;
71
+ }
72
+ };
73
+
74
+ (function($)
75
+ {
76
+ // private members
77
+
78
+ var __oneDay = (24*60*60*1000);
79
+ var __daysIn = [ 31,28,31,30,31,30,31,31,30,31,30,31 ];
80
+ var __iframe = null;
81
+ var __initialized = false;
82
+ var __msie6 = ( navigator.userAgent.indexOf('MSIE 6') > 0 );
83
+ var __msie7 = ( navigator.userAgent.indexOf('MSIE 7') > 0 );
84
+ var __pickers = [];
85
+
86
+ // Add methods to jQuery to create and destroy pickers using
87
+ // the typical jQuery approach.
88
+
89
+ jQuery.prototype.AnyTime_picker = function( options )
90
+ {
91
+ return this.each( function(i) { AnyTime.picker( this.id, options ); } );
92
+ }
93
+
94
+ jQuery.prototype.AnyTime_noPicker = function()
95
+ {
96
+ return this.each( function(i) { AnyTime.noPicker( this.id ); } );
97
+ }
98
+
99
+ // Add methods to jQuery to change the earliest and latest times using
100
+ // the typical jQuery approach.
101
+
102
+ jQuery.prototype.AnyTime_setEarliest = function( options )
103
+ {
104
+ return this.each( function(i) { AnyTime.setEarliest( this.id, options ); } );
105
+ }
106
+
107
+ jQuery.prototype.AnyTime_setLatest = function( options )
108
+ {
109
+ return this.each( function(i) { AnyTime.setLatest( this.id, options ); } );
110
+ }
111
+
112
+ // Add special methods to jQuery to compute the height and width
113
+ // of picker components differently for Internet Explorer 6.x
114
+ // This prevents the pickers from being too tall and wide.
115
+
116
+ jQuery.prototype.AnyTime_height = function(inclusive)
117
+ {
118
+ return ( __msie6 ?
119
+ Number(this.css('height').replace(/[^0-9]/g,'')) :
120
+ this.outerHeight(inclusive) );
121
+ };
122
+
123
+ jQuery.prototype.AnyTime_width = function(inclusive)
124
+ {
125
+ return ( __msie6 ?
126
+ (1+Number(this.css('width').replace(/[^0-9]/g,''))) :
127
+ this.outerWidth(inclusive) );
128
+ };
129
+
130
+
131
+ // Add a method to jQuery to change the classes of an element to
132
+ // indicate whether it's value is current (used by AnyTime.picker),
133
+ // and another to trigger the click handler for the currently-
134
+ // selected button under an element.
135
+
136
+ jQuery.prototype.AnyTime_current = function(isCurrent,isLegal)
137
+ {
138
+ if ( isCurrent )
139
+ {
140
+ this.removeClass('AnyTime-out-btn ui-state-default ui-state-disabled ui-state-highlight');
141
+ this.addClass('AnyTime-cur-btn ui-state-default ui-state-highlight');
142
+ }
143
+ else
144
+ {
145
+ this.removeClass('AnyTime-cur-btn ui-state-highlight');
146
+ if ( ! isLegal )
147
+ this.addClass('AnyTime-out-btn ui-state-disabled');
148
+ else
149
+ this.removeClass('AnyTime-out-btn ui-state-disabled');
150
+ }
151
+ };
152
+
153
+ jQuery.prototype.AnyTime_clickCurrent = function()
154
+ {
155
+ this.find('.AnyTime-cur-btn').triggerHandler('click');
156
+ }
157
+
158
+ $(document).ready(
159
+ function()
160
+ {
161
+ // IE6 doesn't float popups over <select> elements unless an
162
+ // <iframe> is inserted between them! The <iframe> is added to
163
+ // the page *before* the popups are moved, so they will appear
164
+ // after the <iframe>.
165
+
166
+ if ( __msie6 )
167
+ {
168
+ __iframe = $('<iframe frameborder="0" scrolling="no"></iframe>');
169
+ __iframe.src = "javascript:'<html></html>';";
170
+ $(__iframe).css( {
171
+ display: 'block',
172
+ height: '1px',
173
+ left: '0',
174
+ top: '0',
175
+ width: '1px',
176
+ zIndex: 0
177
+ } );
178
+ $(document.body).append(__iframe);
179
+ }
180
+
181
+ // Move popup windows to the end of the page. This allows them to
182
+ // overcome XHTML restrictions on <table> placement enforced by MSIE.
183
+
184
+ for ( var id in __pickers )
185
+ if ( ! Array.prototype[id] ) // prototype.js compatibility issue
186
+ __pickers[id].onReady();
187
+
188
+ __initialized = true;
189
+
190
+ } ); // document.ready
191
+
192
+ //=============================================================================
193
+ // AnyTime.Converter
194
+ //
195
+ // This object converts between Date objects and Strings.
196
+ //
197
+ // To use AnyTime.Converter, simply create an instance for a format string,
198
+ // and then (repeatedly) invoke the format() and/or parse() methods to
199
+ // perform the conversions. For example:
200
+ //
201
+ // var converter = new AnyTime.Converter({format:'%Y-%m-%d'})
202
+ // var datetime = converter.parse('1967-07-30') // July 30, 1967 @ 00:00
203
+ // alert( converter.format(datetime) ); // outputs: 1967-07-30
204
+ //
205
+ // Constructor parameter:
206
+ //
207
+ // options - an object of optional parameters that override default behaviors.
208
+ // The supported options are:
209
+ //
210
+ // baseYear - the number to add to two-digit years if the %y format
211
+ // specifier is used. By default, AnyTime.Converter follows the
212
+ // MySQL assumption that two-digit years are in the range 1970 to 2069
213
+ // (see http://dev.mysql.com/doc/refman/5.1/en/y2k-issues.html).
214
+ // The most common alternatives for baseYear are 1900 and 2000.
215
+ //
216
+ // dayAbbreviations - an array of seven strings, indexed 0-6, to be used
217
+ // as ABBREVIATED day names. If not specified, the following are used:
218
+ // ['Sun','Mon','Tue','Wed','Thu','Fri','Sat']
219
+ // Note that if the firstDOW option is passed to AnyTime.picker() (see
220
+ // AnyTime.picker()), this array should nonetheless begin with the
221
+ // desired abbreviation for Sunday.
222
+ //
223
+ // dayNames - an array of seven strings, indexed 0-6, to be used as
224
+ // day names. If not specified, the following are used: ['Sunday',
225
+ // 'Monday','Tuesday','Wednesday','Thursday','Friday','Saturday']
226
+ // Note that if the firstDOW option is passed to AnyTime.picker() (see
227
+ // AnyTime.picker()), this array should nonetheless begin with the
228
+ // desired name for Sunday.
229
+ //
230
+ // eraAbbreviations - an array of two strings, indexed 0-1, to be used
231
+ // as ABBREVIATED era names. Item #0 is the abbreviation for "Before
232
+ // Common Era" (years before 0001, sometimes represented as negative
233
+ // years or "B.C"), while item #1 is the abbreviation for "Common Era"
234
+ // (years from 0001 to present, usually represented as unsigned years
235
+ // or years "A.D."). If not specified, the following are used:
236
+ // ['BCE','CE']
237
+ //
238
+ // format - a string specifying the pattern of strings involved in the
239
+ // conversion. The parse() method can take a string in this format and
240
+ // convert it to a Date, and the format() method can take a Date object
241
+ // and convert it to a string matching the format.
242
+ //
243
+ // Fields in the format string must match those for the DATE_FORMAT()
244
+ // function in MySQL, as defined here:
245
+ // http://tinyurl.com/bwd45#function_date-format
246
+ //
247
+ // IMPORTANT: Some MySQL specifiers are not supported (especially
248
+ // those involving day-of-the-year, week-of-the-year) or approximated.
249
+ // See the code for exact behavior.
250
+ //
251
+ // In addition to the MySQL format specifiers, the following custom
252
+ // specifiers are also supported:
253
+ //
254
+ // %B - If the year is before 0001, then the "Before Common Era"
255
+ // abbreviation (usually BCE or the obsolete BC) will go here.
256
+ //
257
+ // %C - If the year is 0001 or later, then the "Common Era"
258
+ // abbreviation (usually CE or the obsolete AD) will go here.
259
+ //
260
+ // %E - If the year is before 0001, then the "Before Common Era"
261
+ // abbreviation (usually BCE or the obsolete BC) will go here.
262
+ // Otherwise, the "Common Era" abbreviation (usually CE or the
263
+ // obsolete AD) will go here.
264
+ //
265
+ // %Z - The current four-digit year, without any sign. This is
266
+ // commonly used with years that might be before (or after) 0001,
267
+ // when the %E (or %B and %C) specifier is used instead of a sign.
268
+ // For example, 45 BCE is represented "0045". By comparison, in
269
+ // the "%Y" format, 45 BCE is represented "-0045".
270
+ //
271
+ // %z - The current year, without any sign, using only the necessary
272
+ // number of digits. This if the year is commonly used with years
273
+ // that might be before (or after) 0001, when the %E (or %B and %C)
274
+ // specifier is used instead of a sign. For example, the year
275
+ // 45 BCE is represented as "45", and the year 312 CE as "312".
276
+ //
277
+ // %# - the timezone offset, with a sign, in minutes.
278
+ //
279
+ // %+ - the timezone offset, with a sign, in hours and minutes, in
280
+ // four-digit, 24-hour format with no delimiter (for example, +0530).
281
+ // To remember the difference between %+ and %-, it might be helpful
282
+ // to remember that %+ might have more characters than %-.
283
+ //
284
+ // %: - the timezone offset, with a sign, in hours and minutes, in
285
+ // four-digit, 24-hour format with a colon delimiter (for example,
286
+ // +05:30). This is similar to the %z format used by Java.
287
+ // To remember the difference between %: and %;, it might be helpful
288
+ // to remember that a colon (:) has a period (.) on the bottom and
289
+ // a semicolon (;) has a comma (,), and in English sentence structure,
290
+ // a period represents a more significant stop than a comma, and
291
+ // %: might be a longer string than %; (I know it's a stretch, but
292
+ // it's easier than looking it up every time)!
293
+ //
294
+ // %- - the timezone offset, with a sign, in hours and minutes, in
295
+ // three-or-four-digit, 24-hour format with no delimiter (for
296
+ // example, +530).
297
+ //
298
+ // %; - the timezone offset, with a sign, in hours and minutes, in
299
+ // three-or-four-digit, 24-hour format with a colon delimiter
300
+ // (for example, +5:30).
301
+ //
302
+ // %@ - the timezone offset label. By default, this will be the
303
+ // string "UTC" followed by the offset, with a sign, in hours and
304
+ // minutes, in four-digit, 24-hour format with a colon delimiter
305
+ // (for example, UTC+05:30). However, if Any+Time(TM) has been
306
+ // extended with a member named utcLabel (for example, by the
307
+ // anytimetz.js file), then it is assumed to be an array of arrays,
308
+ // where the primary array is indexed by time zone offsets, and
309
+ // each sub-array contains a potential label for that offset.
310
+ // When parsing with %@, the array is scanned for matches to the
311
+ // input string, and if a match is found, the corresponding UTC
312
+ // offset is used. When formatting, the array is scanned for a
313
+ // matching offset, and if one is found, the first member of the
314
+ // sub-array is used for output (unless overridden with
315
+ // utcFormatOffsetSubIndex or setUtcFormatOffsetSubIndex()).
316
+ // If the array does not exist, or does not contain a sub-array
317
+ // for the offset, then the default format is used.
318
+ //
319
+ // monthAbbreviations - an array of twelve strings, indexed 0-6, to be
320
+ // used as ABBREVIATED month names. If not specified, the following
321
+ // are used: ['Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep',
322
+ // 'Oct','Nov','Dec']
323
+ //
324
+ // monthNames - an array of twelve strings, indexed 0-6, to be used as
325
+ // month names. If not specified, the following are used:
326
+ // ['January','February','March','April','May','June','July',
327
+ // 'August','September','October','November','December']
328
+ //
329
+ // utcFormatOffsetAlleged - the offset from UTC, in minutes, to claim that
330
+ // a Date object represents during formatting, even though it is formatted
331
+ // using local time. Unlike utcFormatOffsetImposed, which actually
332
+ // converts the Date object to the specified different time zone, this
333
+ // option merely reports the alleged offset when a timezone specifier
334
+ // (%#, %+, %-, %:, %; %@) is encountered in the format string.
335
+ // This primarily exists so AnyTime.picker can edit the time as specified
336
+ // (without conversion to local time) and then convert the edited time to
337
+ // a different time zone (as selected using the picker). Any initial
338
+ // value specified here can be changed by setUtcFormatOffsetAlleged().
339
+ // If a format offset is alleged, one cannot also be imposed (the imposed
340
+ // offset is ignored).
341
+ //
342
+ // utcFormatOffsetImposed - the offset from UTC, in minutes, to specify when
343
+ // formatting a Date object. By default, a Date is always formatted
344
+ // using the local time zone.
345
+ //
346
+ // utcFormatOffsetSubIndex - when extending AnyTime with a utcLabel array
347
+ // (for example, by the anytimetz.js file), the specified sub-index is
348
+ // used to choose the Time Zone label for the UTC offset when formatting
349
+ // a Date object. This primarily exists so AnyTime.picker can specify
350
+ // the label selected using the picker. Any initial value specified here
351
+ // can be changed by setUtcFormatOffsetSubIndex().
352
+ //
353
+ // utcParseOffsetAssumed - the offset from UTC, in minutes, to assume when
354
+ // parsing a String object. By default, a Date is always parsed using the
355
+ // local time zone, unless the format string includes a timezone
356
+ // specifier (%#, %+, %-, %:, %; or %@), in which case the timezone
357
+ // specified in the string is used. The Date object created by parsing
358
+ // always represents local time regardless of the input time zone.
359
+ //
360
+ // utcParseOffsetCapture - if true, any parsed string is always treated as
361
+ // though it represents local time, and any offset specified by the string
362
+ // (or utcParseOffsetAssume) is captured for return by the
363
+ // getUtcParseOffsetCaptured() method. If the %@ format specifier is
364
+ // used, the sub-index of any matched label is also captured for return
365
+ // by the getUtcParseOffsetSubIndex() method. This primarily exists so
366
+ // AnyTime.picker can edit the time as specified (without conversion to
367
+ // local time) and then convert the edited time to a different time zone
368
+ // (as selected using the picker).
369
+ //=============================================================================
370
+
371
+ AnyTime.Converter = function(options)
372
+ {
373
+ // private members
374
+
375
+ var _flen = 0;
376
+ var _longDay = 9;
377
+ var _longMon = 9;
378
+ var _shortDay = 6;
379
+ var _shortMon = 3;
380
+ var _offAl = Number.MIN_VALUE; // format time zone offset alleged
381
+ var _offCap = Number.MIN_VALUE; // parsed time zone offset captured
382
+ var _offF = Number.MIN_VALUE; // format time zone offset imposed
383
+ var _offFSI = (-1); // format time zone label subindex
384
+ var _offP = Number.MIN_VALUE; // parsed time zone offset assumed
385
+ var _offPSI = (-1); // parsed time zone label subindex captured
386
+ var _captureOffset = false;
387
+
388
+ // public members
389
+
390
+ this.fmt = '%Y-%m-%d %T';
391
+ this.dAbbr = ['Sun','Mon','Tue','Wed','Thu','Fri','Sat'];
392
+ this.dNames = ['Sunday','Monday','Tuesday','Wednesday','Thursday','Friday','Saturday'];
393
+ this.eAbbr = ['BCE','CE'];
394
+ this.mAbbr = [ 'Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec' ];
395
+ this.mNames = [ 'January','February','March','April','May','June','July','August','September','October','November','December' ];
396
+ this.baseYear = null;
397
+
398
+ //-------------------------------------------------------------------------
399
+ // AnyTime.Converter.dAt() returns true if the character in str at pos
400
+ // is a digit.
401
+ //-------------------------------------------------------------------------
402
+
403
+ this.dAt = function( str, pos )
404
+ {
405
+ return ( (str.charCodeAt(pos)>='0'.charCodeAt(0)) &&
406
+ (str.charCodeAt(pos)<='9'.charCodeAt(0)) );
407
+ };
408
+
409
+ //-------------------------------------------------------------------------
410
+ // AnyTime.Converter.format() returns a String containing the value
411
+ // of a specified Date object, using the format string passed to
412
+ // AnyTime.Converter().
413
+ //
414
+ // Method parameter:
415
+ //
416
+ // date - the Date object to be converted
417
+ //-------------------------------------------------------------------------
418
+
419
+ this.format = function( date )
420
+ {
421
+ var d = new Date(date.getTime());
422
+ if ( ( _offAl == Number.MIN_VALUE ) && ( _offF != Number.MIN_VALUE ) )
423
+ d.setTime( ( d.getTime() + (d.getTimezoneOffset()*60000) ) + (_offF*60000) );
424
+
425
+ var t;
426
+ var str = '';
427
+ for ( var f = 0 ; f < _flen ; f++ )
428
+ {
429
+ if ( this.fmt.charAt(f) != '%' )
430
+ str += this.fmt.charAt(f);
431
+ else
432
+ {
433
+ var ch = this.fmt.charAt(f+1)
434
+ switch ( ch )
435
+ {
436
+ case 'a': // Abbreviated weekday name (Sun..Sat)
437
+ str += this.dAbbr[ d.getDay() ];
438
+ break;
439
+ case 'B': // BCE string (eAbbr[0], usually BCE or BC, only if appropriate) (NON-MYSQL)
440
+ if ( d.getFullYear() < 0 )
441
+ str += this.eAbbr[0];
442
+ break;
443
+ case 'b': // Abbreviated month name (Jan..Dec)
444
+ str += this.mAbbr[ d.getMonth() ];
445
+ break;
446
+ case 'C': // CE string (eAbbr[1], usually CE or AD, only if appropriate) (NON-MYSQL)
447
+ if ( d.getFullYear() > 0 )
448
+ str += this.eAbbr[1];
449
+ break;
450
+ case 'c': // Month, numeric (0..12)
451
+ str += d.getMonth()+1;
452
+ break;
453
+ case 'd': // Day of the month, numeric (00..31)
454
+ t = d.getDate();
455
+ if ( t < 10 ) str += '0';
456
+ str += String(t);
457
+ break;
458
+ case 'D': // Day of the month with English suffix (0th, 1st,...)
459
+ t = String(d.getDate());
460
+ str += t;
461
+ if ( ( t.length == 2 ) && ( t.charAt(0) == '1' ) )
462
+ str += 'th';
463
+ else
464
+ {
465
+ switch ( t.charAt( t.length-1 ) )
466
+ {
467
+ case '1': str += 'st'; break;
468
+ case '2': str += 'nd'; break;
469
+ case '3': str += 'rd'; break;
470
+ default: str += 'th'; break;
471
+ }
472
+ }
473
+ break;
474
+ case 'E': // era string (from eAbbr[], BCE, CE, BC or AD) (NON-MYSQL)
475
+ str += this.eAbbr[ (d.getFullYear()<0) ? 0 : 1 ];
476
+ break;
477
+ case 'e': // Day of the month, numeric (0..31)
478
+ str += d.getDate();
479
+ break;
480
+ case 'H': // Hour (00..23)
481
+ t = d.getHours();
482
+ if ( t < 10 ) str += '0';
483
+ str += String(t);
484
+ break;
485
+ case 'h': // Hour (01..12)
486
+ case 'I': // Hour (01..12)
487
+ t = d.getHours() % 12;
488
+ if ( t == 0 )
489
+ str += '12';
490
+ else
491
+ {
492
+ if ( t < 10 ) str += '0';
493
+ str += String(t);
494
+ }
495
+ break;
496
+ case 'i': // Minutes, numeric (00..59)
497
+ t = d.getMinutes();
498
+ if ( t < 10 ) str += '0';
499
+ str += String(t);
500
+ break;
501
+ case 'k': // Hour (0..23)
502
+ str += d.getHours();
503
+ break;
504
+ case 'l': // Hour (1..12)
505
+ t = d.getHours() % 12;
506
+ if ( t == 0 )
507
+ str += '12';
508
+ else
509
+ str += String(t);
510
+ break;
511
+ case 'M': // Month name (January..December)
512
+ str += this.mNames[ d.getMonth() ];
513
+ break;
514
+ case 'm': // Month, numeric (00..12)
515
+ t = d.getMonth() + 1;
516
+ if ( t < 10 ) str += '0';
517
+ str += String(t);
518
+ break;
519
+ case 'p': // AM or PM
520
+ str += ( ( d.getHours() < 12 ) ? 'AM' : 'PM' );
521
+ break;
522
+ case 'r': // Time, 12-hour (hh:mm:ss followed by AM or PM)
523
+ t = d.getHours() % 12;
524
+ if ( t == 0 )
525
+ str += '12:';
526
+ else
527
+ {
528
+ if ( t < 10 ) str += '0';
529
+ str += String(t) + ':';
530
+ }
531
+ t = d.getMinutes();
532
+ if ( t < 10 ) str += '0';
533
+ str += String(t) + ':';
534
+ t = d.getSeconds();
535
+ if ( t < 10 ) str += '0';
536
+ str += String(t);
537
+ str += ( ( d.getHours() < 12 ) ? 'AM' : 'PM' );
538
+ break;
539
+ case 'S': // Seconds (00..59)
540
+ case 's': // Seconds (00..59)
541
+ t = d.getSeconds();
542
+ if ( t < 10 ) str += '0';
543
+ str += String(t);
544
+ break;
545
+ case 'T': // Time, 24-hour (hh:mm:ss)
546
+ t = d.getHours();
547
+ if ( t < 10 ) str += '0';
548
+ str += String(t) + ':';
549
+ t = d.getMinutes();
550
+ if ( t < 10 ) str += '0';
551
+ str += String(t) + ':';
552
+ t = d.getSeconds();
553
+ if ( t < 10 ) str += '0';
554
+ str += String(t);
555
+ break;
556
+ case 'W': // Weekday name (Sunday..Saturday)
557
+ str += this.dNames[ d.getDay() ];
558
+ break;
559
+ case 'w': // Day of the week (0=Sunday..6=Saturday)
560
+ str += d.getDay();
561
+ break;
562
+ case 'Y': // Year, numeric, four digits (negative if before 0001)
563
+ str += AnyTime.pad(d.getFullYear(),4);
564
+ break;
565
+ case 'y': // Year, numeric (two digits, negative if before 0001)
566
+ t = d.getFullYear() % 100;
567
+ str += AnyTime.pad(t,2);
568
+ break;
569
+ case 'Z': // Year, numeric, four digits, unsigned (NON-MYSQL)
570
+ str += AnyTime.pad(Math.abs(d.getFullYear()),4);
571
+ break;
572
+ case 'z': // Year, numeric, variable length, unsigned (NON-MYSQL)
573
+ str += Math.abs(d.getFullYear());
574
+ break;
575
+ case '%': // A literal '%' character
576
+ str += '%';
577
+ break;
578
+ case '#': // signed timezone offset in minutes
579
+ t = ( _offAl != Number.MIN_VALUE ) ? _offAl :
580
+ ( _offF == Number.MIN_VALUE ) ? (0-d.getTimezoneOffset()) : _offF;
581
+ if ( t >= 0 )
582
+ str += '+';
583
+ str += t;
584
+ break;
585
+ case '@': // timezone offset label
586
+ t = ( _offAl != Number.MIN_VALUE ) ? _offAl :
587
+ ( _offF == Number.MIN_VALUE ) ? (0-d.getTimezoneOffset()) : _offF;
588
+ if ( AnyTime.utcLabel && AnyTime.utcLabel[t] )
589
+ {
590
+ if ( ( _offFSI > 0 ) && ( _offFSI < AnyTime.utcLabel[t].length ) )
591
+ str += AnyTime.utcLabel[t][_offFSI];
592
+ else
593
+ str += AnyTime.utcLabel[t][0];
594
+ break;
595
+ }
596
+ str += 'UTC';
597
+ ch = ':'; // drop through for offset formatting
598
+ case '+': // signed, 4-digit timezone offset in hours and minutes
599
+ case '-': // signed, 3-or-4-digit timezone offset in hours and minutes
600
+ case ':': // signed 4-digit timezone offset with colon delimiter
601
+ case ';': // signed 3-or-4-digit timezone offset with colon delimiter
602
+ t = ( _offAl != Number.MIN_VALUE ) ? _offAl :
603
+ ( _offF == Number.MIN_VALUE ) ? (0-d.getTimezoneOffset()) : _offF;
604
+ if ( t < 0 )
605
+ str += '-';
606
+ else
607
+ str += '+';
608
+ t = Math.abs(t);
609
+ str += ((ch=='+')||(ch==':')) ? AnyTime.pad(Math.floor(t/60),2) : Math.floor(t/60);
610
+ if ( (ch==':') || (ch==';') )
611
+ str += ':';
612
+ str += AnyTime.pad(t%60,2);
613
+ break;
614
+ case 'f': // Microseconds (000000..999999)
615
+ case 'j': // Day of year (001..366)
616
+ case 'U': // Week (00..53), where Sunday is the first day of the week
617
+ case 'u': // Week (00..53), where Monday is the first day of the week
618
+ case 'V': // Week (01..53), where Sunday is the first day of the week; used with %X
619
+ case 'v': // Week (01..53), where Monday is the first day of the week; used with %x
620
+ case 'X': // Year for the week where Sunday is the first day of the week, numeric, four digits; used with %V
621
+ case 'x': // Year for the week, where Monday is the first day of the week, numeric, four digits; used with %v
622
+ throw '%'+ch+' not implemented by AnyTime.Converter';
623
+ default: // for any character not listed above
624
+ str += this.fmt.substr(f,2);
625
+ } // switch ( this.fmt.charAt(f+1) )
626
+ f++;
627
+ } // else
628
+ } // for ( var f = 0 ; f < _flen ; f++ )
629
+ return str;
630
+
631
+ }; // AnyTime.Converter.format()
632
+
633
+ //-------------------------------------------------------------------------
634
+ // AnyTime.Converter.getUtcParseOffsetCaptured() returns the UTC offset
635
+ // last captured by a parsed string (or assumed by utcParseOffsetAssumed).
636
+ // It returns Number.MIN_VALUE if this object was not constructed with
637
+ // the utcParseOffsetCapture option set to true, or if an offset was not
638
+ // specified by the last parsed string or utcParseOffsetAssumed.
639
+ //-------------------------------------------------------------------------
640
+
641
+ this.getUtcParseOffsetCaptured = function()
642
+ {
643
+ return _offCap;
644
+ };
645
+
646
+ //-------------------------------------------------------------------------
647
+ // AnyTime.Converter.getUtcParseOffsetCaptured() returns the UTC offset
648
+ // last captured by a parsed string (or assumed by utcParseOffsetAssumed).
649
+ // It returns Number.MIN_VALUE if this object was not constructed with
650
+ // the utcParseOffsetCapture option set to true, or if an offset was not
651
+ // specified by the last parsed string or utcParseOffsetAssumed.
652
+ //-------------------------------------------------------------------------
653
+
654
+ this.getUtcParseOffsetSubIndex = function()
655
+ {
656
+ return _offPSI;
657
+ };
658
+
659
+ //-------------------------------------------------------------------------
660
+ // AnyTime.Converter.parse() returns a Date initialized from a specified
661
+ // string, using the format passed to AnyTime.Converter().
662
+ //
663
+ // Method parameter:
664
+ //
665
+ // str - the String object to be converted
666
+ //-------------------------------------------------------------------------
667
+
668
+ this.parse = function( str )
669
+ {
670
+ _offCap = _offP;
671
+ _offPSI = (-1);
672
+ var era = 1;
673
+ var time = new Date(4,0,1,0,0,0,0);//4=leap year bug
674
+ var slen = str.length;
675
+ var s = 0;
676
+ var tzSign = 1, tzOff = _offP;
677
+ var i, matched, sub, sublen, temp;
678
+ for ( var f = 0 ; f < _flen ; f++ )
679
+ {
680
+ if ( this.fmt.charAt(f) == '%' )
681
+ {
682
+ var ch = this.fmt.charAt(f+1);
683
+ switch ( ch )
684
+ {
685
+ case 'a': // Abbreviated weekday name (Sun..Sat)
686
+ matched = false;
687
+ for ( sublen = 0 ; s + sublen < slen ; sublen++ )
688
+ {
689
+ sub = str.substr(s,sublen);
690
+ for ( i = 0 ; i < 12 ; i++ )
691
+ if ( this.dAbbr[i] == sub )
692
+ {
693
+ matched = true;
694
+ s += sublen;
695
+ break;
696
+ }
697
+ if ( matched )
698
+ break;
699
+ } // for ( sublen ... )
700
+ if ( ! matched )
701
+ throw 'unknown weekday: '+str.substr(s);
702
+ break;
703
+ case 'B': // BCE string (eAbbr[0]), only if needed. (NON-MYSQL)
704
+ sublen = this.eAbbr[0].length;
705
+ if ( ( s + sublen <= slen ) && ( str.substr(s,sublen) == this.eAbbr[0] ) )
706
+ {
707
+ era = (-1);
708
+ s += sublen;
709
+ }
710
+ break;
711
+ case 'b': // Abbreviated month name (Jan..Dec)
712
+ matched = false;
713
+ for ( sublen = 0 ; s + sublen < slen ; sublen++ )
714
+ {
715
+ sub = str.substr(s,sublen);
716
+ for ( i = 0 ; i < 12 ; i++ )
717
+ if ( this.mAbbr[i] == sub )
718
+ {
719
+ time.setMonth( i );
720
+ matched = true;
721
+ s += sublen;
722
+ break;
723
+ }
724
+ if ( matched )
725
+ break;
726
+ } // for ( sublen ... )
727
+ if ( ! matched )
728
+ throw 'unknown month: '+str.substr(s);
729
+ break;
730
+ case 'C': // CE string (eAbbr[1]), only if needed. (NON-MYSQL)
731
+ sublen = this.eAbbr[1].length;
732
+ if ( ( s + sublen <= slen ) && ( str.substr(s,sublen) == this.eAbbr[1] ) )
733
+ s += sublen; // note: CE is the default era
734
+ break;
735
+ case 'c': // Month, numeric (0..12)
736
+ if ( ( s+1 < slen ) && this.dAt(str,s+1) )
737
+ {
738
+ time.setMonth( (Number(str.substr(s,2))-1)%12 );
739
+ s += 2;
740
+ }
741
+ else
742
+ {
743
+ time.setMonth( (Number(str.substr(s,1))-1)%12 );
744
+ s++;
745
+ }
746
+ break;
747
+ case 'D': // Day of the month with English suffix (0th,1st,...)
748
+ if ( ( s+1 < slen ) && this.dAt(str,s+1) )
749
+ {
750
+ time.setDate( Number(str.substr(s,2)) );
751
+ s += 4;
752
+ }
753
+ else
754
+ {
755
+ time.setDate( Number(str.substr(s,1)) );
756
+ s += 3;
757
+ }
758
+ break;
759
+ case 'd': // Day of the month, numeric (00..31)
760
+ time.setDate( Number(str.substr(s,2)) );
761
+ s += 2;
762
+ break;
763
+ case 'E': // era string (from eAbbr[]) (NON-MYSQL)
764
+ sublen = this.eAbbr[0].length;
765
+ if ( ( s + sublen <= slen ) && ( str.substr(s,sublen) == this.eAbbr[0] ) )
766
+ {
767
+ era = (-1);
768
+ s += sublen;
769
+ }
770
+ else if ( ( s + ( sublen = this.eAbbr[1].length ) <= slen ) && ( str.substr(s,sublen) == this.eAbbr[1] ) )
771
+ s += sublen; // note: CE is the default era
772
+ else
773
+ throw 'unknown era: '+str.substr(s);
774
+ break;
775
+ case 'e': // Day of the month, numeric (0..31)
776
+ if ( ( s+1 < slen ) && this.dAt(str,s+1) )
777
+ {
778
+ time.setDate( Number(str.substr(s,2)) );
779
+ s += 2;
780
+ }
781
+ else
782
+ {
783
+ time.setDate( Number(str.substr(s,1)) );
784
+ s++;
785
+ }
786
+ break;
787
+ case 'f': // Microseconds (000000..999999)
788
+ s += 6; // SKIPPED!
789
+ break;
790
+ case 'H': // Hour (00..23)
791
+ time.setHours( Number(str.substr(s,2)) );
792
+ s += 2;
793
+ break;
794
+ case 'h': // Hour (01..12)
795
+ case 'I': // Hour (01..12)
796
+ time.setHours( Number(str.substr(s,2)) );
797
+ s += 2;
798
+ break;
799
+ case 'i': // Minutes, numeric (00..59)
800
+ time.setMinutes( Number(str.substr(s,2)) );
801
+ s += 2;
802
+ break;
803
+ case 'k': // Hour (0..23)
804
+ if ( ( s+1 < slen ) && this.dAt(str,s+1) )
805
+ {
806
+ time.setHours( Number(str.substr(s,2)) );
807
+ s += 2;
808
+ }
809
+ else
810
+ {
811
+ time.setHours( Number(str.substr(s,1)) );
812
+ s++;
813
+ }
814
+ break;
815
+ case 'l': // Hour (1..12)
816
+ if ( ( s+1 < slen ) && this.dAt(str,s+1) )
817
+ {
818
+ time.setHours( Number(str.substr(s,2)) );
819
+ s += 2;
820
+ }
821
+ else
822
+ {
823
+ time.setHours( Number(str.substr(s,1)) );
824
+ s++;
825
+ }
826
+ break;
827
+ case 'M': // Month name (January..December)
828
+ matched = false;
829
+ for (sublen=_shortMon ; s + sublen <= slen ; sublen++ )
830
+ {
831
+ if ( sublen > _longMon )
832
+ break;
833
+ sub = str.substr(s,sublen);
834
+ for ( i = 0 ; i < 12 ; i++ )
835
+ {
836
+ if ( this.mNames[i] == sub )
837
+ {
838
+ time.setMonth( i );
839
+ matched = true;
840
+ s += sublen;
841
+ break;
842
+ }
843
+ }
844
+ if ( matched )
845
+ break;
846
+ }
847
+ break;
848
+ case 'm': // Month, numeric (00..12)
849
+ time.setMonth( (Number(str.substr(s,2))-1)%12 );
850
+ s += 2;
851
+ break;
852
+ case 'p': // AM or PM
853
+ if ( time.getHours() == 12 )
854
+ {
855
+ if ( str.charAt(s) == 'A' )
856
+ time.setHours(0);
857
+ }
858
+ else if ( str.charAt(s) == 'P' )
859
+ time.setHours( time.getHours() + 12 );
860
+ s += 2;
861
+ break;
862
+ case 'r': // Time, 12-hour (hh:mm:ss followed by AM or PM)
863
+ time.setHours(Number(str.substr(s,2)));
864
+ time.setMinutes(Number(str.substr(s+3,2)));
865
+ time.setSeconds(Number(str.substr(s+6,2)));
866
+ if ( time.getHours() == 12 )
867
+ {
868
+ if ( str.charAt(s) == 'A' )
869
+ time.setHours(0);
870
+ }
871
+ else if ( str.charAt(s) == 'P' )
872
+ time.setHours( time.getHours() + 12 );
873
+ s += 10;
874
+ break;
875
+ case 'S': // Seconds (00..59)
876
+ case 's': // Seconds (00..59)
877
+ time.setSeconds(Number(str.substr(s,2)));
878
+ s += 2;
879
+ break;
880
+ case 'T': // Time, 24-hour (hh:mm:ss)
881
+ time.setHours(Number(str.substr(s,2)));
882
+ time.setMinutes(Number(str.substr(s+3,2)));
883
+ time.setSeconds(Number(str.substr(s+6,2)));
884
+ s += 8;
885
+ break;
886
+ case 'W': // Weekday name (Sunday..Saturday)
887
+ matched = false;
888
+ for (sublen=_shortDay ; s + sublen <= slen ; sublen++ )
889
+ {
890
+ if ( sublen > _longDay )
891
+ break;
892
+ sub = str.substr(s,sublen);
893
+ for ( i = 0 ; i < 7 ; i++ )
894
+ {
895
+ if ( this.dNames[i] == sub )
896
+ {
897
+ matched = true;
898
+ s += sublen;
899
+ break;
900
+ }
901
+ }
902
+ if ( matched )
903
+ break;
904
+ }
905
+ break;
906
+ case 'w': // Day of the week (0=Sunday..6=Saturday) (ignored)
907
+ s += 1;
908
+ break;
909
+ case 'Y': // Year, numeric, four digits, negative if before 0001
910
+ i = 4;
911
+ if ( str.substr(s,1) == '-' )
912
+ i++;
913
+ time.setFullYear(Number(str.substr(s,i)));
914
+ s += i;
915
+ break;
916
+ case 'y': // Year, numeric (two digits), negative before baseYear
917
+ i = 2;
918
+ if ( str.substr(s,1) == '-' )
919
+ i++;
920
+ temp = Number(str.substr(s,i));
921
+ if ( typeof(this.baseYear) == 'number' )
922
+ temp += this.baseYear;
923
+ else if ( temp < 70 )
924
+ temp += 2000;
925
+ else
926
+ temp += 1900;
927
+ time.setFullYear(temp);
928
+ s += i;
929
+ break;
930
+ case 'Z': // Year, numeric, four digits, unsigned (NON-MYSQL)
931
+ time.setFullYear(Number(str.substr(s,4)));
932
+ s += 4;
933
+ break;
934
+ case 'z': // Year, numeric, variable length, unsigned (NON-MYSQL)
935
+ i = 0;
936
+ while ( ( s < slen ) && this.dAt(str,s) )
937
+ i = ( i * 10 ) + Number(str.charAt(s++));
938
+ time.setFullYear(i);
939
+ break;
940
+ case '#': // signed timezone offset in minutes.
941
+ if ( str.charAt(s++) == '-' )
942
+ tzSign = (-1);
943
+ for ( tzOff = 0 ; ( s < slen ) && (String(i=Number(str.charAt(s)))==str.charAt(s)) ; s++ )
944
+ tzOff = ( tzOff * 10 ) + i;
945
+ tzOff *= tzSign;
946
+ break;
947
+ case '@': // timezone label
948
+ _offPSI = (-1);
949
+ if ( AnyTime.utcLabel )
950
+ {
951
+ matched = false;
952
+ for ( tzOff in AnyTime.utcLabel )
953
+ if ( ! Array.prototype[tzOff] ) // prototype.js compatibility issue
954
+ {
955
+ for ( i = 0 ; i < AnyTime.utcLabel[tzOff].length ; i++ )
956
+ {
957
+ sub = AnyTime.utcLabel[tzOff][i];
958
+ sublen = sub.length;
959
+ if ( ( s+sublen <= slen ) && ( str.substr(s,sublen) == sub ) )
960
+ {
961
+ s+=sublen;
962
+ matched = true;
963
+ break;
964
+ }
965
+ }
966
+ if ( matched )
967
+ break;
968
+ }
969
+ if ( matched )
970
+ {
971
+ _offPSI = i;
972
+ tzOff = Number(tzOff);
973
+ break; // case
974
+ }
975
+ }
976
+ if ( ( s+9 < slen ) || ( str.substr(s,3) != "UTC" ) )
977
+ throw 'unknown time zone: '+str.substr(s);
978
+ s += 3;
979
+ ch = ':'; // drop through for offset parsing
980
+ case '-': // signed, 3-or-4-digit timezone offset in hours and minutes
981
+ case '+': // signed, 4-digit timezone offset in hours and minutes
982
+ case ':': // signed 4-digit timezone offset with colon delimiter
983
+ case ';': // signed 3-or-4-digit timezone offset with colon delimiter
984
+ if ( str.charAt(s++) == '-' )
985
+ tzSign = (-1);
986
+ tzOff = Number(str.charAt(s));
987
+ if ( (ch=='+')||(ch==':')||((s+3<slen)&&(String(Number(str.charAt(s+3)))!==str.charAt(s+3))) )
988
+ tzOff = (tzOff*10) + Number(str.charAt(++s));
989
+ tzOff *= 60;
990
+ if ( (ch==':') || (ch==';') )
991
+ s++; // skip ":" (assumed)
992
+ tzOff = ( tzOff + Number(str.substr(++s,2)) ) * tzSign;
993
+ s += 2;
994
+ break;
995
+ case 'j': // Day of year (001..366)
996
+ case 'U': // Week (00..53), where Sunday is the first day of the week
997
+ case 'u': // Week (00..53), where Monday is the first day of the week
998
+ case 'V': // Week (01..53), where Sunday is the first day of the week; used with %X
999
+ case 'v': // Week (01..53), where Monday is the first day of the week; used with %x
1000
+ case 'X': // Year for the week where Sunday is the first day of the week, numeric, four digits; used with %V
1001
+ case 'x': // Year for the week, where Monday is the first day of the week, numeric, four digits; used with %v
1002
+ throw '%'+this.fmt.charAt(f+1)+' not implemented by AnyTime.Converter';
1003
+ case '%': // A literal '%' character
1004
+ default: // for any character not listed above
1005
+ throw '%'+this.fmt.charAt(f+1)+' reserved for future use';
1006
+ break;
1007
+ }
1008
+ f++;
1009
+ } // if ( this.fmt.charAt(f) == '%' )
1010
+ else if ( this.fmt.charAt(f) != str.charAt(s) )
1011
+ throw str + ' is not in "' + this.fmt + '" format';
1012
+ else
1013
+ s++;
1014
+ } // for ( var f ... )
1015
+ if ( era < 0 )
1016
+ time.setFullYear( 0 - time.getFullYear() );
1017
+ if ( tzOff != Number.MIN_VALUE )
1018
+ {
1019
+ if ( _captureOffset )
1020
+ _offCap = tzOff;
1021
+ else
1022
+ time.setTime( ( time.getTime() - (tzOff*60000) ) - (time.getTimezoneOffset()*60000) );
1023
+ }
1024
+
1025
+ return time;
1026
+
1027
+ }; // AnyTime.Converter.parse()
1028
+
1029
+ //-------------------------------------------------------------------------
1030
+ // AnyTime.Converter.setUtcFormatOffsetAlleged() sets the offset from
1031
+ // UTC, in minutes, to claim that a Date object represents during
1032
+ // formatting, even though it is formatted using local time. This merely
1033
+ // reports the alleged offset when a timezone specifier (%#, %+, %-, %:,
1034
+ // %; or %@) is encountered in the format string--it does not otherwise
1035
+ // affect the date/time value. This primarily exists so AnyTime.picker
1036
+ // can edit the time as specified (without conversion to local time) and
1037
+ // then convert the edited time to a different time zone (as selected
1038
+ // using the picker). This method returns the previous value, if any,
1039
+ // set by the utcFormatOffsetAlleged option, or a previous call to
1040
+ // setUtcFormatOffsetAlleged(), or Number.MIN_VALUE if no offset was
1041
+ // previously-alleged. Call this method with Number.MIN_VALUE to cancel
1042
+ // any prior value. Note that if a format offset is alleged, any offset
1043
+ // specified by option utcFormatOffsetImposed is ignored.
1044
+ //-------------------------------------------------------------------------
1045
+
1046
+ this.setUtcFormatOffsetAlleged = function( offset )
1047
+ {
1048
+ var prev = _offAl;
1049
+ _offAl = offset;
1050
+ return prev;
1051
+ };
1052
+
1053
+ //-------------------------------------------------------------------------
1054
+ // AnyTime.Converter.setUtcFormatOffsetSubIndex() sets the sub-index
1055
+ // to choose from the AnyTime.utcLabel array of arrays when formatting
1056
+ // a Date using the %@ specifier. For more information, see option
1057
+ // AnyTime.Converter.utcFormatOffsetSubIndex. This primarily exists so
1058
+ // AnyTime.picker can specify the Time Zone label selected using the
1059
+ // picker). This method returns the previous value, if any, set by the
1060
+ // utcFormatOffsetSubIndex option, or a previous call to
1061
+ // setUtcFormatOffsetAlleged(), or (-1) if no sub-index was previously-
1062
+ // chosen. Call this method with (-1) to cancel any prior value.
1063
+ //-------------------------------------------------------------------------
1064
+
1065
+ this.setUtcFormatOffsetSubIndex = function( subIndex )
1066
+ {
1067
+ var prev = _offFSI;
1068
+ _offFSI = subIndex;
1069
+ return prev;
1070
+ };
1071
+
1072
+ //-------------------------------------------------------------------------
1073
+ // AnyTime.Converter construction code:
1074
+ //-------------------------------------------------------------------------
1075
+
1076
+ (function(_this)
1077
+ {
1078
+ var i, len;
1079
+
1080
+ options = jQuery.extend(true,{},options||{});
1081
+
1082
+ if ( options.baseYear )
1083
+ _this.baseYear = Number(options.baseYear);
1084
+
1085
+ if ( options.format )
1086
+ _this.fmt = options.format;
1087
+
1088
+ _flen = _this.fmt.length;
1089
+
1090
+ if ( options.dayAbbreviations )
1091
+ _this.dAbbr = $.makeArray( options.dayAbbreviations );
1092
+
1093
+ if ( options.dayNames )
1094
+ {
1095
+ _this.dNames = $.makeArray( options.dayNames );
1096
+ _longDay = 1;
1097
+ _shortDay = 1000;
1098
+ for ( i = 0 ; i < 7 ; i++ )
1099
+ {
1100
+ len = _this.dNames[i].length;
1101
+ if ( len > _longDay )
1102
+ _longDay = len;
1103
+ if ( len < _shortDay )
1104
+ _shortDay = len;
1105
+ }
1106
+ }
1107
+
1108
+ if ( options.eraAbbreviations )
1109
+ _this.eAbbr = $.makeArray(options.eraAbbreviations);
1110
+
1111
+ if ( options.monthAbbreviations )
1112
+ _this.mAbbr = $.makeArray(options.monthAbbreviations);
1113
+
1114
+ if ( options.monthNames )
1115
+ {
1116
+ _this.mNames = $.makeArray( options.monthNames );
1117
+ _longMon = 1;
1118
+ _shortMon = 1000;
1119
+ for ( i = 0 ; i < 12 ; i++ )
1120
+ {
1121
+ len = _this.mNames[i].length;
1122
+ if ( len > _longMon )
1123
+ _longMon = len;
1124
+ if ( len < _shortMon )
1125
+ _shortMon = len;
1126
+ }
1127
+ }
1128
+
1129
+ if ( typeof options.utcFormatOffsetImposed != "undefined" )
1130
+ _offF = options.utcFormatOffsetImposed;
1131
+
1132
+ if ( typeof options.utcParseOffsetAssumed != "undefined" )
1133
+ _offP = options.utcParseOffsetAssumed;
1134
+
1135
+ if ( options.utcParseOffsetCapture )
1136
+ _captureOffset = true;
1137
+
1138
+ })(this); // AnyTime.Converter construction
1139
+
1140
+ }; // AnyTime.Converter =
1141
+
1142
+ //=============================================================================
1143
+ // AnyTime.noPicker()
1144
+ //
1145
+ // Removes the date/time entry picker attached to a specified text field.
1146
+ //=============================================================================
1147
+
1148
+ AnyTime.noPicker = function( id )
1149
+ {
1150
+ if ( __pickers[id] )
1151
+ {
1152
+ __pickers[id].cleanup();
1153
+ delete __pickers[id];
1154
+ }
1155
+ };
1156
+
1157
+ //=============================================================================
1158
+ // AnyTime.picker()
1159
+ //
1160
+ // Creates a date/time entry picker attached to a specified text field.
1161
+ // Instead of entering a date and/or time into the text field, the user
1162
+ // selects legal combinations using the picker, and the field is auto-
1163
+ // matically populated. The picker can be incorporated into the page
1164
+ // "inline", or used as a "popup" that appears when the text field is
1165
+ // clicked and disappears when the picker is dismissed. Ajax can be used
1166
+ // to send the selected value to a server to approve or veto it.
1167
+ //
1168
+ // To create a picker, simply include the necessary files in an HTML page
1169
+ // and call the function for each date/time input field. The following
1170
+ // example creates a popup picker for field "foo" using the default
1171
+ // format, and a second date-only (no time) inline (always-visible)
1172
+ // Ajax-enabled picker for field "bar":
1173
+ //
1174
+ // <link rel="stylesheet" type="text/css" href="anytime.css" />
1175
+ // <script type="text/javascript" src="jquery.js"></script>
1176
+ // <script type="text/javascript" src="anytime.js"></script>
1177
+ // <input type="text" id="foo" tabindex="1" value="1967-07-30 23:45" />
1178
+ // <input type="text" id="bar" tabindex="2" value="01/06/90" />
1179
+ // <script type="text/javascript">
1180
+ // AnyTime.picker( "foo" );
1181
+ // AnyTime.picker( "bar", { placement:"inline", format: "%m/%d/%y",
1182
+ // ajaxOptions { url: "/some/server/page/" } } );
1183
+ // </script>
1184
+ //
1185
+ // The appearance of the picker can be extensively modified using CSS styles.
1186
+ // A default appearance can be achieved by the "anytime.css" stylesheet that
1187
+ // accompanies this script. The default style looks better in browsers other
1188
+ // than Internet Explorer (before IE8) because older versions of IE do not
1189
+ // properly implement the CSS box model standard; however, it is passable in
1190
+ // Internet Explorer as well.
1191
+ //
1192
+ // Method parameters:
1193
+ //
1194
+ // id - the "id" attribute of the textfield to associate with the
1195
+ // AnyTime.picker object. The AnyTime.picker will attach itself
1196
+ // to the textfield and manage its value.
1197
+ //
1198
+ // options - an object (associative array) of optional parameters that
1199
+ // override default behaviors. The supported options are:
1200
+ //
1201
+ // ajaxOptions - options passed to jQuery's $.ajax() method whenever
1202
+ // the user dismisses a popup picker or selects a value in an inline
1203
+ // picker. The input's name (or ID) and value are passed to the
1204
+ // server (appended to ajaxOptions.data, if present), and the
1205
+ // "success" handler sets the input's value to the responseText.
1206
+ // Therefore, the text returned by the server must be valid for the
1207
+ // input'sdate/time format, and the server can approve or veto the
1208
+ // value chosen by the user. For more information, see:
1209
+ // http://docs.jquery.com/Ajax.
1210
+ // If ajaxOptions.success is specified, it is used instead of the
1211
+ // default "success" behavior.
1212
+ //
1213
+ // askEra - if true, buttons to select the era are shown on the year
1214
+ // selector popup, even if format specifier does not include the
1215
+ // era. If false, buttons to select the era are NOT shown, even
1216
+ // if the format specifier includes ther era. Normally, era buttons
1217
+ // are only shown if the format string specifies the era.
1218
+ //
1219
+ // askSecond - if false, buttons for number-of-seconds are not shown
1220
+ // even if the format includes seconds. Normally, the buttons
1221
+ // are shown if the format string includes seconds.
1222
+ //
1223
+ // earliest - String or Date object representing the earliest date/time
1224
+ // that a user can select. For best results if the field is only
1225
+ // used to specify a date, be sure to set the time to 00:00:00.
1226
+ // If a String is used, it will be parsed according to the picker's
1227
+ // format (see AnyTime.Converter.format()).
1228
+ //
1229
+ // firstDOW - a value from 0 (Sunday) to 6 (Saturday) stating which
1230
+ // day should appear at the beginning of the week. The default is 0
1231
+ // (Sunday). The most common substitution is 1 (Monday). Note that
1232
+ // if custom arrays are specified for AnyTime.Converter's dayAbbreviations
1233
+ // and/or dayNames options, they should nonetheless begin with the
1234
+ // value for Sunday.
1235
+ //
1236
+ // hideInput - if true, the <input> is "hidden" (the picker appears in
1237
+ // its place). This actually sets the border, height, margin, padding
1238
+ // and width of the field as small as possivle, so it can still get focus.
1239
+ // If you try to hide the field using traditional techniques (such as
1240
+ // setting "display:none"), the picker will not behave correctly.
1241
+ //
1242
+ // labelDayOfMonth - the label for the day-of-month "buttons".
1243
+ // Can be any HTML! If not specified, "Day of Month" is assumed.
1244
+ //
1245
+ // labelDismiss - the label for the dismiss "button" (if placement is
1246
+ // "popup"). Can be any HTML! If not specified, "X" is assumed.
1247
+ //
1248
+ // labelHour - the label for the hour "buttons".
1249
+ // Can be any HTML! If not specified, "Hour" is assumed.
1250
+ //
1251
+ // labelMinute - the label for the minute "buttons".
1252
+ // Can be any HTML! If not specified, "Minute" is assumed.
1253
+ //
1254
+ // labelMonth - the label for the month "buttons".
1255
+ // Can be any HTML! If not specified, "Month" is assumed.
1256
+ //
1257
+ // labelTimeZone - the label for the UTC offset (timezone) "buttons".
1258
+ // Can be any HTML! If not specified, "Time Zone" is assumed.
1259
+ //
1260
+ // labelSecond - the label for the second "buttons".
1261
+ // Can be any HTML! If not specified, "Second" is assumed.
1262
+ // This option is ignored if askSecond is false!
1263
+ //
1264
+ // labelTitle - the label for the "title bar". Can be any HTML!
1265
+ // If not specified, then whichever of the following is most
1266
+ // appropriate is used: "Select a Date and Time", "Select a Date"
1267
+ // or "Select a Time", or no label if only one field is present.
1268
+ //
1269
+ // labelYear - the label for the year "buttons".
1270
+ // Can be any HTML! If not specified, "Year" is assumed.
1271
+ //
1272
+ // latest - String or Date object representing the latest date/time
1273
+ // that a user can select. For best results if the field is only
1274
+ // used to specify a date, be sure to set the time to 23:59:59.
1275
+ // If a String is used, it will be parsed according to the picker's
1276
+ // format (see AnyTime.Converter.format()).
1277
+ //
1278
+ // placement - One of the following strings:
1279
+ //
1280
+ // "popup" = the picker appears above its <input> when the input
1281
+ // receives focus, and disappears when it is dismissed. This is
1282
+ // the default behavior.
1283
+ //
1284
+ // "inline" = the picker is placed immediately after the <input>
1285
+ // and remains visible at all times. When choosing this placement,
1286
+ // it is best to make the <input> invisible and use only the
1287
+ // picker to select dates. The <input> value can still be used
1288
+ // during form submission as it will always reflect the current
1289
+ // picker state.
1290
+ //
1291
+ // WARNING: when using "inline" and XHTML and including a day-of-
1292
+ // the-month format field, the input may only appear where a <table>
1293
+ // element is permitted (for example, NOT within a <p> element).
1294
+ // This is because the picker uses a <table> element to arrange
1295
+ // the day-of-the-month (calendar) buttons. Failure to follow this
1296
+ // advice may result in an "unknown error" in Internet Explorer.
1297
+ //
1298
+ // The following additional options may be specified; see documentation
1299
+ // for AnyTime.Converter (above) for information about these options:
1300
+ //
1301
+ // baseYear
1302
+ // dayAbbreviations
1303
+ // dayNames
1304
+ // eraAbbreviations
1305
+ // format
1306
+ // monthAbbreviations
1307
+ // monthNames
1308
+ //
1309
+ // Other behavior, such as how to format the values on the display
1310
+ // and which "buttons" to include, is inferred from the format string.
1311
+ //=============================================================================
1312
+
1313
+ AnyTime.picker = function( id, options )
1314
+ {
1315
+ // Create a new private object instance to manage the picker,
1316
+ // if one does not already exist.
1317
+
1318
+ if ( __pickers[id] )
1319
+ throw 'Cannot create another AnyTime.picker for "'+id+'"';
1320
+
1321
+ var _this = null;
1322
+
1323
+ __pickers[id] =
1324
+ {
1325
+ // private members
1326
+
1327
+ twelveHr: false,
1328
+ ajaxOpts: null, // options for AJAX requests
1329
+ denyTab: true, // set to true to stop Opera from tabbing away
1330
+ askEra: false, // prompt the user for the era in yDiv?
1331
+ cloak: null, // cloak div
1332
+ conv: null, // AnyTime.Converter
1333
+ bMinW: 0, // min width of body div
1334
+ bMinH: 0, // min height of body div
1335
+ dMinW: 0, // min width of date div
1336
+ dMinH: 0, // min height of date div
1337
+ div: null, // picker div
1338
+ dB: null, // body div
1339
+ dD: null, // date div
1340
+ dY: null, // years div
1341
+ dMo: null, // months div
1342
+ dDoM: null, // date-of-month table
1343
+ hDoM: null, // date-of-month heading
1344
+ hMo: null, // month heading
1345
+ hTitle: null, // title heading
1346
+ hY: null, // year heading
1347
+ dT: null, // time div
1348
+ dH: null, // hours div
1349
+ dM: null, // minutes div
1350
+ dS: null, // seconds div
1351
+ dO: null, // offset (time zone) div
1352
+ earliest: null, // earliest selectable date/time
1353
+ fBtn: null, // button with current focus
1354
+ fDOW: 0, // index to use as first day-of-week
1355
+ hBlur: null, // input handler
1356
+ hClick: null, // input handler
1357
+ hFocus: null, // input handler
1358
+ hKeydown: null, // input handler
1359
+ hKeypress: null, // input handler
1360
+ id: null, // picker ID
1361
+ inp: null, // input text field
1362
+ latest: null, // latest selectable date/time
1363
+ lastAjax: null, // last value submitted using AJAX
1364
+ lostFocus: false, // when focus is lost, must redraw
1365
+ lX: 'X', // label for dismiss button
1366
+ lY: 'Year', // label for year
1367
+ lO: 'Time Zone', // label for UTC offset (time zone)
1368
+ oBody: null, // UTC offset selector popup
1369
+ oConv: null, // AnyTime.Converter for offset display
1370
+ oCur: null, // current-UTC-offset button
1371
+ oDiv: null, // UTC offset selector popup
1372
+ oLab: null, // UTC offset label
1373
+ oListMinW: 0, // min width of offset list element
1374
+ oMinW: 0, // min width of UTC offset element
1375
+ oSel: null, // select (plus/minus) UTC-offset button
1376
+ offMin: Number.MIN_VALUE, // current UTC offset in minutes
1377
+ offSI: -1, // current UTC label sub-index (if any)
1378
+ offStr: "", // current UTC offset (time zone) string
1379
+ pop: true, // picker is a popup?
1380
+ time: null, // current date/time
1381
+ tMinW: 0, // min width of time div
1382
+ tMinH: 0, // min height of time div
1383
+ url: null, // URL to submit value using AJAX
1384
+ wMinW: 0, // min width of picker
1385
+ wMinH: 0, // min height of picker
1386
+ yAhead: null, // years-ahead button
1387
+ y0XXX: null, // millenium-digit-zero button (for focus)
1388
+ yCur: null, // current-year button
1389
+ yDiv: null, // year selector popup
1390
+ yLab: null, // year label
1391
+ yNext: null, // next-year button
1392
+ yPast: null, // years-past button
1393
+ yPrior: null, // prior-year button
1394
+
1395
+ //---------------------------------------------------------------------
1396
+ // .initialize() initializes the picker instance.
1397
+ //---------------------------------------------------------------------
1398
+
1399
+ initialize: function( id )
1400
+ {
1401
+ _this = this;
1402
+
1403
+ this.id = 'AnyTime--'+id.replace(/[^-_.A-Za-z0-9]/g,'--AnyTime--');
1404
+
1405
+ options = jQuery.extend(true,{},options||{});
1406
+ options.utcParseOffsetCapture = true;
1407
+ this.conv = new AnyTime.Converter(options);
1408
+
1409
+ if ( options.placement )
1410
+ {
1411
+ if ( options.placement == 'inline' )
1412
+ this.pop = false;
1413
+ else if ( options.placement != 'popup' )
1414
+ throw 'unknown placement: ' + options.placement;
1415
+ }
1416
+
1417
+ if ( options.ajaxOptions )
1418
+ {
1419
+ this.ajaxOpts = jQuery.extend( {}, options.ajaxOptions );
1420
+ if ( ! this.ajaxOpts.success )
1421
+ this.ajaxOpts.success = function(data,status) { _this.inp.val(data); };
1422
+ }
1423
+
1424
+ if ( options.earliest )
1425
+ {
1426
+ if ( typeof options.earliest.getTime == 'function' )
1427
+ this.earliest = options.earliest.getTime();
1428
+ else
1429
+ this.earliest = this.conv.parse( options.earliest.toString() );
1430
+ }
1431
+
1432
+ if ( options.firstDOW )
1433
+ {
1434
+ if ( ( options.firstDOW < 0 ) || ( options.firstDOW > 6 ) )
1435
+ throw new Exception('illegal firstDOW: ' + options.firstDOW);
1436
+ this.fDOW = options.firstDOW;
1437
+ }
1438
+
1439
+ if ( options.latest )
1440
+ {
1441
+ if ( typeof options.latest.getTime == 'function' )
1442
+ this.latest = options.latest.getTime();
1443
+ else
1444
+ this.latest = this.conv.parse( options.latest.toString() );
1445
+ }
1446
+
1447
+ this.lX = options.labelDismiss || 'X';
1448
+ this.lY = options.labelYear || 'Year';
1449
+ this.lO = options.labelTimeZone || 'Time Zone';
1450
+
1451
+ // Infer what we can about what to display from the format.
1452
+
1453
+ var i;
1454
+ var t;
1455
+ var lab;
1456
+ var shownFields = 0;
1457
+ var format = this.conv.fmt;
1458
+
1459
+ if ( typeof options.askEra != 'undefined' )
1460
+ this.askEra = options.askEra;
1461
+ else
1462
+ this.askEra = (format.indexOf('%B')>=0) || (format.indexOf('%C')>=0) || (format.indexOf('%E')>=0);
1463
+ var askYear = (format.indexOf('%Y')>=0) || (format.indexOf('%y')>=0) || (format.indexOf('%Z')>=0) || (format.indexOf('%z')>=0);
1464
+ var askMonth = (format.indexOf('%b')>=0) || (format.indexOf('%c')>=0) || (format.indexOf('%M')>=0) || (format.indexOf('%m')>=0);
1465
+ var askDoM = (format.indexOf('%D')>=0) || (format.indexOf('%d')>=0) || (format.indexOf('%e')>=0);
1466
+ var askDate = askYear || askMonth || askDoM;
1467
+ this.twelveHr = (format.indexOf('%h')>=0) || (format.indexOf('%I')>=0) || (format.indexOf('%l')>=0) || (format.indexOf('%r')>=0);
1468
+ var askHour = this.twelveHr || (format.indexOf('%H')>=0) || (format.indexOf('%k')>=0) || (format.indexOf('%T')>=0);
1469
+ var askMinute = (format.indexOf('%i')>=0) || (format.indexOf('%r')>=0) || (format.indexOf('%T')>=0);
1470
+ var askSec = ( (format.indexOf('%r')>=0) || (format.indexOf('%S')>=0) || (format.indexOf('%s')>=0) || (format.indexOf('%T')>=0) );
1471
+ if ( askSec && ( typeof options.askSecond != 'undefined' ) )
1472
+ askSec = options.askSecond;
1473
+ var askOff = ( (format.indexOf('%#')>=0) || (format.indexOf('%+')>=0) || (format.indexOf('%-')>=0) || (format.indexOf('%:')>=0) || (format.indexOf('%;')>=0) || (format.indexOf('%<')>=0) || (format.indexOf('%>')>=0) || (format.indexOf('%@')>=0) );
1474
+ var askTime = askHour || askMinute || askSec || askOff;
1475
+
1476
+ if ( askOff )
1477
+ this.oConv = new AnyTime.Converter( { format: options.formatUtcOffset ||
1478
+ format.match(/\S*%[-+:;<>#@]\S*/g).join(' ') } );
1479
+
1480
+ // Create the picker HTML and add it to the page.
1481
+ // Popup pickers will be moved to the end of the body
1482
+ // once the entire page has loaded.
1483
+
1484
+ this.inp = $(document.getElementById(id)); // avoids ID-vs-pseudo-selector probs like id="foo:bar"
1485
+ this.div = $( '<div class="AnyTime-win AnyTime-pkr ui-widget ui-widget-content ui-corner-all" style="width:0;height:0" id="' + this.id + '" aria-live="off"/>' );
1486
+ this.inp.after(this.div);
1487
+ this.wMinW = this.div.outerWidth(!$.browser.safari);
1488
+ this.wMinH = this.div.AnyTime_height(true);
1489
+ this.hTitle = $( '<h5 class="AnyTime-hdr ui-widget-header ui-corner-top"/>' );
1490
+ this.div.append( this.hTitle );
1491
+ this.dB = $( '<div class="AnyTime-body" style="width:0;height:0"/>' );
1492
+ this.div.append( this.dB );
1493
+ this.bMinW = this.dB.outerWidth(true);
1494
+ this.bMinH = this.dB.AnyTime_height(true);
1495
+
1496
+ if ( options.hideInput )
1497
+ this.inp.css({border:0,height:'1px',margin:0,padding:0,width:'1px'});
1498
+
1499
+ // Add dismiss box to title (if popup)
1500
+
1501
+ t = null;
1502
+ var xDiv = null;
1503
+ if ( this.pop )
1504
+ {
1505
+ xDiv = $( '<div class="AnyTime-x-btn ui-state-default">'+this.lX+'</div>' );
1506
+ this.hTitle.append( xDiv );
1507
+ xDiv.click(function(e){_this.dismiss(e);});
1508
+ }
1509
+
1510
+ // date (calendar) portion
1511
+
1512
+ lab = '';
1513
+ if ( askDate )
1514
+ {
1515
+ this.dD = $( '<div class="AnyTime-date" style="width:0;height:0"/>' );
1516
+ this.dB.append( this.dD );
1517
+ this.dMinW = this.dD.outerWidth(true);
1518
+ this.dMinH = this.dD.AnyTime_height(true);
1519
+
1520
+ if ( askYear )
1521
+ {
1522
+ this.yLab = $('<h6 class="AnyTime-lbl AnyTime-lbl-yr">' + this.lY + '</h6>');
1523
+ this.dD.append( this.yLab );
1524
+
1525
+ this.dY = $( '<ul class="AnyTime-yrs ui-helper-reset" />' );
1526
+ this.dD.append( this.dY );
1527
+
1528
+ this.yPast = this.btn(this.dY,'&lt;',this.newYear,['yrs-past'],'- '+this.lY);
1529
+ this.yPrior = this.btn(this.dY,'1',this.newYear,['yr-prior'],'-1 '+this.lY);
1530
+ this.yCur = this.btn(this.dY,'2',this.newYear,['yr-cur'],this.lY);
1531
+ this.yCur.removeClass('ui-state-default');
1532
+ this.yCur.addClass('AnyTime-cur-btn ui-state-default ui-state-highlight');
1533
+
1534
+ this.yNext = this.btn(this.dY,'3',this.newYear,['yr-next'],'+1 '+this.lY);
1535
+ this.yAhead = this.btn(this.dY,'&gt;',this.newYear,['yrs-ahead'],'+ '+this.lY);
1536
+
1537
+ shownFields++;
1538
+
1539
+ } // if ( askYear )
1540
+
1541
+ if ( askMonth )
1542
+ {
1543
+ lab = options.labelMonth || 'Month';
1544
+ this.hMo = $( '<h6 class="AnyTime-lbl AnyTime-lbl-month">' + lab + '</h6>' );
1545
+ this.dD.append( this.hMo );
1546
+ this.dMo = $('<ul class="AnyTime-mons" />');
1547
+ this.dD.append(this.dMo);
1548
+ for ( i = 0 ; i < 12 ; i++ )
1549
+ {
1550
+ var mBtn = this.btn( this.dMo, this.conv.mAbbr[i],
1551
+ function( event )
1552
+ {
1553
+ var elem = $(event.target);
1554
+ if ( elem.hasClass("AnyTime-out-btn") )
1555
+ return;
1556
+ var mo = event.target.AnyTime_month;
1557
+ var t = new Date(this.time.getTime());
1558
+ if ( t.getDate() > __daysIn[mo] )
1559
+ t.setDate(__daysIn[mo])
1560
+ t.setMonth(mo);
1561
+ this.set(t);
1562
+ this.upd(elem);
1563
+ },
1564
+ ['mon','mon'+String(i+1)], lab+' '+this.conv.mNames[i] );
1565
+ mBtn[0].AnyTime_month = i;
1566
+ }
1567
+ shownFields++;
1568
+ }
1569
+
1570
+ if ( askDoM )
1571
+ {
1572
+ lab = options.labelDayOfMonth || 'Day of Month';
1573
+ this.hDoM = $('<h6 class="AnyTime-lbl AnyTime-lbl-dom">' + lab + '</h6>' );
1574
+ this.dD.append( this.hDoM );
1575
+ this.dDoM = $( '<table border="0" cellpadding="0" cellspacing="0" class="AnyTime-dom-table"/>' );
1576
+ this.dD.append( this.dDoM );
1577
+ t = $( '<thead class="AnyTime-dom-head"/>' );
1578
+ this.dDoM.append(t);
1579
+ var tr = $( '<tr class="AnyTime-dow"/>' );
1580
+ t.append(tr);
1581
+ for ( i = 0 ; i < 7 ; i++ )
1582
+ tr.append( '<th class="AnyTime-dow AnyTime-dow'+String(i+1)+'">'+this.conv.dAbbr[(this.fDOW+i)%7]+'</th>' );
1583
+
1584
+ var tbody = $( '<tbody class="AnyTime-dom-body" />' );
1585
+ this.dDoM.append(tbody);
1586
+ for ( var r = 0 ; r < 6 ; r++ )
1587
+ {
1588
+ tr = $( '<tr class="AnyTime-wk AnyTime-wk'+String(r+1)+'"/>' );
1589
+ tbody.append(tr);
1590
+ for ( i = 0 ; i < 7 ; i++ )
1591
+ this.btn( tr, 'x',
1592
+ function( event )
1593
+ {
1594
+ var elem = $(event.target);
1595
+ if ( elem.hasClass("AnyTime-out-btn") )
1596
+ return;
1597
+ var dom = Number(elem.html());
1598
+ if ( dom )
1599
+ {
1600
+ var t = new Date(this.time.getTime());
1601
+ t.setDate(dom);
1602
+ this.set(t);
1603
+ this.upd(elem);
1604
+ }
1605
+ },
1606
+ ['dom'], lab );
1607
+ }
1608
+ shownFields++;
1609
+
1610
+ } // if ( askDoM )
1611
+
1612
+ } // if ( askDate )
1613
+
1614
+ // time portion
1615
+
1616
+ if ( askTime )
1617
+ {
1618
+ var tensDiv, onesDiv;
1619
+
1620
+ this.dT = $('<div class="AnyTime-time" style="width:0;height:0" />');
1621
+ this.dB.append(this.dT);
1622
+ this.tMinW = this.dT.outerWidth(true);
1623
+ this.tMinH = this.dT.AnyTime_height(true);
1624
+
1625
+ if ( askHour )
1626
+ {
1627
+ this.dH = $('<div class="AnyTime-hrs"/>');
1628
+ this.dT.append(this.dH);
1629
+
1630
+ lab = options.labelHour || 'Hour';
1631
+ this.dH.append( $('<h6 class="AnyTime-lbl AnyTime-lbl-hr">'+lab+'</h6>') );
1632
+ var amDiv = $('<ul class="AnyTime-hrs-am"/>');
1633
+ this.dH.append( amDiv );
1634
+ var pmDiv = $('<ul class="AnyTime-hrs-pm"/>');
1635
+ this.dH.append( pmDiv );
1636
+
1637
+ for ( i = 0 ; i < 12 ; i++ )
1638
+ {
1639
+ if ( this.twelveHr )
1640
+ {
1641
+ if ( i == 0 )
1642
+ t = '12am';
1643
+ else
1644
+ t = String(i)+'am';
1645
+ }
1646
+ else
1647
+ t = AnyTime.pad(i,2);
1648
+
1649
+ this.btn( amDiv, t, this.newHour,['hr','hr'+String(i)],lab+' '+t);
1650
+
1651
+ if ( this.twelveHr )
1652
+ {
1653
+ if ( i == 0 )
1654
+ t = '12pm';
1655
+ else
1656
+ t = String(i)+'pm';
1657
+ }
1658
+ else
1659
+ t = i+12;
1660
+
1661
+ this.btn( pmDiv, t, this.newHour,['hr','hr'+String(i+12)],lab+' '+t);
1662
+ }
1663
+
1664
+ shownFields++;
1665
+
1666
+ } // if ( askHour )
1667
+
1668
+ if ( askMinute )
1669
+ {
1670
+ this.dM = $('<div class="AnyTime-mins"/>');
1671
+ this.dT.append(this.dM);
1672
+
1673
+ lab = options.labelMinute || 'Minute';
1674
+ this.dM.append( $('<h6 class="AnyTime-lbl AnyTime-lbl-min">'+lab+'</h6>') );
1675
+ tensDiv = $('<ul class="AnyTime-mins-tens"/>');
1676
+ this.dM.append(tensDiv);
1677
+
1678
+ for ( i = 0 ; i < 6 ; i++ )
1679
+ this.btn( tensDiv, i,
1680
+ function( event )
1681
+ {
1682
+ var elem = $(event.target);
1683
+ if ( elem.hasClass("AnyTime-out-btn") )
1684
+ return;
1685
+ var t = new Date(this.time.getTime());
1686
+ t.setMinutes( (Number(elem.text())*10) + (this.time.getMinutes()%10) );
1687
+ this.set(t);
1688
+ this.upd(elem);
1689
+ },
1690
+ ['min-ten','min'+i+'0'], lab+' '+i+'0' );
1691
+ for ( ; i < 12 ; i++ )
1692
+ this.btn( tensDiv, '&#160;', $.noop, ['min-ten','min'+i+'0'], lab+' '+i+'0' ).addClass('AnyTime-min-ten-btn-empty ui-state-default ui-state-disabled');
1693
+
1694
+ onesDiv = $('<ul class="AnyTime-mins-ones"/>');
1695
+ this.dM.append(onesDiv);
1696
+ for ( i = 0 ; i < 10 ; i++ )
1697
+ this.btn( onesDiv, i,
1698
+ function( event )
1699
+ {
1700
+ var elem = $(event.target);
1701
+ if ( elem.hasClass("AnyTime-out-btn") )
1702
+ return;
1703
+ var t = new Date(this.time.getTime());
1704
+ t.setMinutes( (Math.floor(this.time.getMinutes()/10)*10)+Number(elem.text()) );
1705
+ this.set(t);
1706
+ this.upd(elem);
1707
+ },
1708
+ ['min-one','min'+i], lab+' '+i );
1709
+ for ( ; i < 12 ; i++ )
1710
+ this.btn( onesDiv, '&#160;', $.noop, ['min-one','min'+i+'0'], lab+' '+i ).addClass('AnyTime-min-one-btn-empty ui-state-default ui-state-disabled');
1711
+
1712
+ shownFields++;
1713
+
1714
+ } // if ( askMinute )
1715
+
1716
+ if ( askSec )
1717
+ {
1718
+ this.dS = $('<div class="AnyTime-secs"/>');
1719
+ this.dT.append(this.dS);
1720
+ lab = options.labelSecond || 'Second';
1721
+ this.dS.append( $('<h6 class="AnyTime-lbl AnyTime-lbl-sec">'+lab+'</h6>') );
1722
+ tensDiv = $('<ul class="AnyTime-secs-tens"/>');
1723
+ this.dS.append(tensDiv);
1724
+
1725
+ for ( i = 0 ; i < 6 ; i++ )
1726
+ this.btn( tensDiv, i,
1727
+ function( event )
1728
+ {
1729
+ var elem = $(event.target);
1730
+ if ( elem.hasClass("AnyTime-out-btn") )
1731
+ return;
1732
+ var t = new Date(this.time.getTime());
1733
+ t.setSeconds( (Number(elem.text())*10) + (this.time.getSeconds()%10) );
1734
+ this.set(t);
1735
+ this.upd(elem);
1736
+ },
1737
+ ['sec-ten','sec'+i+'0'], lab+' '+i+'0' );
1738
+ for ( ; i < 12 ; i++ )
1739
+ this.btn( tensDiv, '&#160;', $.noop, ['sec-ten','sec'+i+'0'], lab+' '+i+'0' ).addClass('AnyTime-sec-ten-btn-empty ui-state-default ui-state-disabled');
1740
+
1741
+ onesDiv = $('<ul class="AnyTime-secs-ones"/>');
1742
+ this.dS.append(onesDiv);
1743
+ for ( i = 0 ; i < 10 ; i++ )
1744
+ this.btn( onesDiv, i,
1745
+ function( event )
1746
+ {
1747
+ var elem = $(event.target);
1748
+ if ( elem.hasClass("AnyTime-out-btn") )
1749
+ return;
1750
+ var t = new Date(this.time.getTime());
1751
+ t.setSeconds( (Math.floor(this.time.getSeconds()/10)*10) + Number(elem.text()) );
1752
+ this.set(t);
1753
+ this.upd(elem);
1754
+ },
1755
+ ['sec-one','sec'+i], lab+' '+i );
1756
+ for ( ; i < 12 ; i++ )
1757
+ this.btn( onesDiv, '&#160;', $.noop, ['sec-one','sec'+i+'0'], lab+' '+i ).addClass('AnyTime-sec-one-btn-empty ui-state-default ui-state-disabled');
1758
+
1759
+ shownFields++;
1760
+
1761
+ } // if ( askSec )
1762
+
1763
+ if ( askOff )
1764
+ {
1765
+ this.dO = $('<div class="AnyTime-offs" />');
1766
+ this.dT.append(this.dO);
1767
+ this.oMinW = this.dO.outerWidth(true);
1768
+
1769
+ this.oLab = $('<h6 class="AnyTime-lbl AnyTime-lbl-off">' + this.lO + '</h6>');
1770
+ this.dO.append( this.oLab );
1771
+
1772
+ var offDiv = $('<ul class="AnyTime-off-list ui-helper-reset" />');
1773
+ this.dO.append(offDiv);
1774
+
1775
+ this.oCur = this.btn(offDiv,'',this.newOffset,['off','off-cur'],lab);
1776
+ this.oCur.removeClass('ui-state-default');
1777
+ this.oCur.addClass('AnyTime-cur-btn ui-state-default ui-state-highlight');
1778
+ this.oCur.css({overflow:"hidden"});
1779
+
1780
+ this.oSel = this.btn(offDiv,'&#177;',this.newOffset,['off','off-select'],'+/- '+this.lO);
1781
+ this.oListMinW = this.oCur.outerWidth(true)+this.oSel.outerWidth(true);
1782
+
1783
+ shownFields++;
1784
+ }
1785
+
1786
+ } // if ( askTime )
1787
+
1788
+ // Set the title. If a title option has been specified, use it.
1789
+ // Otherwise, determine a worthy title based on which (and how many)
1790
+ // format fields have been specified.
1791
+
1792
+ if ( options.labelTitle )
1793
+ this.hTitle.append( options.labelTitle );
1794
+ else if ( shownFields > 1 )
1795
+ this.hTitle.append( 'Select a '+(askDate?(askTime?'Date and Time':'Date'):'Time') );
1796
+ else
1797
+ this.hTitle.append( 'Select' );
1798
+
1799
+
1800
+ // Initialize the picker's date/time value.
1801
+
1802
+ try
1803
+ {
1804
+ this.time = this.conv.parse(this.inp.val());
1805
+ this.offMin = this.conv.getUtcParseOffsetCaptured();
1806
+ this.offSI = this.conv.getUtcParseOffsetSubIndex();
1807
+ }
1808
+ catch ( e )
1809
+ {
1810
+ this.time = new Date();
1811
+ }
1812
+ this.lastAjax = this.time;
1813
+
1814
+
1815
+ // If this is a popup picker, hide it until needed.
1816
+
1817
+ if ( this.pop )
1818
+ {
1819
+ this.div.hide();
1820
+ if ( __iframe )
1821
+ __iframe.hide();
1822
+ this.div.css('position','absolute');
1823
+ }
1824
+
1825
+ // Setup event listeners for the input and resize listeners for
1826
+ // the picker. Add the picker to the instances list (which is used
1827
+ // to hide pickers if the user clicks off of them).
1828
+
1829
+ this.inp.blur( this.hBlur =
1830
+ function(e)
1831
+ {
1832
+ _this.inpBlur(e);
1833
+ } );
1834
+
1835
+ this.inp.click( this.hClick =
1836
+ function(e)
1837
+ {
1838
+ _this.showPkr(e);
1839
+ } );
1840
+
1841
+ this.inp.focus( this.hFocus =
1842
+ function(e)
1843
+ {
1844
+ if ( _this.lostFocus )
1845
+ _this.showPkr(e);
1846
+ _this.lostFocus = false;
1847
+ } );
1848
+
1849
+ this.inp.keydown( this.hKeydown =
1850
+ function(e)
1851
+ {
1852
+ _this.key(e);
1853
+ } );
1854
+
1855
+ this.inp.keypress( this.hKeypress =
1856
+ function(e)
1857
+ {
1858
+ if ( $.browser.opera && _this.denyTab )
1859
+ e.preventDefault();
1860
+ } );
1861
+
1862
+ this.div.click(
1863
+ function(e)
1864
+ {
1865
+ _this.lostFocus = false;
1866
+ _this.inp.focus();
1867
+ } );
1868
+
1869
+ $(window).resize(
1870
+ function(e)
1871
+ {
1872
+ _this.pos(e);
1873
+ } );
1874
+
1875
+ if ( __initialized )
1876
+ this.onReady();
1877
+
1878
+ }, // initialize()
1879
+
1880
+
1881
+ //---------------------------------------------------------------------
1882
+ // .ajax() notifies the server of a value change using Ajax.
1883
+ //---------------------------------------------------------------------
1884
+
1885
+ ajax: function()
1886
+ {
1887
+ if ( this.ajaxOpts && ( this.time.getTime() != this.lastAjax.getTime() ) )
1888
+ {
1889
+ try
1890
+ {
1891
+ var opts = jQuery.extend( {}, this.ajaxOpts );
1892
+ if ( typeof opts.data == 'object' )
1893
+ opts.data[this.inp[0].name||this.inp[0].id] = this.inp.val();
1894
+ else
1895
+ {
1896
+ var opt = (this.inp[0].name||this.inp[0].id) + '=' + encodeURI(this.inp.val());
1897
+ if ( opts.data )
1898
+ opts.data += '&' + opt;
1899
+ else
1900
+ opts.data = opt;
1901
+ }
1902
+ $.ajax( opts );
1903
+ this.lastAjax = this.time;
1904
+ }
1905
+ catch( e )
1906
+ {
1907
+ }
1908
+ }
1909
+ return;
1910
+
1911
+ }, // .ajax()
1912
+
1913
+ //---------------------------------------------------------------------
1914
+ // .askOffset() is called by this.newOffset() when the UTC offset or
1915
+ // +- selection button is clicked.
1916
+ //---------------------------------------------------------------------
1917
+
1918
+ askOffset: function( event )
1919
+ {
1920
+ if ( ! this.oDiv )
1921
+ {
1922
+ this.makeCloak();
1923
+
1924
+ this.oDiv = $('<div class="AnyTime-win AnyTime-off-selector ui-widget ui-widget-content ui-corner-all" style="position:absolute" />');
1925
+ this.div.append(this.oDiv);
1926
+
1927
+ // the order here (HDR,BODY,XDIV,TITLE) is important for width calcluation:
1928
+ var title = $('<h5 class="AnyTime-hdr AnyTime-hdr-off-selector ui-widget-header ui-corner-top" />');
1929
+ this.oDiv.append( title );
1930
+ this.oBody = $('<div class="AnyTime-body AnyTime-body-off-selector" style="overflow:auto;white-space:nowrap" />');
1931
+ this.oDiv.append( this.oBody );
1932
+ var oBHS = this.oBody.AnyTime_height(true); // body spacing
1933
+ var oBWS = this.oBody.AnyTime_width(true);
1934
+ var oTWS = title.AnyTime_width(true);
1935
+
1936
+ var xDiv = $('<div class="AnyTime-x-btn ui-state-default">'+this.lX+'</div>');
1937
+ title.append(xDiv);
1938
+ xDiv.click(function(e){_this.dismissODiv(e);});
1939
+ title.append( this.lO );
1940
+ if ( __msie6 || __msie7 ) // IE bugs!
1941
+ title.width(String(this.lO.length*0.8)+"em");
1942
+ var oBW = title.AnyTime_width(true) - oBWS; // initial body width
1943
+
1944
+ var cont = $('<ul class="AnyTime-off-off" />' );
1945
+ var last = null;
1946
+ this.oBody.append(cont);
1947
+ var useSubIndex = (this.oConv.fmt.indexOf('%@')>=0);
1948
+ var btnW = 0; // determine uniform button width
1949
+ if ( AnyTime.utcLabel )
1950
+ for ( var o = -720 ; o < 720 ; o++ )
1951
+ if ( AnyTime.utcLabel[o] )
1952
+ {
1953
+ this.oConv.setUtcFormatOffsetAlleged(o);
1954
+ for ( var i = 0; i < AnyTime.utcLabel[o].length; i++ )
1955
+ {
1956
+ this.oConv.setUtcFormatOffsetSubIndex(i);
1957
+ last = this.btn( cont, this.oConv.format(this.time), this.newOPos, ['off-off'], o );
1958
+ last[0].AnyTime_offMin = o;
1959
+ last[0].AnyTime_offSI = i;
1960
+ var w = last.width();
1961
+ if ( w > btnW )
1962
+ btnW = w;
1963
+ if ( ! useSubIndex )
1964
+ break; // for
1965
+ }
1966
+ }
1967
+
1968
+ if ( last )
1969
+ last.addClass('AnyTime-off-off-last-btn');
1970
+
1971
+ // compute optimal width
1972
+
1973
+ this.oBody.find('.AnyTime-off-off-btn').width(btnW); // set uniform button width
1974
+ if ( last )
1975
+ {
1976
+ var lW = last.AnyTime_width(true);
1977
+ if ( lW > oBW )
1978
+ oBW = lW+1; // expand body to hold buttons
1979
+ }
1980
+ this.oBody.width(oBW);
1981
+ oBW = this.oBody.AnyTime_width(true);
1982
+ this.oDiv.width( oBW );
1983
+ if ( __msie6 || __msie7 ) // IE bugs!
1984
+ title.width( oBW - oTWS );
1985
+
1986
+ // compute optimal height
1987
+
1988
+ var oH = this.oDiv.AnyTime_height(true);
1989
+ var oHmax = this.div.height() * 0.75;
1990
+ if ( oH > oHmax )
1991
+ {
1992
+ oH = oHmax;
1993
+ this.oBody.height(oH-(title.AnyTime_height(true)+oBHS));
1994
+ this.oBody.width(this.oBody.width()+20); // add nominal px for scrollbar
1995
+ this.oDiv.width(this.oDiv.width()+20);
1996
+ if ( __msie6 || __msie7 ) // IE bugs!
1997
+ title.width( this.oBody.AnyTime_width(true) - oTWS );
1998
+ }
1999
+ if ( ! __msie7 ) // IE7 bug!
2000
+ this.oDiv.height(String(oH)+'px');
2001
+
2002
+ } // if ( ! this.oDiv )
2003
+ else
2004
+ {
2005
+ this.cloak.show();
2006
+ this.oDiv.show();
2007
+ }
2008
+ this.pos(event);
2009
+ this.updODiv(null);
2010
+
2011
+ var f = this.oDiv.find('.AnyTime-off-off-btn.AnyTime-cur-btn:first');
2012
+ if ( ! f.length )
2013
+ f = this.oDiv.find('.AnyTime-off-off-btn:first');
2014
+ this.setFocus( f );
2015
+
2016
+ }, // .askOffset()
2017
+
2018
+ //---------------------------------------------------------------------
2019
+ // .askYear() is called by this.newYear() when the yPast or yAhead
2020
+ // button is clicked.
2021
+ //---------------------------------------------------------------------
2022
+
2023
+ askYear: function( event )
2024
+ {
2025
+ if ( ! this.yDiv )
2026
+ {
2027
+ this.makeCloak();
2028
+
2029
+ this.yDiv = $('<div class="AnyTime-win AnyTime-yr-selector ui-widget ui-widget-content ui-corner-all" style="position:absolute" />');
2030
+ this.div.append(this.yDiv);
2031
+
2032
+ var title = $('<h5 class="AnyTime-hdr AnyTime-hdr-yr-selector ui-widget-header ui-corner-top" />');
2033
+ this.yDiv.append( title );
2034
+
2035
+ var xDiv = $('<div class="AnyTime-x-btn ui-state-default">'+this.lX+'</div>');
2036
+ title.append(xDiv);
2037
+ xDiv.click(function(e){_this.dismissYDiv(e);});
2038
+
2039
+ title.append( this.lY );
2040
+
2041
+ var yBody = $('<div class="AnyTime-body AnyTime-body-yr-selector" />');
2042
+ var yW = yBody.AnyTime_width(true);
2043
+ var yH = 0;
2044
+ this.yDiv.append( yBody );
2045
+
2046
+ cont = $('<ul class="AnyTime-yr-mil" />' );
2047
+ yBody.append(cont);
2048
+ this.y0XXX = this.btn( cont, 0, this.newYPos,['mil','mil0'],this.lY+' '+0+'000');
2049
+ for ( i = 1; i < 10 ; i++ )
2050
+ this.btn( cont, i, this.newYPos,['mil','mil'+i],this.lY+' '+i+'000');
2051
+ yW += cont.AnyTime_width(true);
2052
+ if ( yH < cont.AnyTime_height(true) )
2053
+ yH = cont.AnyTime_height(true);
2054
+
2055
+ cont = $('<ul class="AnyTime-yr-cent" />' );
2056
+ yBody.append(cont);
2057
+ for ( i = 0 ; i < 10 ; i++ )
2058
+ this.btn( cont, i, this.newYPos,['cent','cent'+i],this.lY+' '+i+'00');
2059
+ yW += cont.AnyTime_width(true);
2060
+ if ( yH < cont.AnyTime_height(true) )
2061
+ yH = cont.AnyTime_height(true);
2062
+
2063
+ cont = $('<ul class="AnyTime-yr-dec" />');
2064
+ yBody.append(cont);
2065
+ for ( i = 0 ; i < 10 ; i++ )
2066
+ this.btn( cont, i, this.newYPos,['dec','dec'+i],this.lY+' '+i+'0');
2067
+ yW += cont.AnyTime_width(true);
2068
+ if ( yH < cont.AnyTime_height(true) )
2069
+ yH = cont.AnyTime_height(true);
2070
+
2071
+ cont = $('<ul class="AnyTime-yr-yr" />');
2072
+ yBody.append(cont);
2073
+ for ( i = 0 ; i < 10 ; i++ )
2074
+ this.btn( cont, i, this.newYPos,['yr','yr'+i],this.lY+' '+i );
2075
+ yW += cont.AnyTime_width(true);
2076
+ if ( yH < cont.AnyTime_height(true) )
2077
+ yH = cont.AnyTime_height(true);
2078
+
2079
+ if ( this.askEra )
2080
+ {
2081
+ cont = $('<ul class="AnyTime-yr-era" />' );
2082
+ yBody.append(cont);
2083
+
2084
+ this.btn( cont, this.conv.eAbbr[0],
2085
+ function( event )
2086
+ {
2087
+ var t = new Date(this.time.getTime());
2088
+ var year = t.getFullYear();
2089
+ if ( year > 0 )
2090
+ t.setFullYear(0-year);
2091
+ this.set(t);
2092
+ this.updYDiv($(event.target));
2093
+ },
2094
+ ['era','bce'], this.conv.eAbbr[0] );
2095
+
2096
+ this.btn( cont, this.conv.eAbbr[1],
2097
+ function( event )
2098
+ {
2099
+ var t = new Date(this.time.getTime());
2100
+ var year = t.getFullYear();
2101
+ if ( year < 0 )
2102
+ t.setFullYear(0-year);
2103
+ this.set(t);
2104
+ this.updYDiv($(event.target));
2105
+ },
2106
+ ['era','ce'], this.conv.eAbbr[1] );
2107
+
2108
+ yW += cont.AnyTime_width(true);
2109
+ if ( yH < cont.AnyTime_height(true) )
2110
+ yH = cont.AnyTime_height(true);
2111
+
2112
+ } // if ( this.askEra )
2113
+
2114
+ if ( $.browser.msie ) // IE8+ThemeUI bug!
2115
+ yW += 1;
2116
+ else if ( $.browser.safari ) // Safari small-text bug!
2117
+ yW += 2;
2118
+ yH += yBody.AnyTime_height(true);
2119
+ yBody.css('width',String(yW)+'px');
2120
+ if ( ! __msie7 ) // IE7 bug!
2121
+ yBody.css('height',String(yH)+'px');
2122
+ if ( __msie6 || __msie7 ) // IE bugs!
2123
+ title.width(yBody.outerWidth(true));
2124
+ yH += title.AnyTime_height(true);
2125
+ if ( title.AnyTime_width(true) > yW )
2126
+ yW = title.AnyTime_width(true);
2127
+ this.yDiv.css('width',String(yW)+'px');
2128
+ if ( ! __msie7 ) // IE7 bug!
2129
+ this.yDiv.css('height',String(yH)+'px');
2130
+
2131
+ } // if ( ! this.yDiv )
2132
+ else
2133
+ {
2134
+ this.cloak.show();
2135
+ this.yDiv.show();
2136
+ }
2137
+ this.pos(event);
2138
+ this.updYDiv(null);
2139
+ this.setFocus( this.yDiv.find('.AnyTime-yr-btn.AnyTime-cur-btn:first') );
2140
+
2141
+ }, // .askYear()
2142
+
2143
+ //---------------------------------------------------------------------
2144
+ // .inpBlur() is called when a picker's input loses focus to dismiss
2145
+ // the popup. A 1/3 second delay is necessary to restore focus if
2146
+ // the div is clicked (shorter delays don't always work!) To prevent
2147
+ // problems cause by scrollbar focus (except in FF), focus is
2148
+ // force-restored if the offset div is visible.
2149
+ //---------------------------------------------------------------------
2150
+
2151
+ inpBlur: function(event)
2152
+ {
2153
+ if ( this.oDiv && this.oDiv.is(":visible") )
2154
+ {
2155
+ _this.inp.focus();
2156
+ return;
2157
+ }
2158
+ this.lostFocus = true;
2159
+ setTimeout(
2160
+ function()
2161
+ {
2162
+ if ( _this.lostFocus )
2163
+ {
2164
+ _this.div.find('.AnyTime-focus-btn').removeClass('AnyTime-focus-btn ui-state-focus');
2165
+ if ( _this.pop )
2166
+ _this.dismiss(event);
2167
+ else
2168
+ _this.ajax();
2169
+ }
2170
+ }, 334 );
2171
+ },
2172
+
2173
+ //---------------------------------------------------------------------
2174
+ // .btn() is called by AnyTime.picker() to create a <div> element
2175
+ // containing an <a> element. The elements are given appropriate
2176
+ // classes based on the specified "classes" (an array of strings).
2177
+ // The specified "text" and "title" are used for the <a> element.
2178
+ // The "handler" is bound to click events for the <div>, which will
2179
+ // catch bubbling clicks from the <a> as well. The button is
2180
+ // appended to the specified parent (jQuery), and the <div> jQuery
2181
+ // is returned.
2182
+ //---------------------------------------------------------------------
2183
+
2184
+ btn: function( parent, text, handler, classes, title )
2185
+ {
2186
+ var tagName = ( (parent[0].nodeName.toLowerCase()=='ul')?'li':'td');
2187
+ var div$ = '<' + tagName +
2188
+ ' class="AnyTime-btn';
2189
+ for ( var i = 0 ; i < classes.length ; i++ )
2190
+ div$ += ' AnyTime-' + classes[i] + '-btn';
2191
+ var div = $( div$ + ' ui-state-default">' + text + '</' + tagName + '>' );
2192
+ parent.append(div);
2193
+ div.AnyTime_title = title;
2194
+
2195
+ div.click(
2196
+ function(e)
2197
+ {
2198
+ // bind the handler to the picker so "this" is correct
2199
+ _this.tempFunc = handler;
2200
+ _this.tempFunc(e);
2201
+ });
2202
+ div.dblclick(
2203
+ function(e)
2204
+ {
2205
+ var elem = $(this);
2206
+ if ( elem.is('.AnyTime-off-off-btn') )
2207
+ _this.dismissODiv(e);
2208
+ else if ( elem.is('.AnyTime-mil-btn') || elem.is('.AnyTime-cent-btn') || elem.is('.AnyTime-dec-btn') || elem.is('.AnyTime-yr-btn') || elem.is('.AnyTime-era-btn') )
2209
+ _this.dismissYDiv(e);
2210
+ else if ( _this.pop )
2211
+ _this.dismiss(e);
2212
+ });
2213
+ return div;
2214
+
2215
+ }, // .btn()
2216
+
2217
+ //---------------------------------------------------------------------
2218
+ // .cleanup() destroys the DOM events and elements associated with
2219
+ // the picker so it can be deleted.
2220
+ //---------------------------------------------------------------------
2221
+
2222
+ cleanup: function(event)
2223
+ {
2224
+ this.inp.unbind('blur',this.hBlur);
2225
+ this.inp.unbind('click',this.hClick);
2226
+ this.inp.unbind('focus',this.hFocus);
2227
+ this.inp.unbind('keydown',this.hKeydown);
2228
+ this.inp.unbind('keypress',this.hKeypress);
2229
+ this.div.remove();
2230
+ },
2231
+
2232
+ //---------------------------------------------------------------------
2233
+ // .dismiss() dismisses a popup picker.
2234
+ //---------------------------------------------------------------------
2235
+
2236
+ dismiss: function(event)
2237
+ {
2238
+ this.ajax();
2239
+ if ( __iframe )
2240
+ __iframe.hide();
2241
+ if ( this.yDiv )
2242
+ this.dismissYDiv();
2243
+ if ( this.oDiv )
2244
+ this.dismissODiv();
2245
+ this.div.hide();
2246
+ this.lostFocus = true;
2247
+ },
2248
+
2249
+ //---------------------------------------------------------------------
2250
+ // .dismissODiv() dismisses the UTC offset selector popover.
2251
+ //---------------------------------------------------------------------
2252
+
2253
+ dismissODiv: function(event)
2254
+ {
2255
+ this.oDiv.hide();
2256
+ this.cloak.hide();
2257
+ this.setFocus(this.oCur);
2258
+ },
2259
+
2260
+ //---------------------------------------------------------------------
2261
+ // .dismissYDiv() dismisses the date selector popover.
2262
+ //---------------------------------------------------------------------
2263
+
2264
+ dismissYDiv: function(event)
2265
+ {
2266
+ this.yDiv.hide();
2267
+ this.cloak.hide();
2268
+ this.setFocus(this.yCur);
2269
+ },
2270
+
2271
+ //---------------------------------------------------------------------
2272
+ // .setFocus() makes a specified psuedo-button appear to get focus.
2273
+ //---------------------------------------------------------------------
2274
+
2275
+ setFocus: function(btn)
2276
+ {
2277
+ if ( ! btn.hasClass('AnyTime-focus-btn') )
2278
+ {
2279
+ this.div.find('.AnyTime-focus-btn').removeClass('AnyTime-focus-btn ui-state-focus');
2280
+ this.fBtn = btn;
2281
+ btn.removeClass('ui-state-default ui-state-highlight');
2282
+ btn.addClass('AnyTime-focus-btn ui-state-default ui-state-highlight ui-state-focus');
2283
+ }
2284
+ if ( btn.hasClass('AnyTime-off-off-btn') )
2285
+ {
2286
+ var oBT = this.oBody.offset().top;
2287
+ var btnT = btn.offset().top;
2288
+ var btnH = btn.AnyTime_height(true);
2289
+ if ( btnT - btnH < oBT ) // move a page up
2290
+ this.oBody.scrollTop( btnT + this.oBody.scrollTop() - ( this.oBody.innerHeight() + oBT ) + ( btnH * 2 ) );
2291
+ else if ( btnT + btnH > oBT + this.oBody.innerHeight() ) // move a page down
2292
+ this.oBody.scrollTop( ( btnT + this.oBody.scrollTop() ) - ( oBT + btnH ) );
2293
+ }
2294
+ },
2295
+
2296
+ //---------------------------------------------------------------------
2297
+ // .key() is invoked when a user presses a key while the picker's
2298
+ // input has focus. A psuedo-button is considered "in focus" and an
2299
+ // appropriate action is performed according to the WAI-ARIA Authoring
2300
+ // Practices 1.0 for datepicker from
2301
+ // www.w3.org/TR/2009/WD-wai-aria-practices-20091215/#datepicker:
2302
+ //
2303
+ // * LeftArrow moves focus left, continued to previous week.
2304
+ // * RightArrow moves focus right, continued to next week.
2305
+ // * UpArrow moves focus to the same weekday in the previous week.
2306
+ // * DownArrow moves focus to same weekday in the next week.
2307
+ // * PageUp moves focus to same day in the previous month.
2308
+ // * PageDown moves focus to same day in the next month.
2309
+ // * Shift+Page Up moves focus to same day in the previous year.
2310
+ // * Shift+Page Down moves focus to same day in the next year.
2311
+ // * Home moves focus to the first day of the month.
2312
+ // * End moves focus to the last day of the month.
2313
+ // * Ctrl+Home moves focus to the first day of the year.
2314
+ // * Ctrl+End moves focus to the last day of the year.
2315
+ // * Esc closes a DatePicker that is opened as a Popup.
2316
+ //
2317
+ // The following actions (for multiple-date selection) are NOT
2318
+ // supported:
2319
+ // * Shift+Arrow performs continous selection.
2320
+ // * Ctrl+Space multiple selection of certain days.
2321
+ //
2322
+ // The authoring practices do not specify behavior for a time picker,
2323
+ // or for month-and-year pickers that do not have a day-of-the-month,
2324
+ // but AnyTime.picker uses the following behavior to be as consistent
2325
+ // as possible with the defined datepicker functionality:
2326
+ // * LeftArrow moves focus left or up to previous value or field.
2327
+ // * RightArrow moves focus right or down to next value or field.
2328
+ // * UpArrow moves focus up or left to previous value or field.
2329
+ // * DownArrow moves focus down or right to next value or field
2330
+ // * PageUp moves focus to the current value in the previous units
2331
+ // (for example, from ten-minutes to hours or one-minutes to
2332
+ // ten-minutes or months to years).
2333
+ // * PageDown moves focus to the current value in the next units
2334
+ // (for example, from hours to ten-minutes or ten-minutes to
2335
+ // one-minutes or years to months).
2336
+ // * Home moves the focus to the first unit button.
2337
+ // * End moves the focus to the last unit button.
2338
+ //
2339
+ // In addition, Tab and Shift+Tab move between units (including to/
2340
+ // from the Day-of-Month table) and also in/out of the picker.
2341
+ //
2342
+ // Because AnyTime.picker sets a value as soon as the button receives
2343
+ // focus, SPACE and ENTER are not needed (the WAI-ARIA guidelines use
2344
+ // them to select a value.
2345
+ //---------------------------------------------------------------------
2346
+
2347
+ key: function(event)
2348
+ {
2349
+ var mo;
2350
+ var t = null;
2351
+ var elem = this.div.find('.AnyTime-focus-btn');
2352
+ var key = event.keyCode || event.which;
2353
+ this.denyTab = true;
2354
+
2355
+ if ( key == 16 ) // Shift
2356
+ {
2357
+ }
2358
+ else if ( ( key == 10 ) || ( key == 13 ) || ( key == 27 ) ) // Enter & Esc
2359
+ {
2360
+ if ( this.oDiv && this.oDiv.is(':visible') )
2361
+ this.dismissODiv(event);
2362
+ else if ( this.yDiv && this.yDiv.is(':visible') )
2363
+ this.dismissYDiv(event);
2364
+ else if ( this.pop )
2365
+ this.dismiss(event);
2366
+ }
2367
+ else if ( ( key == 33 ) || ( ( key == 9 ) && event.shiftKey ) ) // PageUp & Shift+Tab
2368
+ {
2369
+ if ( this.fBtn.hasClass('AnyTime-off-off-btn') )
2370
+ {
2371
+ if ( key == 9 )
2372
+ this.dismissODiv(event);
2373
+ }
2374
+ else if ( this.fBtn.hasClass('AnyTime-mil-btn') )
2375
+ {
2376
+ if ( key == 9 )
2377
+ this.dismissYDiv(event);
2378
+ }
2379
+ else if ( this.fBtn.hasClass('AnyTime-cent-btn') )
2380
+ this.yDiv.find('.AnyTime-mil-btn.AnyTime-cur-btn').triggerHandler('click');
2381
+ else if ( this.fBtn.hasClass('AnyTime-dec-btn') )
2382
+ this.yDiv.find('.AnyTime-cent-btn.AnyTime-cur-btn').triggerHandler('click');
2383
+ else if ( this.fBtn.hasClass('AnyTime-yr-btn') )
2384
+ this.yDiv.find('.AnyTime-dec-btn.AnyTime-cur-btn').triggerHandler('click');
2385
+ else if ( this.fBtn.hasClass('AnyTime-era-btn') )
2386
+ this.yDiv.find('.AnyTime-yr-btn.AnyTime-cur-btn').triggerHandler('click');
2387
+ else if ( this.fBtn.parents('.AnyTime-yrs').length )
2388
+ {
2389
+ if ( key == 9 )
2390
+ {
2391
+ this.denyTab = false;
2392
+ return;
2393
+ }
2394
+ }
2395
+ else if ( this.fBtn.hasClass('AnyTime-mon-btn') )
2396
+ {
2397
+ if ( this.dY )
2398
+ this.yCur.triggerHandler('click');
2399
+ else if ( key == 9 )
2400
+ {
2401
+ this.denyTab = false;
2402
+ return;
2403
+ }
2404
+ }
2405
+ else if ( this.fBtn.hasClass('AnyTime-dom-btn') )
2406
+ {
2407
+ if ( ( key == 9 ) && event.shiftKey ) // Shift+Tab
2408
+ {
2409
+ this.denyTab = false;
2410
+ return;
2411
+ }
2412
+ else // PageUp
2413
+ {
2414
+ t = new Date(this.time.getTime());
2415
+ if ( event.shiftKey )
2416
+ t.setFullYear(t.getFullYear()-1);
2417
+ else
2418
+ {
2419
+ mo = t.getMonth()-1;
2420
+ if ( t.getDate() > __daysIn[mo] )
2421
+ t.setDate(__daysIn[mo])
2422
+ t.setMonth(mo);
2423
+ }
2424
+ this.keyDateChange(t);
2425
+ }
2426
+ }
2427
+ else if ( this.fBtn.hasClass('AnyTime-hr-btn') )
2428
+ {
2429
+ t = this.dDoM || this.dMo;
2430
+ if ( t )
2431
+ t.AnyTime_clickCurrent();
2432
+ else if ( this.dY )
2433
+ this.yCur.triggerHandler('click');
2434
+ else if ( key == 9 )
2435
+ {
2436
+ this.denyTab = false;
2437
+ return;
2438
+ }
2439
+ }
2440
+ else if ( this.fBtn.hasClass('AnyTime-min-ten-btn') )
2441
+ {
2442
+ t = this.dH || this.dDoM || this.dMo;
2443
+ if ( t )
2444
+ t.AnyTime_clickCurrent();
2445
+ else if ( this.dY )
2446
+ this.yCur.triggerHandler('click');
2447
+ else if ( key == 9 )
2448
+ {
2449
+ this.denyTab = false;
2450
+ return;
2451
+ }
2452
+ }
2453
+ else if ( this.fBtn.hasClass('AnyTime-min-one-btn') )
2454
+ this.dM.AnyTime_clickCurrent();
2455
+ else if ( this.fBtn.hasClass('AnyTime-sec-ten-btn') )
2456
+ {
2457
+ if ( this.dM )
2458
+ t = this.dM.find('.AnyTime-mins-ones');
2459
+ else
2460
+ t = this.dH || this.dDoM || this.dMo;
2461
+ if ( t )
2462
+ t.AnyTime_clickCurrent();
2463
+ else if ( this.dY )
2464
+ this.yCur.triggerHandler('click');
2465
+ else if ( key == 9 )
2466
+ {
2467
+ this.denyTab = false;
2468
+ return;
2469
+ }
2470
+ }
2471
+ else if ( this.fBtn.hasClass('AnyTime-sec-one-btn') )
2472
+ this.dS.AnyTime_clickCurrent();
2473
+ else if ( this.fBtn.hasClass('AnyTime-off-btn') )
2474
+ {
2475
+ if ( this.dS )
2476
+ t = this.dS.find('.AnyTime-secs-ones');
2477
+ else if ( this.dM )
2478
+ t = this.dM.find('.AnyTime-mins-ones');
2479
+ else
2480
+ t = this.dH || this.dDoM || this.dMo;
2481
+ if ( t )
2482
+ t.AnyTime_clickCurrent();
2483
+ else if ( this.dY )
2484
+ this.yCur.triggerHandler('click');
2485
+ else if ( key == 9 )
2486
+ {
2487
+ this.denyTab = false;
2488
+ return;
2489
+ }
2490
+ }
2491
+ }
2492
+ else if ( ( key == 34 ) || ( key == 9 ) ) // PageDown or Tab
2493
+ {
2494
+ if ( this.fBtn.hasClass('AnyTime-mil-btn') )
2495
+ this.yDiv.find('.AnyTime-cent-btn.AnyTime-cur-btn').triggerHandler('click');
2496
+ else if ( this.fBtn.hasClass('AnyTime-cent-btn') )
2497
+ this.yDiv.find('.AnyTime-dec-btn.AnyTime-cur-btn').triggerHandler('click');
2498
+ else if ( this.fBtn.hasClass('AnyTime-dec-btn') )
2499
+ this.yDiv.find('.AnyTime-yr-btn.AnyTime-cur-btn').triggerHandler('click');
2500
+ else if ( this.fBtn.hasClass('AnyTime-yr-btn') )
2501
+ {
2502
+ t = this.yDiv.find('.AnyTime-era-btn.AnyTime-cur-btn');
2503
+ if ( t.length )
2504
+ t.triggerHandler('click');
2505
+ else if ( key == 9 )
2506
+ this.dismissYDiv(event);
2507
+ }
2508
+ else if ( this.fBtn.hasClass('AnyTime-era-btn') )
2509
+ {
2510
+ if ( key == 9 )
2511
+ this.dismissYDiv(event);
2512
+ }
2513
+ else if ( this.fBtn.hasClass('AnyTime-off-off-btn') )
2514
+ {
2515
+ if ( key == 9 )
2516
+ this.dismissODiv(event);
2517
+ }
2518
+ else if ( this.fBtn.parents('.AnyTime-yrs').length )
2519
+ {
2520
+ t = this.dDoM || this.dMo || this.dH || this.dM || this.dS || this.dO;
2521
+ if ( t )
2522
+ t.AnyTime_clickCurrent();
2523
+ else if ( key == 9 )
2524
+ {
2525
+ this.denyTab = false;
2526
+ return;
2527
+ }
2528
+ }
2529
+ else if ( this.fBtn.hasClass('AnyTime-mon-btn') )
2530
+ {
2531
+ t = this.dDoM || this.dH || this.dM || this.dS || this.dO;
2532
+ if ( t )
2533
+ t.AnyTime_clickCurrent();
2534
+ else if ( key == 9 )
2535
+ {
2536
+ this.denyTab = false;
2537
+ return;
2538
+ }
2539
+ }
2540
+ else if ( this.fBtn.hasClass('AnyTime-dom-btn') )
2541
+ {
2542
+ if ( key == 9 ) // Tab
2543
+ {
2544
+ t = this.dH || this.dM || this.dS || this.dO;
2545
+ if ( t )
2546
+ t.AnyTime_clickCurrent();
2547
+ else
2548
+ {
2549
+ this.denyTab = false;
2550
+ return;
2551
+ }
2552
+ }
2553
+ else // PageDown
2554
+ {
2555
+ t = new Date(this.time.getTime());
2556
+ if ( event.shiftKey )
2557
+ t.setFullYear(t.getFullYear()+1);
2558
+ else
2559
+ {
2560
+ mo = t.getMonth()+1;
2561
+ if ( t.getDate() > __daysIn[mo] )
2562
+ t.setDate(__daysIn[mo])
2563
+ t.setMonth(mo);
2564
+ }
2565
+ this.keyDateChange(t);
2566
+ }
2567
+ }
2568
+ else if ( this.fBtn.hasClass('AnyTime-hr-btn') )
2569
+ {
2570
+ t = this.dM || this.dS || this.dO;
2571
+ if ( t )
2572
+ t.AnyTime_clickCurrent();
2573
+ else if ( key == 9 )
2574
+ {
2575
+ this.denyTab = false;
2576
+ return;
2577
+ }
2578
+ }
2579
+ else if ( this.fBtn.hasClass('AnyTime-min-ten-btn') )
2580
+ this.dM.find('.AnyTime-mins-ones .AnyTime-cur-btn').triggerHandler('click');
2581
+ else if ( this.fBtn.hasClass('AnyTime-min-one-btn') )
2582
+ {
2583
+ t = this.dS || this.dO;
2584
+ if ( t )
2585
+ t.AnyTime_clickCurrent();
2586
+ else if ( key == 9 )
2587
+ {
2588
+ this.denyTab = false;
2589
+ return;
2590
+ }
2591
+ }
2592
+ else if ( this.fBtn.hasClass('AnyTime-sec-ten-btn') )
2593
+ this.dS.find('.AnyTime-secs-ones .AnyTime-cur-btn').triggerHandler('click');
2594
+ else if ( this.fBtn.hasClass('AnyTime-sec-one-btn') )
2595
+ {
2596
+ if ( this.dO )
2597
+ this.dO.AnyTime_clickCurrent();
2598
+ else if ( key == 9 )
2599
+ {
2600
+ this.denyTab = false;
2601
+ return;
2602
+ }
2603
+ }
2604
+ else if ( this.fBtn.hasClass('AnyTime-off-btn') )
2605
+ {
2606
+ if ( key == 9 )
2607
+ {
2608
+ this.denyTab = false;
2609
+ return;
2610
+ }
2611
+ }
2612
+ }
2613
+ else if ( key == 35 ) // END
2614
+ {
2615
+ if ( this.fBtn.hasClass('AnyTime-mil-btn') || this.fBtn.hasClass('AnyTime-cent-btn') ||
2616
+ this.fBtn.hasClass('AnyTime-dec-btn') || this.fBtn.hasClass('AnyTime-yr-btn') ||
2617
+ this.fBtn.hasClass('AnyTime-era-btn') )
2618
+ {
2619
+ t = this.yDiv.find('.AnyTime-ce-btn');
2620
+ if ( ! t.length )
2621
+ t = this.yDiv.find('.AnyTime-yr9-btn');
2622
+ t.triggerHandler('click');
2623
+ }
2624
+ else if ( this.fBtn.hasClass('AnyTime-dom-btn') )
2625
+ {
2626
+ t = new Date(this.time.getTime());
2627
+ t.setDate(1);
2628
+ t.setMonth(t.getMonth()+1);
2629
+ t.setDate(t.getDate()-1);
2630
+ if ( event.ctrlKey )
2631
+ t.setMonth(11);
2632
+ this.keyDateChange(t);
2633
+ }
2634
+ else if ( this.dS )
2635
+ this.dS.find('.AnyTime-sec9-btn').triggerHandler('click');
2636
+ else if ( this.dM )
2637
+ this.dM.find('.AnyTime-min9-btn').triggerHandler('click');
2638
+ else if ( this.dH )
2639
+ this.dH.find('.AnyTime-hr23-btn').triggerHandler('click');
2640
+ else if ( this.dDoM )
2641
+ this.dDoM.find('.AnyTime-dom-btn-filled:last').triggerHandler('click');
2642
+ else if ( this.dMo )
2643
+ this.dMo.find('.AnyTime-mon12-btn').triggerHandler('click');
2644
+ else if ( this.dY )
2645
+ this.yAhead.triggerHandler('click');
2646
+ }
2647
+ else if ( key == 36 ) // HOME
2648
+ {
2649
+ if ( this.fBtn.hasClass('AnyTime-mil-btn') || this.fBtn.hasClass('AnyTime-cent-btn') ||
2650
+ this.fBtn.hasClass('AnyTime-dec-btn') || this.fBtn.hasClass('AnyTime-yr-btn') ||
2651
+ this.fBtn.hasClass('AnyTime-era-btn') )
2652
+ {
2653
+ this.yDiv.find('.AnyTime-mil0-btn').triggerHandler('click');
2654
+ }
2655
+ else if ( this.fBtn.hasClass('AnyTime-dom-btn') )
2656
+ {
2657
+ t = new Date(this.time.getTime());
2658
+ t.setDate(1);
2659
+ if ( event.ctrlKey )
2660
+ t.setMonth(0);
2661
+ this.keyDateChange(t);
2662
+ }
2663
+ else if ( this.dY )
2664
+ this.yCur.triggerHandler('click');
2665
+ else if ( this.dMo )
2666
+ this.dMo.find('.AnyTime-mon1-btn').triggerHandler('click');
2667
+ else if ( this.dDoM )
2668
+ this.dDoM.find('.AnyTime-dom-btn-filled:first').triggerHandler('click');
2669
+ else if ( this.dH )
2670
+ this.dH.find('.AnyTime-hr0-btn').triggerHandler('click');
2671
+ else if ( this.dM )
2672
+ this.dM.find('.AnyTime-min00-btn').triggerHandler('click');
2673
+ else if ( this.dS )
2674
+ this.dS.find('.AnyTime-sec00-btn').triggerHandler('click');
2675
+ }
2676
+ else if ( key == 37 ) // left arrow
2677
+ {
2678
+ if ( this.fBtn.hasClass('AnyTime-dom-btn') )
2679
+ this.keyDateChange(new Date(this.time.getTime()-__oneDay));
2680
+ else
2681
+ this.keyBack();
2682
+ }
2683
+ else if ( key == 38 ) // up arrow
2684
+ {
2685
+ if ( this.fBtn.hasClass('AnyTime-dom-btn') )
2686
+ this.keyDateChange(new Date(this.time.getTime()-(7*__oneDay)));
2687
+ else
2688
+ this.keyBack();
2689
+ }
2690
+ else if ( key == 39 ) // right arrow
2691
+ {
2692
+ if ( this.fBtn.hasClass('AnyTime-dom-btn') )
2693
+ this.keyDateChange(new Date(this.time.getTime()+__oneDay));
2694
+ else
2695
+ this.keyAhead();
2696
+ }
2697
+ else if ( key == 40 ) // down arrow
2698
+ {
2699
+ if ( this.fBtn.hasClass('AnyTime-dom-btn') )
2700
+ this.keyDateChange(new Date(this.time.getTime()+(7*__oneDay)));
2701
+ else
2702
+ this.keyAhead();
2703
+ }
2704
+ else if ( ( ( key == 86 ) || ( key == 118 ) ) && event.ctrlKey )
2705
+ {
2706
+ this.inp.val("").change();
2707
+ var _this = this;
2708
+ setTimeout( function() { _this.showPkr(null); }, 100 );
2709
+ return;
2710
+ }
2711
+ else
2712
+ this.showPkr(null);
2713
+
2714
+ event.preventDefault();
2715
+
2716
+ }, // .key()
2717
+
2718
+ //---------------------------------------------------------------------
2719
+ // .keyAhead() is called by #key when a user presses the right or
2720
+ // down arrow. It moves to the next appropriate button.
2721
+ //---------------------------------------------------------------------
2722
+
2723
+ keyAhead: function()
2724
+ {
2725
+ if ( this.fBtn.hasClass('AnyTime-mil9-btn') )
2726
+ this.yDiv.find('.AnyTime-cent0-btn').triggerHandler('click');
2727
+ else if ( this.fBtn.hasClass('AnyTime-cent9-btn') )
2728
+ this.yDiv.find('.AnyTime-dec0-btn').triggerHandler('click');
2729
+ else if ( this.fBtn.hasClass('AnyTime-dec9-btn') )
2730
+ this.yDiv.find('.AnyTime-yr0-btn').triggerHandler('click');
2731
+ else if ( this.fBtn.hasClass('AnyTime-yr9-btn') )
2732
+ this.yDiv.find('.AnyTime-bce-btn').triggerHandler('click');
2733
+ else if ( this.fBtn.hasClass('AnyTime-sec9-btn') )
2734
+ {}
2735
+ else if ( this.fBtn.hasClass('AnyTime-sec50-btn') )
2736
+ this.dS.find('.AnyTime-sec0-btn').triggerHandler('click');
2737
+ else if ( this.fBtn.hasClass('AnyTime-min9-btn') )
2738
+ {
2739
+ if ( this.dS )
2740
+ this.dS.find('.AnyTime-sec00-btn').triggerHandler('click');
2741
+ }
2742
+ else if ( this.fBtn.hasClass('AnyTime-min50-btn') )
2743
+ this.dM.find('.AnyTime-min0-btn').triggerHandler('click');
2744
+ else if ( this.fBtn.hasClass('AnyTime-hr23-btn') )
2745
+ {
2746
+ if ( this.dM )
2747
+ this.dM.find('.AnyTime-min00-btn').triggerHandler('click');
2748
+ else if ( this.dS )
2749
+ this.dS.find('.AnyTime-sec00-btn').triggerHandler('click');
2750
+ }
2751
+ else if ( this.fBtn.hasClass('AnyTime-hr11-btn') )
2752
+ this.dH.find('.AnyTime-hr12-btn').triggerHandler('click');
2753
+ else if ( this.fBtn.hasClass('AnyTime-mon12-btn') )
2754
+ {
2755
+ if ( this.dDoM )
2756
+ this.dDoM.AnyTime_clickCurrent();
2757
+ else if ( this.dH )
2758
+ this.dH.find('.AnyTime-hr0-btn').triggerHandler('click');
2759
+ else if ( this.dM )
2760
+ this.dM.find('.AnyTime-min00-btn').triggerHandler('click');
2761
+ else if ( this.dS )
2762
+ this.dS.find('.AnyTime-sec00-btn').triggerHandler('click');
2763
+ }
2764
+ else if ( this.fBtn.hasClass('AnyTime-yrs-ahead-btn') )
2765
+ {
2766
+ if ( this.dMo )
2767
+ this.dMo.find('.AnyTime-mon1-btn').triggerHandler('click');
2768
+ else if ( this.dH )
2769
+ this.dH.find('.AnyTime-hr0-btn').triggerHandler('click');
2770
+ else if ( this.dM )
2771
+ this.dM.find('.AnyTime-min00-btn').triggerHandler('click');
2772
+ else if ( this.dS )
2773
+ this.dS.find('.AnyTime-sec00-btn').triggerHandler('click');
2774
+ }
2775
+ else if ( this.fBtn.hasClass('AnyTime-yr-cur-btn') )
2776
+ this.yNext.triggerHandler('click');
2777
+ else
2778
+ this.fBtn.next().triggerHandler('click');
2779
+
2780
+ }, // .keyAhead()
2781
+
2782
+
2783
+ //---------------------------------------------------------------------
2784
+ // .keyBack() is called by #key when a user presses the left or
2785
+ // up arrow. It moves to the previous appropriate button.
2786
+ //---------------------------------------------------------------------
2787
+
2788
+ keyBack: function()
2789
+ {
2790
+ if ( this.fBtn.hasClass('AnyTime-cent0-btn') )
2791
+ this.yDiv.find('.AnyTime-mil9-btn').triggerHandler('click');
2792
+ else if ( this.fBtn.hasClass('AnyTime-dec0-btn') )
2793
+ this.yDiv.find('.AnyTime-cent9-btn').triggerHandler('click');
2794
+ else if ( this.fBtn.hasClass('AnyTime-yr0-btn') )
2795
+ this.yDiv.find('.AnyTime-dec9-btn').triggerHandler('click');
2796
+ else if ( this.fBtn.hasClass('AnyTime-bce-btn') )
2797
+ this.yDiv.find('.AnyTime-yr9-btn').triggerHandler('click');
2798
+ else if ( this.fBtn.hasClass('AnyTime-yr-cur-btn') )
2799
+ this.yPrior.triggerHandler('click');
2800
+ else if ( this.fBtn.hasClass('AnyTime-mon1-btn') )
2801
+ {
2802
+ if ( this.dY )
2803
+ this.yCur.triggerHandler('click');
2804
+ }
2805
+ else if ( this.fBtn.hasClass('AnyTime-hr0-btn') )
2806
+ {
2807
+ if ( this.dDoM )
2808
+ this.dDoM.AnyTime_clickCurrent();
2809
+ else if ( this.dMo )
2810
+ this.dMo.find('.AnyTime-mon12-btn').triggerHandler('click');
2811
+ else if ( this.dY )
2812
+ this.yNext.triggerHandler('click');
2813
+ }
2814
+ else if ( this.fBtn.hasClass('AnyTime-hr12-btn') )
2815
+ this.dH.find('.AnyTime-hr11-btn').triggerHandler('click');
2816
+ else if ( this.fBtn.hasClass('AnyTime-min00-btn') )
2817
+ {
2818
+ if ( this.dH )
2819
+ this.dH.find('.AnyTime-hr23-btn').triggerHandler('click');
2820
+ else if ( this.dDoM )
2821
+ this.dDoM.AnyTime_clickCurrent();
2822
+ else if ( this.dMo )
2823
+ this.dMo.find('.AnyTime-mon12-btn').triggerHandler('click');
2824
+ else if ( this.dY )
2825
+ this.yNext.triggerHandler('click');
2826
+ }
2827
+ else if ( this.fBtn.hasClass('AnyTime-min0-btn') )
2828
+ this.dM.find('.AnyTime-min50-btn').triggerHandler('click');
2829
+ else if ( this.fBtn.hasClass('AnyTime-sec00-btn') )
2830
+ {
2831
+ if ( this.dM )
2832
+ this.dM.find('.AnyTime-min9-btn').triggerHandler('click');
2833
+ else if ( this.dH )
2834
+ this.dH.find('.AnyTime-hr23-btn').triggerHandler('click');
2835
+ else if ( this.dDoM )
2836
+ this.dDoM.AnyTime_clickCurrent();
2837
+ else if ( this.dMo )
2838
+ this.dMo.find('.AnyTime-mon12-btn').triggerHandler('click');
2839
+ else if ( this.dY )
2840
+ this.yNext.triggerHandler('click');
2841
+ }
2842
+ else if ( this.fBtn.hasClass('AnyTime-sec0-btn') )
2843
+ this.dS.find('.AnyTime-sec50-btn').triggerHandler('click');
2844
+ else
2845
+ this.fBtn.prev().triggerHandler('click');
2846
+
2847
+ }, // .keyBack()
2848
+
2849
+ //---------------------------------------------------------------------
2850
+ // .keyDateChange() is called by #key when an direction key
2851
+ // (arrows/page/etc) is pressed while the Day-of-Month calendar has
2852
+ // focus. The current day is adjusted accordingly.
2853
+ //---------------------------------------------------------------------
2854
+
2855
+ keyDateChange: function( newDate )
2856
+ {
2857
+ if ( this.fBtn.hasClass('AnyTime-dom-btn') )
2858
+ {
2859
+ this.set(newDate);
2860
+ this.upd(null);
2861
+ this.setFocus( this.dDoM.find('.AnyTime-cur-btn') );
2862
+ }
2863
+ },
2864
+
2865
+ //---------------------------------------------------------------------
2866
+ // .makeCloak() is called by .askOffset() and .askYear() to create
2867
+ // a cloak div.
2868
+ //---------------------------------------------------------------------
2869
+
2870
+ makeCloak: function()
2871
+ {
2872
+ if ( ! this.cloak )
2873
+ {
2874
+ this.cloak = $('<div class="AnyTime-cloak" style="position:absolute" />');
2875
+ this.div.append( this.cloak );
2876
+ this.cloak.click(
2877
+ function(e)
2878
+ {
2879
+ if ( _this.oDiv && _this.oDiv.is(":visible") )
2880
+ _this.dismissODiv(e);
2881
+ else
2882
+ _this.dismissYDiv(e);
2883
+ });
2884
+ }
2885
+ else
2886
+ this.cloak.show();
2887
+ },
2888
+
2889
+ //---------------------------------------------------------------------
2890
+ // .newHour() is called when a user clicks an hour value.
2891
+ // It changes the date and updates the text field.
2892
+ //---------------------------------------------------------------------
2893
+
2894
+ newHour: function( event )
2895
+ {
2896
+ var h;
2897
+ var t;
2898
+ var elem = $(event.target);
2899
+ if ( elem.hasClass("AnyTime-out-btn") )
2900
+ return;
2901
+ if ( ! this.twelveHr )
2902
+ h = Number(elem.text());
2903
+ else
2904
+ {
2905
+ var str = elem.text();
2906
+ t = str.indexOf('a');
2907
+ if ( t < 0 )
2908
+ {
2909
+ t = Number(str.substr(0,str.indexOf('p')));
2910
+ h = ( (t==12) ? 12 : (t+12) );
2911
+ }
2912
+ else
2913
+ {
2914
+ t = Number(str.substr(0,t));
2915
+ h = ( (t==12) ? 0 : t );
2916
+ }
2917
+ }
2918
+ t = new Date(this.time.getTime());
2919
+ t.setHours(h);
2920
+ this.set(t);
2921
+ this.upd(elem);
2922
+
2923
+ }, // .newHour()
2924
+
2925
+ //---------------------------------------------------------------------
2926
+ // .newOffset() is called when a user clicks the UTC offset (timezone)
2927
+ // (or +/- button) to shift the year. It changes the date and updates
2928
+ // the text field.
2929
+ //---------------------------------------------------------------------
2930
+
2931
+ newOffset: function( event )
2932
+ {
2933
+ if ( event.target == this.oSel[0] )
2934
+ this.askOffset(event);
2935
+ else
2936
+ {
2937
+ this.upd(this.oCur);
2938
+ }
2939
+ },
2940
+
2941
+ //---------------------------------------------------------------------
2942
+ // .newOPos() is called internally whenever a user clicks an offset
2943
+ // selection value. It changes the date and updates the text field.
2944
+ //---------------------------------------------------------------------
2945
+
2946
+ newOPos: function( event )
2947
+ {
2948
+ var elem = $(event.target);
2949
+ this.offMin = elem[0].AnyTime_offMin;
2950
+ this.offSI = elem[0].AnyTime_offSI;
2951
+ var t = new Date(this.time.getTime());
2952
+ this.set(t);
2953
+ this.updODiv(elem);
2954
+
2955
+ }, // .newOPos()
2956
+
2957
+ //---------------------------------------------------------------------
2958
+ // .newYear() is called when a user clicks a year (or one of the
2959
+ // "arrows") to shift the year. It changes the date and updates the
2960
+ // text field.
2961
+ //---------------------------------------------------------------------
2962
+
2963
+ newYear: function( event )
2964
+ {
2965
+ var elem = $(event.target);
2966
+ if ( elem.hasClass("AnyTime-out-btn") )
2967
+ return;
2968
+ var txt = elem.text();
2969
+ if ( ( txt == '<' ) || ( txt == '&lt;' ) )
2970
+ this.askYear(event);
2971
+ else if ( ( txt == '>' ) || ( txt == '&gt;' ) )
2972
+ this.askYear(event);
2973
+ else
2974
+ {
2975
+ var t = new Date(this.time.getTime());
2976
+ t.setFullYear(Number(txt));
2977
+ this.set(t);
2978
+ this.upd(this.yCur);
2979
+ }
2980
+ },
2981
+
2982
+ //---------------------------------------------------------------------
2983
+ // .newYPos() is called internally whenever a user clicks a year
2984
+ // selection value. It changes the date and updates the text field.
2985
+ //---------------------------------------------------------------------
2986
+
2987
+ newYPos: function( event )
2988
+ {
2989
+ var elem = $(event.target);
2990
+ if ( elem.hasClass("AnyTime-out-btn") )
2991
+ return;
2992
+
2993
+ var era = 1;
2994
+ var year = this.time.getFullYear();
2995
+ if ( year < 0 )
2996
+ {
2997
+ era = (-1);
2998
+ year = 0 - year;
2999
+ }
3000
+ year = AnyTime.pad( year, 4 );
3001
+ if ( elem.hasClass('AnyTime-mil-btn') )
3002
+ year = elem.html() + year.substring(1,4);
3003
+ else if ( elem.hasClass('AnyTime-cent-btn') )
3004
+ year = year.substring(0,1) + elem.html() + year.substring(2,4);
3005
+ else if ( elem.hasClass('AnyTime-dec-btn') )
3006
+ year = year.substring(0,2) + elem.html() + year.substring(3,4);
3007
+ else
3008
+ year = year.substring(0,3) + elem.html();
3009
+ if ( year == '0000' )
3010
+ year = 1;
3011
+ var t = new Date(this.time.getTime());
3012
+ t.setFullYear( era * year );
3013
+ this.set(t);
3014
+ this.updYDiv(elem);
3015
+
3016
+ }, // .newYPos()
3017
+
3018
+ //---------------------------------------------------------------------
3019
+ // .onReady() initializes the picker after the page has loaded and,
3020
+ // if IE6, after the iframe has been created.
3021
+ //---------------------------------------------------------------------
3022
+
3023
+ onReady: function()
3024
+ {
3025
+ this.lostFocus = true;
3026
+ if ( ! this.pop )
3027
+ this.upd(null);
3028
+ else
3029
+ {
3030
+ if ( this.div.parent() != document.body )
3031
+ this.div.appendTo( document.body );
3032
+ }
3033
+ },
3034
+
3035
+ //---------------------------------------------------------------------
3036
+ // .pos() positions the picker, such as when it is displayed or
3037
+ // when the window is resized.
3038
+ //---------------------------------------------------------------------
3039
+
3040
+ pos: function(event) // note: event is ignored but this is a handler
3041
+ {
3042
+ if ( this.pop )
3043
+ {
3044
+ var off = this.inp.offset();
3045
+ var bodyWidth = $(document.body).outerWidth(true);
3046
+ var pickerWidth = this.div.outerWidth(true);
3047
+ var left = off.left;
3048
+ if ( left + pickerWidth > bodyWidth - 20 )
3049
+ left = bodyWidth - ( pickerWidth + 20 );
3050
+ var top = off.top - this.div.outerHeight(true);
3051
+ if ( top < 0 )
3052
+ top = off.top + this.inp.outerHeight(true);
3053
+ this.div.css( { top: String(top)+'px', left: String(left<0?0:left)+'px' } );
3054
+ }
3055
+
3056
+ var wOff = this.div.offset();
3057
+
3058
+ if ( this.oDiv && this.oDiv.is(":visible") )
3059
+ {
3060
+ var oOff = this.oLab.offset();
3061
+ if ( this.div.css('position') == 'absolute' )
3062
+ {
3063
+ oOff.top -= wOff.top;
3064
+ oOff.left = oOff.left - wOff.left;
3065
+ wOff = { top: 0, left: 0 };
3066
+ }
3067
+ var oW = this.oDiv.AnyTime_width(true);
3068
+ var wW = this.div.AnyTime_width(true);
3069
+ if ( oOff.left + oW > wOff.left + wW )
3070
+ {
3071
+ oOff.left = (wOff.left+wW)-oW;
3072
+ if ( oOff.left < 2 )
3073
+ oOff.left = 2;
3074
+ }
3075
+
3076
+ var oH = this.oDiv.AnyTime_height(true);
3077
+ var wH = this.div.AnyTime_height(true);
3078
+ oOff.top += this.oLab.AnyTime_height(true);
3079
+ if ( oOff.top + oH > wOff.top + wH )
3080
+ oOff.top = oOff.top - oH;
3081
+ if ( oOff.top < wOff.top )
3082
+ oOff.top = wOff.top;
3083
+
3084
+ this.oDiv.css( { top: oOff.top+'px', left: oOff.left+'px' } ) ;
3085
+ }
3086
+
3087
+ else if ( this.yDiv && this.yDiv.is(":visible") )
3088
+ {
3089
+ var yOff = this.yLab.offset();
3090
+ if ( this.div.css('position') == 'absolute' )
3091
+ {
3092
+ yOff.top -= wOff.top;
3093
+ yOff.left = yOff.left - wOff.left;
3094
+ wOff = { top: 0, left: 0 };
3095
+ }
3096
+ yOff.left += ( (this.yLab.outerWidth(true)-this.yDiv.outerWidth(true)) / 2 );
3097
+ this.yDiv.css( { top: yOff.top+'px', left: yOff.left+'px' } ) ;
3098
+ }
3099
+
3100
+ if ( this.cloak )
3101
+ this.cloak.css( {
3102
+ top: wOff.top+'px',
3103
+ left: wOff.left+'px',
3104
+ height: String(this.div.outerHeight(true)-2)+'px',
3105
+ width: String(this.div.outerWidth(!$.browser.safari)-2)+'px'
3106
+ } );
3107
+
3108
+ }, // .pos()
3109
+
3110
+ //---------------------------------------------------------------------
3111
+ // .set() changes the current time. It returns true if the new
3112
+ // time is within the allowed range (if any).
3113
+ //---------------------------------------------------------------------
3114
+
3115
+ set: function(newTime)
3116
+ {
3117
+ var t = newTime.getTime();
3118
+ if ( this.earliest && ( t < this.earliest ) )
3119
+ this.time = new Date(this.earliest);
3120
+ else if ( this.latest && ( t > this.latest ) )
3121
+ this.time = new Date(this.latest);
3122
+ else
3123
+ this.time = newTime;
3124
+ },
3125
+
3126
+ //---------------------------------------------------------------------
3127
+ // .setEarliest() changes the earliest time.
3128
+ //---------------------------------------------------------------------
3129
+
3130
+ setEarliest: function(newTime)
3131
+ {
3132
+ this.earliest = newTime;
3133
+ this.set(this.time);
3134
+ },
3135
+
3136
+ //---------------------------------------------------------------------
3137
+ // .setLatest() changes the latest time.
3138
+ //---------------------------------------------------------------------
3139
+
3140
+ setLatest: function(newTime)
3141
+ {
3142
+ this.latest = newTime;
3143
+ this.set(this.time);
3144
+ },
3145
+
3146
+ //---------------------------------------------------------------------
3147
+ // .showPkr() displays the picker and sets the focus psuedo-
3148
+ // element. The current value in the input field is used to initialize
3149
+ // the picker.
3150
+ //---------------------------------------------------------------------
3151
+
3152
+ showPkr: function(event)
3153
+ {
3154
+ try
3155
+ {
3156
+ this.time = this.conv.parse(this.inp.val());
3157
+ this.offMin = this.conv.getUtcParseOffsetCaptured();
3158
+ this.offSI = this.conv.getUtcParseOffsetSubIndex();
3159
+ }
3160
+ catch ( e )
3161
+ {
3162
+ this.time = new Date();
3163
+ }
3164
+ this.set(this.time);
3165
+ this.upd(null);
3166
+
3167
+ fBtn = null;
3168
+ var cb = '.AnyTime-cur-btn:first';
3169
+ if ( this.dDoM )
3170
+ fBtn = this.dDoM.find(cb);
3171
+ else if ( this.yCur )
3172
+ fBtn = this.yCur;
3173
+ else if ( this.dMo )
3174
+ fBtn = this.dMo.find(cb);
3175
+ else if ( this.dH )
3176
+ fBtn = this.dH.find(cb);
3177
+ else if ( this.dM )
3178
+ fBtn = this.dM.find(cb);
3179
+ else if ( this.dS )
3180
+ fBtn = this.dS.find(cb);
3181
+
3182
+ this.setFocus(fBtn);
3183
+ this.pos(event);
3184
+
3185
+ // IE6 doesn't float popups over <select> elements unless an
3186
+ // <iframe> is inserted between them! So after the picker is
3187
+ // made visible, move the <iframe> behind it.
3188
+
3189
+ if ( this.pop && __iframe )
3190
+ setTimeout(
3191
+ function()
3192
+ {
3193
+ var pos = _this.div.offset();
3194
+ __iframe.css( {
3195
+ height: String(_this.div.outerHeight(true)) + 'px',
3196
+ left: String(pos.left) + 'px',
3197
+ position: 'absolute',
3198
+ top: String(pos.top) + 'px',
3199
+ width: String(_this.div.outerWidth(true)) + 'px'
3200
+ } );
3201
+ __iframe.show();
3202
+ }, 300 );
3203
+
3204
+ }, // .showPkr()
3205
+
3206
+ //---------------------------------------------------------------------
3207
+ // .upd() updates the picker's appearance. It is called after
3208
+ // most events to make the picker reflect the currently-selected
3209
+ // values. fBtn is the psuedo-button to be given focus.
3210
+ //---------------------------------------------------------------------
3211
+
3212
+ upd: function(fBtn)
3213
+ {
3214
+ var cmpLo = new Date(this.time.getTime());
3215
+ cmpLo.setMonth(0,1);
3216
+ cmpLo.setHours(0,0,0,0);
3217
+ var cmpHi = new Date(this.time.getTime());
3218
+ cmpHi.setMonth(11,31);
3219
+ cmpHi.setHours(23,59,59,999);
3220
+
3221
+ // Update year.
3222
+
3223
+ var current = this.time.getFullYear();
3224
+ if ( this.earliest && this.yPast )
3225
+ {
3226
+ cmpHi.setYear(current-2);
3227
+ if ( cmpHi.getTime() < this.earliest )
3228
+ this.yPast.addClass('AnyTime-out-btn ui-state-disabled');
3229
+ else
3230
+ this.yPast.removeClass('AnyTime-out-btn ui-state-disabled');
3231
+ }
3232
+ if ( this.yPrior )
3233
+ {
3234
+ this.yPrior.text(AnyTime.pad((current==1)?(-1):(current-1),4));
3235
+ if ( this.earliest )
3236
+ {
3237
+ cmpHi.setYear(current-1);
3238
+ if ( cmpHi.getTime() < this.earliest )
3239
+ this.yPrior.addClass('AnyTime-out-btn ui-state-disabled');
3240
+ else
3241
+ this.yPrior.removeClass('AnyTime-out-btn ui-state-disabled');
3242
+ }
3243
+ }
3244
+ if ( this.yCur )
3245
+ this.yCur.text(AnyTime.pad(current,4));
3246
+ if ( this.yNext )
3247
+ {
3248
+ this.yNext.text(AnyTime.pad((current==-1)?1:(current+1),4));
3249
+ if ( this.latest )
3250
+ {
3251
+ cmpLo.setYear(current+1);
3252
+ if ( cmpLo.getTime() > this.latest )
3253
+ this.yNext.addClass('AnyTime-out-btn ui-state-disabled');
3254
+ else
3255
+ this.yNext.removeClass('AnyTime-out-btn ui-state-disabled');
3256
+ }
3257
+ }
3258
+ if ( this.latest && this.yAhead )
3259
+ {
3260
+ cmpLo.setYear(current+2);
3261
+ if ( cmpLo.getTime() > this.latest )
3262
+ this.yAhead.addClass('AnyTime-out-btn ui-state-disabled');
3263
+ else
3264
+ this.yAhead.removeClass('AnyTime-out-btn ui-state-disabled');
3265
+ }
3266
+
3267
+ // Update month.
3268
+
3269
+ cmpLo.setFullYear( this.time.getFullYear() );
3270
+ cmpHi.setFullYear( this.time.getFullYear() );
3271
+ var i = 0;
3272
+ current = this.time.getMonth();
3273
+ $('#'+this.id+' .AnyTime-mon-btn').each(
3274
+ function()
3275
+ {
3276
+ cmpLo.setMonth(i);
3277
+ cmpHi.setDate(1);
3278
+ cmpHi.setMonth(i+1);
3279
+ cmpHi.setDate(0);
3280
+ $(this).AnyTime_current( i == current,
3281
+ ((!_this.earliest)||(cmpHi.getTime()>=_this.earliest)) &&
3282
+ ((!_this.latest)||(cmpLo.getTime()<=_this.latest)) );
3283
+ i++;
3284
+ } );
3285
+
3286
+ // Update days.
3287
+
3288
+ cmpLo.setFullYear( this.time.getFullYear() );
3289
+ cmpHi.setFullYear( this.time.getFullYear() );
3290
+ cmpLo.setMonth( this.time.getMonth() );
3291
+ cmpHi.setMonth( this.time.getMonth(), 1 );
3292
+ current = this.time.getDate();
3293
+ var currentMonth = this.time.getMonth();
3294
+ var dow1 = cmpLo.getDay();
3295
+ if ( this.fDOW > dow1 )
3296
+ dow1 += 7;
3297
+ var wom = 0, dow=0;
3298
+ $('#'+this.id+' .AnyTime-wk').each(
3299
+ function()
3300
+ {
3301
+ dow = _this.fDOW;
3302
+ $(this).children().each(
3303
+ function()
3304
+ {
3305
+ if ( dow - _this.fDOW < 7 )
3306
+ {
3307
+ var td = $(this);
3308
+ if ( ((wom==0)&&(dow<dow1)) || (cmpLo.getMonth()!=currentMonth) )
3309
+ {
3310
+ td.html('&#160;');
3311
+ td.removeClass('AnyTime-dom-btn-filled AnyTime-cur-btn ui-state-default ui-state-highlight');
3312
+ td.addClass('AnyTime-dom-btn-empty');
3313
+ if ( wom ) // not first week
3314
+ {
3315
+ if ( ( cmpLo.getDate() == 1 ) && ( dow != 0 ) )
3316
+ td.addClass('AnyTime-dom-btn-empty-after-filled');
3317
+ else
3318
+ td.removeClass('AnyTime-dom-btn-empty-after-filled');
3319
+ if ( cmpLo.getDate() <= 7 )
3320
+ td.addClass('AnyTime-dom-btn-empty-below-filled');
3321
+ else
3322
+ td.removeClass('AnyTime-dom-btn-empty-below-filled');
3323
+ cmpLo.setDate(cmpLo.getDate()+1);
3324
+ cmpHi.setDate(cmpHi.getDate()+1);
3325
+ }
3326
+ else // first week
3327
+ {
3328
+ td.addClass('AnyTime-dom-btn-empty-above-filled');
3329
+ if ( dow == dow1 - 1 )
3330
+ td.addClass('AnyTime-dom-btn-empty-before-filled');
3331
+ else
3332
+ td.removeClass('AnyTime-dom-btn-empty-before-filled');
3333
+ }
3334
+ td.addClass('ui-state-default ui-state-disabled');
3335
+ }
3336
+ else
3337
+ {
3338
+ i = cmpLo.getDate();
3339
+ td.text(i);
3340
+ td.removeClass('AnyTime-dom-btn-empty AnyTime-dom-btn-empty-above-filled AnyTime-dom-btn-empty-before-filled '+
3341
+ 'AnyTime-dom-btn-empty-after-filled AnyTime-dom-btn-empty-below-filled ' +
3342
+ 'ui-state-default ui-state-disabled');
3343
+ td.addClass('AnyTime-dom-btn-filled ui-state-default');
3344
+ td.AnyTime_current( i == current,
3345
+ ((!_this.earliest)||(cmpHi.getTime()>=_this.earliest)) &&
3346
+ ((!_this.latest)||(cmpLo.getTime()<=_this.latest)) );
3347
+ cmpLo.setDate(i+1);
3348
+ cmpHi.setDate(i+1);
3349
+ }
3350
+ }
3351
+ dow++;
3352
+ } );
3353
+ wom++;
3354
+ } );
3355
+
3356
+ // Update hour.
3357
+
3358
+ cmpLo.setFullYear( this.time.getFullYear() );
3359
+ cmpHi.setFullYear( this.time.getFullYear() );
3360
+ cmpLo.setMonth( this.time.getMonth(), this.time.getDate() );
3361
+ cmpHi.setMonth( this.time.getMonth(), this.time.getDate() );
3362
+ var not12 = ! this.twelveHr;
3363
+ var hr = this.time.getHours();
3364
+ $('#'+this.id+' .AnyTime-hr-btn').each(
3365
+ function()
3366
+ {
3367
+ var html = this.innerHTML;
3368
+ var i;
3369
+ if ( not12 )
3370
+ i = Number(html);
3371
+ else
3372
+ {
3373
+ i = Number(html.substring(0,html.length-2) );
3374
+ if ( html.charAt(html.length-2) == 'a' )
3375
+ {
3376
+ if ( i == 12 )
3377
+ i = 0;
3378
+ }
3379
+ else if ( i < 12 )
3380
+ i += 12;
3381
+ }
3382
+ cmpLo.setHours(i);
3383
+ cmpHi.setHours(i);
3384
+ $(this).AnyTime_current( hr == i,
3385
+ ((!_this.earliest)||(cmpHi.getTime()>=_this.earliest)) &&
3386
+ ((!_this.latest)||(cmpLo.getTime()<=_this.latest)) );
3387
+ if ( i < 23 )
3388
+ cmpLo.setHours( cmpLo.getHours()+1 );
3389
+ } );
3390
+
3391
+ // Update minute.
3392
+
3393
+ cmpLo.setHours( this.time.getHours() );
3394
+ cmpHi.setHours( this.time.getHours() );
3395
+ var units = this.time.getMinutes();
3396
+ var tens = String(Math.floor(units/10));
3397
+ var ones = String(units % 10);
3398
+ $('#'+this.id+' .AnyTime-min-ten-btn:not(.AnyTime-min-ten-btn-empty)').each(
3399
+ function()
3400
+ {
3401
+ $(this).AnyTime_current( this.innerHTML == tens,
3402
+ ((!_this.earliest)||(cmpHi.getTime()>=_this.earliest)) &&
3403
+ ((!_this.latest)||(cmpLo.getTime()<=_this.latest)) );
3404
+ if ( cmpLo.getMinutes() < 50 )
3405
+ {
3406
+ cmpLo.setMinutes( cmpLo.getMinutes()+10 );
3407
+ cmpHi.setMinutes( cmpHi.getMinutes()+10 );
3408
+ }
3409
+ } );
3410
+ cmpLo.setMinutes( Math.floor(this.time.getMinutes()/10)*10 );
3411
+ cmpHi.setMinutes( Math.floor(this.time.getMinutes()/10)*10 );
3412
+ $('#'+this.id+' .AnyTime-min-one-btn:not(.AnyTime-min-one-btn-empty)').each(
3413
+ function()
3414
+ {
3415
+ $(this).AnyTime_current( this.innerHTML == ones,
3416
+ ((!_this.earliest)||(cmpHi.getTime()>=_this.earliest)) &&
3417
+ ((!_this.latest)||(cmpLo.getTime()<=_this.latest)) );
3418
+ cmpLo.setMinutes( cmpLo.getMinutes()+1 );
3419
+ cmpHi.setMinutes( cmpHi.getMinutes()+1 );
3420
+ } );
3421
+
3422
+ // Update second.
3423
+
3424
+ cmpLo.setMinutes( this.time.getMinutes() );
3425
+ cmpHi.setMinutes( this.time.getMinutes() );
3426
+ units = this.time.getSeconds();
3427
+ tens = String(Math.floor(units/10));
3428
+ ones = String(units % 10);
3429
+ $('#'+this.id+' .AnyTime-sec-ten-btn:not(.AnyTime-sec-ten-btn-empty)').each(
3430
+ function()
3431
+ {
3432
+ $(this).AnyTime_current( this.innerHTML == tens,
3433
+ ((!_this.earliest)||(cmpHi.getTime()>=_this.earliest)) &&
3434
+ ((!_this.latest)||(cmpLo.getTime()<=_this.latest)) );
3435
+ if ( cmpLo.getSeconds() < 50 )
3436
+ {
3437
+ cmpLo.setSeconds( cmpLo.getSeconds()+10 );
3438
+ cmpHi.setSeconds( cmpHi.getSeconds()+10 );
3439
+ }
3440
+ } );
3441
+ cmpLo.setSeconds( Math.floor(this.time.getSeconds()/10)*10 );
3442
+ cmpHi.setSeconds( Math.floor(this.time.getSeconds()/10)*10 );
3443
+ $('#'+this.id+' .AnyTime-sec-one-btn:not(.AnyTime-sec-one-btn-empty)').each(
3444
+ function()
3445
+ {
3446
+ $(this).AnyTime_current( this.innerHTML == ones,
3447
+ ((!_this.earliest)||(cmpHi.getTime()>=_this.earliest)) &&
3448
+ ((!_this.latest)||(cmpLo.getTime()<=_this.latest)) );
3449
+ cmpLo.setSeconds( cmpLo.getSeconds()+1 );
3450
+ cmpHi.setSeconds( cmpHi.getSeconds()+1 );
3451
+ } );
3452
+
3453
+ // Update offset (time zone).
3454
+
3455
+ if ( this.oConv )
3456
+ {
3457
+ this.oConv.setUtcFormatOffsetAlleged(this.offMin);
3458
+ this.oConv.setUtcFormatOffsetSubIndex(this.offSI);
3459
+ var tzs = this.oConv.format(this.time);
3460
+ this.oCur.html( tzs );
3461
+ }
3462
+
3463
+ // Set the focus element, then size the picker according to its
3464
+ // components, show the changes, and invoke Ajax if desired.
3465
+
3466
+ if ( fBtn )
3467
+ this.setFocus(fBtn);
3468
+
3469
+ this.conv.setUtcFormatOffsetAlleged(this.offMin);
3470
+ this.conv.setUtcFormatOffsetSubIndex(this.offSI);
3471
+ this.inp.val(this.conv.format(this.time)).change();
3472
+ this.div.show();
3473
+
3474
+ var d, totH = 0, totW = 0, dYW = 0, dMoW = 0, dDoMW = 0;
3475
+ if ( this.dY )
3476
+ {
3477
+ totW = dYW = this.dY.outerWidth(true);
3478
+ totH = this.yLab.AnyTime_height(true) + this.dY.AnyTime_height(true);
3479
+ }
3480
+ if ( this.dMo )
3481
+ {
3482
+ dMoW = this.dMo.outerWidth(true);
3483
+ if ( dMoW > totW )
3484
+ totW = dMoW;
3485
+ totH += this.hMo.AnyTime_height(true) + this.dMo.AnyTime_height(true);
3486
+ }
3487
+ if ( this.dDoM )
3488
+ {
3489
+ dDoMW = this.dDoM.outerWidth(true);
3490
+ if ( dDoMW > totW )
3491
+ totW = dDoMW;
3492
+ if ( __msie6 || __msie7 )
3493
+ {
3494
+ if ( dMoW > dDoMW )
3495
+ this.dDoM.css('width',String(dMoW)+'px');
3496
+ else if ( dYW > dDoMW )
3497
+ this.dDoM.css('width',String(dYW)+'px');
3498
+ }
3499
+ totH += this.hDoM.AnyTime_height(true) + this.dDoM.AnyTime_height(true);
3500
+ }
3501
+ if ( this.dD )
3502
+ {
3503
+ this.dD.css( { width:String(totW)+'px', height:String(totH)+'px' } );
3504
+ totW += this.dMinW;
3505
+ totH += this.dMinH;
3506
+ }
3507
+
3508
+ var w = 0, h = 0, timeH = 0, timeW = 0;
3509
+ if ( this.dH )
3510
+ {
3511
+ w = this.dH.outerWidth(true);
3512
+ timeW += w + 1;
3513
+ h = this.dH.AnyTime_height(true);
3514
+ if ( h > timeH )
3515
+ timeH = h;
3516
+ }
3517
+ if ( this.dM )
3518
+ {
3519
+ w = this.dM.outerWidth(true);
3520
+ timeW += w + 1;
3521
+ h = this.dM.AnyTime_height(true);
3522
+ if ( h > timeH )
3523
+ timeH = h;
3524
+ }
3525
+ if ( this.dS )
3526
+ {
3527
+ w = this.dS.outerWidth(true);
3528
+ timeW += w + 1;
3529
+ h = this.dS.AnyTime_height(true);
3530
+ if ( h > timeH )
3531
+ timeH = h;
3532
+ }
3533
+ if ( this.dO )
3534
+ {
3535
+ w = this.oMinW;
3536
+ if ( timeW < w+1 )
3537
+ timeW = w+1;
3538
+ timeH += this.dO.AnyTime_height(true);
3539
+ }
3540
+ if ( this.dT )
3541
+ {
3542
+ this.dT.css( { width:String(timeW)+'px', height:String(timeH)+'px' } );
3543
+ timeW += this.tMinW + 1;
3544
+ timeH += this.tMinH;
3545
+ totW += timeW;
3546
+ if ( timeH > totH )
3547
+ totH = timeH;
3548
+ if ( this.dO ) // stretch offset button if possible
3549
+ {
3550
+ var dOW = this.dT.width()-(this.oMinW+1);
3551
+ this.dO.css({width:String(dOW)+"px"});
3552
+ this.oCur.css({width:String(dOW-(this.oListMinW+4))+"px"});
3553
+ }
3554
+ }
3555
+
3556
+ this.dB.css({height:String(totH)+'px',width:String(totW)+'px'});
3557
+
3558
+ totH += this.bMinH;
3559
+ totW += this.bMinW;
3560
+ totH += this.hTitle.AnyTime_height(true) + this.wMinH;
3561
+ totW += this.wMinW;
3562
+ if ( this.hTitle.outerWidth(true) > totW )
3563
+ totW = this.hTitle.outerWidth(true); // IE quirk
3564
+ this.div.css({height:String(totH)+'px',width:String(totW)+'px'});
3565
+
3566
+ if ( ! this.pop )
3567
+ this.ajax();
3568
+
3569
+ }, // .upd()
3570
+
3571
+ //---------------------------------------------------------------------
3572
+ // .updODiv() updates the UTC offset selector's appearance. It is
3573
+ // called after most events to make the picker reflect the currently-
3574
+ // selected values. fBtn is the psuedo-button to be given focus.
3575
+ //---------------------------------------------------------------------
3576
+
3577
+ updODiv: function(fBtn)
3578
+ {
3579
+ var cur, matched = false, def = null;
3580
+ this.oDiv.find('.AnyTime-off-off-btn').each(
3581
+ function()
3582
+ {
3583
+ if ( this.AnyTime_offMin == _this.offMin )
3584
+ {
3585
+ if ( this.AnyTime_offSI == _this.offSI )
3586
+ $(this).AnyTime_current(matched=true,true);
3587
+ else
3588
+ {
3589
+ $(this).AnyTime_current(false,true);
3590
+ if ( def == null )
3591
+ def = $(this);
3592
+ }
3593
+ }
3594
+ else
3595
+ $(this).AnyTime_current(false,true);
3596
+ } );
3597
+ if ( ( ! matched ) && ( def != null ) )
3598
+ def.AnyTime_current(true,true);
3599
+
3600
+ // Show change
3601
+
3602
+ this.conv.setUtcFormatOffsetAlleged(this.offMin);
3603
+ this.conv.setUtcFormatOffsetSubIndex(this.offSI);
3604
+ this.inp.val(this.conv.format(this.time)).change();
3605
+ this.upd(fBtn);
3606
+
3607
+ }, // .updODiv()
3608
+
3609
+ //---------------------------------------------------------------------
3610
+ // .updYDiv() updates the year selector's appearance. It is
3611
+ // called after most events to make the picker reflect the currently-
3612
+ // selected values. fBtn is the psuedo-button to be given focus.
3613
+ //---------------------------------------------------------------------
3614
+
3615
+ updYDiv: function(fBtn)
3616
+ {
3617
+ var i, legal;
3618
+ var era = 1;
3619
+ var yearValue = this.time.getFullYear();
3620
+ if ( yearValue < 0 )
3621
+ {
3622
+ era = (-1);
3623
+ yearValue = 0 - yearValue;
3624
+ }
3625
+ yearValue = AnyTime.pad( yearValue, 4 );
3626
+ var eY = _this.earliest && new Date(_this.earliest).getFullYear();
3627
+ var lY = _this.latest && new Date(_this.latest).getFullYear();
3628
+
3629
+ i = 0;
3630
+ this.yDiv.find('.AnyTime-mil-btn').each(
3631
+ function()
3632
+ {
3633
+ legal = ( ((!_this.earliest)||(era*(i+(era<0?0:999))>=eY)) && ((!_this.latest)||(era*(i+(era>0?0:999))<=lY)) );
3634
+ $(this).AnyTime_current( this.innerHTML == yearValue.substring(0,1), legal );
3635
+ i += 1000;
3636
+ } );
3637
+
3638
+ i = (Math.floor(yearValue/1000)*1000);
3639
+ this.yDiv.find('.AnyTime-cent-btn').each(
3640
+ function()
3641
+ {
3642
+ legal = ( ((!_this.earliest)||(era*(i+(era<0?0:99))>=eY)) && ((!_this.latest)||(era*(i+(era>0?0:99))<=lY)) );
3643
+ $(this).AnyTime_current( this.innerHTML == yearValue.substring(1,2), legal );
3644
+ i += 100;
3645
+ } );
3646
+
3647
+ i = (Math.floor(yearValue/100)*100);
3648
+ this.yDiv.find('.AnyTime-dec-btn').each(
3649
+ function()
3650
+ {
3651
+ legal = ( ((!_this.earliest)||(era*(i+(era<0?0:9))>=eY)) && ((!_this.latest)||(era*(i+(era>0?0:9))<=lY)) );
3652
+ $(this).AnyTime_current( this.innerHTML == yearValue.substring(2,3), legal );
3653
+ i += 10;
3654
+ } );
3655
+
3656
+ i = (Math.floor(yearValue/10)*10);
3657
+ this.yDiv.find('.AnyTime-yr-btn').each(
3658
+ function()
3659
+ {
3660
+ legal = ( ((!_this.earliest)||(era*i>=eY)) && ((!_this.latest)||(era*i<=lY)) );
3661
+ $(this).AnyTime_current( this.innerHTML == yearValue.substring(3), legal );
3662
+ i += 1;
3663
+ } );
3664
+
3665
+ this.yDiv.find('.AnyTime-bce-btn').each(
3666
+ function()
3667
+ {
3668
+ $(this).AnyTime_current( era < 0, (!_this.earliest) || ( _this.earliest < 0 ) );
3669
+ } );
3670
+ this.yDiv.find('.AnyTime-ce-btn').each(
3671
+ function()
3672
+ {
3673
+ $(this).AnyTime_current( era > 0, (!_this.latest) || ( _this.latest > 0 ) );
3674
+ } );
3675
+
3676
+ // Show change
3677
+
3678
+ this.conv.setUtcFormatOffsetAlleged(this.offMin);
3679
+ this.conv.setUtcFormatOffsetSubIndex(this.offSI);
3680
+ this.inp.val(this.conv.format(this.time)).change();
3681
+ this.upd(fBtn);
3682
+
3683
+ } // .updYDiv()
3684
+
3685
+ }; // __pickers[id] = ...
3686
+ __pickers[id].initialize(id);
3687
+
3688
+ } // AnyTime.picker =
3689
+
3690
+ //=============================================================================
3691
+ // AnyTime.setEarliest()
3692
+ //
3693
+ // Updates the earliest date/time for the picker attached to a specified
3694
+ // text field.
3695
+ //=============================================================================
3696
+
3697
+ AnyTime.setEarliest = function( id, newTime )
3698
+ {
3699
+ __pickers[id].setEarliest(newTime)
3700
+ };
3701
+
3702
+
3703
+ //=============================================================================
3704
+ // AnyTime.setLatest()
3705
+ //
3706
+ // Updates the latest date/time for the picker attached to a specified
3707
+ // text field.
3708
+ //=============================================================================
3709
+
3710
+ AnyTime.setLatest = function( id, newTime )
3711
+ {
3712
+ __pickers[id].setLatest(newTime)
3713
+ };
3714
+
3715
+
3716
+ })(jQuery); // function($)...