app_frame 0.5.5

Sign up to get free protection for your applications and to get access to all the features.
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($)...