waterfall_bourbon_neat_rails 1.6 → 1.7

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: ca653b79cd2175d242e20813e784b57e9108359a
4
- data.tar.gz: 5dec4e08e8d5161debe787da7217bcfb1ce9ec92
3
+ metadata.gz: 24a743c662a31d2c83ef4cdea868995a7811230f
4
+ data.tar.gz: 54808a0e33a4bc7c7c699f1da80d1545d2b1ac19
5
5
  SHA512:
6
- metadata.gz: 9277aa5b32c03d986b0eb032b72e6259e20a2dbb8eeb1407d2456d3f79c4faebcf1f3f0714a9839fcbeeb3a3e4eec6f9a7b38616a396765ef57102f8a94f8a42
7
- data.tar.gz: d5c91f465c2efaaed0d8d165ace3c8fbd6843f801d24d404b0518d2e67987e169fd1c42bd50762b15b2b425c2d2b0894f185da8ebf335556e61fa51f5309fa05
6
+ metadata.gz: 7c5d2dcd25a1af8a9206f76ff99abb856e2dc2fc22a22957e900ac66e6fe5496c86fd61c61bec9e856cdebbd74293269a98414d48e5f1f719fd1761b7d80ea7f
7
+ data.tar.gz: 35f39ad82784c3d0af4387961019047f75f87b96309119cd8ed183355609ecd17b7358eba587d8bf3ae369e3af6574808a923a535b14b56317cfb50a7b2b79b7
@@ -9,6 +9,7 @@
9
9
  //= require ../../libs/chosen/chosen.jquery.js
10
10
  //= require ../../libs/jQueryUI/jquery-ui.js
11
11
  //= require ../../libs/timepicker/jquery.ui.timepicker.js
12
+ //= require ../../libs/heightpicker/custom-heightpicker.js
12
13
  //= require ../../libs/bPopup/jquery-bpopup.js
13
14
  //= require ../../libs/maskJs/jquery.maskedinput.js
14
15
  //= require ../../libs/papaparse/papaparse.min.js
@@ -0,0 +1,70 @@
1
+ .ui-widget { font-size: 12px; }
2
+
3
+ /*
4
+ * Timepicker stylesheet
5
+ * Highly inspired from datepicker
6
+ * FG - Nov 2010 - Web3R
7
+ *
8
+ * version 0.0.3 : Fixed some settings, more dynamic
9
+ * version 0.0.4 : Removed width:100% on tables
10
+ * version 0.1.1 : set width 0 on tables to fix an ie6 bug
11
+ */
12
+
13
+ .ui-heightpicker-inline { display: inline; }
14
+
15
+ #ui-heightpicker-div { padding: 0.2em; background-color: #fff; }
16
+ .ui-heightpicker-table { display: inline-table; width: 0; }
17
+ .ui-heightpicker-table table { margin:0.15em 0 0 0; border-collapse: collapse; }
18
+
19
+ .ui-heightpicker-hours, .ui-heightpicker-minutes { padding: 0.2em; }
20
+
21
+ .ui-heightpicker-table .ui-heightpicker-title { line-height: 1.8em; text-align: center; }
22
+ .ui-heightpicker-table td { padding: 0.1em; width: 2.2em; }
23
+ .ui-heightpicker-table th.periods { padding: 0.1em; width: 2.2em; }
24
+
25
+ /* span for disabled cells */
26
+ .ui-heightpicker-table td span {
27
+ display:block;
28
+ padding:0.2em 0.3em 0.2em 0.5em;
29
+ width: 1.2em;
30
+
31
+ text-align:right;
32
+ text-decoration:none;
33
+ }
34
+ /* anchors for clickable cells */
35
+ .ui-heightpicker-table td a {
36
+ display:block;
37
+ padding:0.2em 0.3em 0.2em 0.5em;
38
+ cursor: pointer;
39
+ text-align:right;
40
+ text-decoration:none;
41
+ }
42
+
43
+
44
+ /* buttons and button pane styling */
45
+ .ui-heightpicker .ui-heightpicker-buttonpane {
46
+ background-image: none; margin: .7em 0 0 0; padding:0 .2em; border-left: 0; border-right: 0; border-bottom: 0;
47
+ }
48
+ .ui-heightpicker .ui-heightpicker-buttonpane button { margin: .5em .2em .4em; cursor: pointer; padding: .2em .6em .3em .6em; width:auto; overflow:visible; }
49
+ /* The close button */
50
+ .ui-heightpicker .ui-heightpicker-close { float: right }
51
+
52
+ /* the now button */
53
+ .ui-heightpicker .ui-heightpicker-now { float: left; }
54
+
55
+ /* the deselect button */
56
+ .ui-heightpicker .ui-heightpicker-deselect { float: left; }
57
+
58
+
59
+ /* IE6 IFRAME FIX (taken from datepicker 1.5.3 */
60
+ .ui-heightpicker-cover {
61
+ display: none; /*sorry for IE5*/
62
+ display/**/: block; /*sorry for IE5*/
63
+ position: absolute; /*must have*/
64
+ z-index: -1; /*must have*/
65
+ filter: mask(); /*must have*/
66
+ top: -4px; /*must have*/
67
+ left: -4px; /*must have*/
68
+ width: 200px; /*must have*/
69
+ height: 200px; /*must have*/
70
+ }
@@ -0,0 +1,1406 @@
1
+ //this is a modified version of jquery ui heightpicker
2
+ //extend heightpicker
3
+
4
+ (function ($) {
5
+
6
+ $.extend($.heightpicker, { heightpicker: { version: "0.3.4"} });
7
+
8
+ var PROP_NAME = 'heightpicker',
9
+ tpuuid = "";
10
+
11
+ /* Time picker manager.
12
+ Use the singleton instance of this class, $.heightpicker, to interact with the time picker.
13
+ Settings for (groups of) time pickers are maintained in an instance object,
14
+ allowing multiple different settings on the same page. */
15
+
16
+ function Heightpicker() {
17
+ this.debug = true; // Change this to true to start debugging
18
+ this._curInst = null; // The current instance in use
19
+ this._disabledInputs = []; // List of time picker inputs that have been disabled
20
+ this._heightpickerShowing = false; // True if the popup picker is showing , false if not
21
+ this._inDialog = false; // True if showing within a "dialog", false if not
22
+ this._dialogClass = 'ui-heightpicker-dialog'; // The name of the dialog marker class
23
+ this._mainDivId = 'ui-heightpicker-div'; // The ID of the main heightpicker division
24
+ this._inlineClass = 'ui-heightpicker-inline'; // The name of the inline marker class
25
+ this._currentClass = 'ui-heightpicker-current'; // The name of the current hour / minutes marker class
26
+ this._dayOverClass = 'ui-heightpicker-days-cell-over'; // The name of the day hover marker class
27
+
28
+ this.regional = []; // Available regional settings, indexed by language code
29
+ this.regional[''] = { // Default regional settings
30
+ hourText: 'Hour', // Display text for hours section
31
+ minuteText: 'Minute', // Display text for minutes link
32
+ amPmText: ['AM', 'PM'], // Display text for AM PM
33
+ closeButtonText: 'Done', // Text for the confirmation button (ok button)
34
+ nowButtonText: 'Now', // Text for the now button
35
+ deselectButtonText: 'Deselect' // Text for the deselect button
36
+ };
37
+ this._defaults = { // Global defaults for all the time picker instances
38
+ showOn: 'focus', // 'focus' for popup on focus,
39
+ // 'button' for trigger button, or 'both' for either (not yet implemented)
40
+ button: null, // 'button' element that will trigger the heightpicker
41
+ showAnim: 'fadeIn', // Name of jQuery animation for popup
42
+ showOptions: {}, // Options for enhanced animations
43
+ appendText: '', // Display text following the input box, e.g. showing the format
44
+
45
+ beforeShow: null, // Define a callback function executed before the heightpicker is shown
46
+ onSelect: null, // Define a callback function when a hour / minutes is selected
47
+ onClose: null, // Define a callback function when the heightpicker is closed
48
+
49
+ timeSeparator: ':', // The character to use to separate hours and minutes.
50
+ periodSeparator: ' ', // The character to use to separate the time from the time period.
51
+ showPeriod: false, // Define whether or not to show AM/PM with selected time
52
+ showPeriodLabels: true, // Show the AM/PM labels on the left of the time picker
53
+ showLeadingZero: true, // Define whether or not to show a leading zero for hours < 10. [true/false]
54
+ showMinutesLeadingZero: true, // Define whether or not to show a leading zero for minutes < 10.
55
+ altField: '', // Selector for an alternate field to store selected time into
56
+ defaultTime: 'now', // Used as default time when input field is empty or for inline timePicker
57
+ // (set to 'now' for the current time, '' for no highlighted time)
58
+ myPosition: 'left top', // Position of the dialog relative to the input.
59
+ // see the position utility for more info : http://jqueryui.com/demos/position/
60
+ atPosition: 'left bottom', // Position of the input element to match
61
+ // Note : if the position utility is not loaded, the heightpicker will attach left top to left bottom
62
+ //NEW: 2011-02-03
63
+ onHourShow: null, // callback for enabling / disabling on selectable hours ex : function(hour) { return true; }
64
+ onMinuteShow: null, // callback for enabling / disabling on time selection ex : function(hour,minute) { return true; }
65
+
66
+ hours: {
67
+ starts: 0, // first displayed hour
68
+ ends: 23 // last displayed hour
69
+ },
70
+ minutes: {
71
+ starts: 0, // first displayed minute
72
+ ends: 55, // last displayed minute
73
+ interval: 5, // interval of displayed minutes
74
+ manual: [] // optional extra manual entries for minutes
75
+ },
76
+ rows: 4, // number of rows for the input tables, minimum 2, makes more sense if you use multiple of 2
77
+ // 2011-08-05 0.2.4
78
+ showHours: true, // display the hours section of the dialog
79
+ showMinutes: true, // display the minute section of the dialog
80
+ optionalMinutes: false, // optionally parse inputs of whole hours with minutes omitted
81
+
82
+ // buttons
83
+ showCloseButton: false, // shows an OK button to confirm the edit
84
+ showNowButton: false, // Shows the 'now' button
85
+ showDeselectButton: false, // Shows the deselect time button
86
+
87
+ maxTime: {
88
+ hour: null,
89
+ minute: null
90
+ },
91
+ minTime: {
92
+ hour: null,
93
+ minute: null
94
+ }
95
+
96
+ };
97
+ $.extend(this._defaults, this.regional['']);
98
+
99
+ this.tpDiv = $('<div id="' + this._mainDivId + '" class="ui-heightpicker ui-widget ui-helper-clearfix ui-corner-all " style="display: none"></div>');
100
+ }
101
+
102
+ $.extend(Heightpicker.prototype, {
103
+ /* Class name added to elements to indicate already configured with a time picker. */
104
+ markerClassName: 'hasHeightpicker',
105
+
106
+ /* Debug logging (if enabled). */
107
+ log: function () {
108
+ if (this.debug)
109
+ console.log.apply('', arguments);
110
+ },
111
+
112
+ _widgetHeightpicker: function () {
113
+ return this.tpDiv;
114
+ },
115
+
116
+ /* Override the default settings for all instances of the time picker.
117
+ @param settings object - the new settings to use as defaults (anonymous object)
118
+ @return the manager object */
119
+ setDefaults: function (settings) {
120
+ extendRemove(this._defaults, settings || {});
121
+ return this;
122
+ },
123
+
124
+ /* Attach the time picker to a jQuery selection.
125
+ @param target element - the target input field or division or span
126
+ @param settings object - the new settings to use for this time picker instance (anonymous) */
127
+ _attachHeightpicker: function (target, settings) {
128
+ // check for settings on the control itself - in namespace 'time:'
129
+ var inlineSettings = null;
130
+ for (var attrName in this._defaults) {
131
+ var attrValue = target.getAttribute('time:' + attrName);
132
+ if (attrValue) {
133
+ inlineSettings = inlineSettings || {};
134
+ try {
135
+ inlineSettings[attrName] = eval(attrValue);
136
+ } catch (err) {
137
+ inlineSettings[attrName] = attrValue;
138
+ }
139
+ }
140
+ }
141
+ var nodeName = target.nodeName.toLowerCase();
142
+ var inline = (nodeName == 'div' || nodeName == 'span');
143
+
144
+ if (!target.id) {
145
+ this.uuid += 1;
146
+ target.id = 'tp' + this.uuid;
147
+ }
148
+ var inst = this._newInst($(target), inline);
149
+ inst.settings = $.extend({}, settings || {}, inlineSettings || {});
150
+ if (nodeName == 'input') {
151
+ this._connectHeightpicker(target, inst);
152
+ // init inst.hours and inst.minutes from the input value
153
+ this._setTimeFromField(inst);
154
+ } else if (inline) {
155
+ this._inlineHeightpicker(target, inst);
156
+ }
157
+
158
+
159
+ },
160
+
161
+ /* Create a new instance object. */
162
+ _newInst: function (target, inline) {
163
+ var id = target[0].id.replace(/([^A-Za-z0-9_-])/g, '\\\\$1'); // escape jQuery meta chars
164
+ return {
165
+ id: id, input: target, // associated target
166
+ inline: inline, // is heightpicker inline or not :
167
+ tpDiv: (!inline ? this.tpDiv : // presentation div
168
+ $('<div class="' + this._inlineClass + ' ui-heightpicker ui-widget ui-helper-clearfix"></div>'))
169
+ };
170
+ },
171
+
172
+ /* Attach the time picker to an input field. */
173
+ _connectHeightpicker: function (target, inst) {
174
+ var input = $(target);
175
+ inst.append = $([]);
176
+ inst.trigger = $([]);
177
+ if (input.hasClass(this.markerClassName)) { return; }
178
+ this._attachments(input, inst);
179
+ input.addClass(this.markerClassName).
180
+ keydown(this._doKeyDown).
181
+ keyup(this._doKeyUp).
182
+ bind("setData.heightpicker", function (event, key, value) {
183
+ inst.settings[key] = value;
184
+ }).
185
+ bind("getData.heightpicker", function (event, key) {
186
+ return this._get(inst, key);
187
+ });
188
+ $.data(target, PROP_NAME, inst);
189
+ },
190
+
191
+ /* Handle keystrokes. */
192
+ _doKeyDown: function (event) {
193
+ var inst = $.heightpicker._getInst(event.target);
194
+ var handled = true;
195
+ inst._keyEvent = true;
196
+ if ($.heightpicker._heightpickerShowing) {
197
+ switch (event.keyCode) {
198
+ case 9: $.heightpicker._hideHeightpicker();
199
+ handled = false;
200
+ break; // hide on tab out
201
+ case 13:
202
+ $.heightpicker._updateSelectedValue(inst);
203
+ $.heightpicker._hideHeightpicker();
204
+
205
+ return false; // don't submit the form
206
+ break; // select the value on enter
207
+ case 27: $.heightpicker._hideHeightpicker();
208
+ break; // hide on escape
209
+ default: handled = false;
210
+ }
211
+ }
212
+ else if (event.keyCode == 36 && event.ctrlKey) { // display the time picker on ctrl+home
213
+ $.heightpicker._showHeightpicker(this);
214
+ }
215
+ else {
216
+ handled = false;
217
+ }
218
+ if (handled) {
219
+ event.preventDefault();
220
+ event.stopPropagation();
221
+ }
222
+ },
223
+
224
+ /* Update selected time on keyUp */
225
+ /* Added verion 0.0.5 */
226
+ _doKeyUp: function (event) {
227
+ var inst = $.heightpicker._getInst(event.target);
228
+ $.heightpicker._setTimeFromField(inst);
229
+ $.heightpicker._updateHeightpicker(inst);
230
+ },
231
+
232
+ /* Make attachments based on settings. */
233
+ _attachments: function (input, inst) {
234
+ var appendText = this._get(inst, 'appendText');
235
+ var isRTL = this._get(inst, 'isRTL');
236
+ if (inst.append) { inst.append.remove(); }
237
+ if (appendText) {
238
+ inst.append = $('<span class="' + this._appendClass + '">' + appendText + '</span>');
239
+ input[isRTL ? 'before' : 'after'](inst.append);
240
+ }
241
+ input.unbind('focus.heightpicker', this._showHeightpicker);
242
+ input.unbind('click.heightpicker', this._adjustZIndex);
243
+
244
+ if (inst.trigger) { inst.trigger.remove(); }
245
+
246
+ var showOn = this._get(inst, 'showOn');
247
+ if (showOn == 'focus' || showOn == 'both') { // pop-up time picker when in the marked field
248
+ input.bind("focus.heightpicker", this._showHeightpicker);
249
+ input.bind("click.heightpicker", this._adjustZIndex);
250
+ }
251
+ if (showOn == 'button' || showOn == 'both') { // pop-up time picker when 'button' element is clicked
252
+ var button = this._get(inst, 'button');
253
+
254
+ // Add button if button element is not set
255
+ if(button == null) {
256
+ button = $('<button class="ui-heightpicker-trigger" type="button">...</button>');
257
+ input.after(button);
258
+ }
259
+
260
+ $(button).bind("click.heightpicker", function () {
261
+ if ($.heightpicker._heightpickerShowing && $.heightpicker._lastInput == input[0]) {
262
+ $.heightpicker._hideHeightpicker();
263
+ } else if (!inst.input.is(':disabled')) {
264
+ $.heightpicker._showHeightpicker(input[0]);
265
+ }
266
+ return false;
267
+ });
268
+
269
+ }
270
+ },
271
+
272
+
273
+ /* Attach an inline time picker to a div. */
274
+ _inlineHeightpicker: function(target, inst) {
275
+ var divSpan = $(target);
276
+ if (divSpan.hasClass(this.markerClassName))
277
+ return;
278
+ divSpan.addClass(this.markerClassName).append(inst.tpDiv).
279
+ bind("setData.heightpicker", function(event, key, value){
280
+ inst.settings[key] = value;
281
+ }).bind("getData.heightpicker", function(event, key){
282
+ return this._get(inst, key);
283
+ });
284
+ $.data(target, PROP_NAME, inst);
285
+
286
+ this._setTimeFromField(inst);
287
+ this._updateHeightpicker(inst);
288
+ inst.tpDiv.show();
289
+ },
290
+
291
+ _adjustZIndex: function(input) {
292
+ input = input.target || input;
293
+ var inst = $.heightpicker._getInst(input);
294
+ inst.tpDiv.css('zIndex', $.heightpicker._getZIndex(input) +1);
295
+ },
296
+
297
+ /* Pop-up the time picker for a given input field.
298
+ @param input element - the input field attached to the time picker or
299
+ event - if triggered by focus */
300
+ _showHeightpicker: function (input) {
301
+ input = input.target || input;
302
+ if (input.nodeName.toLowerCase() != 'input') { input = $('input', input.parentNode)[0]; } // find from button/image trigger
303
+
304
+ if ($.heightpicker._isDisabledHeightpicker(input) || $.heightpicker._lastInput == input) { return; } // already here
305
+
306
+ // fix v 0.0.8 - close current heightpicker before showing another one
307
+ $.heightpicker._hideHeightpicker();
308
+
309
+ var inst = $.heightpicker._getInst(input);
310
+ if ($.heightpicker._curInst && $.heightpicker._curInst != inst) {
311
+ $.heightpicker._curInst.tpDiv.stop(true, true);
312
+ }
313
+ var beforeShow = $.heightpicker._get(inst, 'beforeShow');
314
+ extendRemove(inst.settings, (beforeShow ? beforeShow.apply(input, [input, inst]) : {}));
315
+ inst.lastVal = null;
316
+ $.heightpicker._lastInput = input;
317
+
318
+ $.heightpicker._setTimeFromField(inst);
319
+
320
+ // calculate default position
321
+ if ($.heightpicker._inDialog) { input.value = ''; } // hide cursor
322
+ if (!$.heightpicker._pos) { // position below input
323
+ $.heightpicker._pos = $.heightpicker._findPos(input);
324
+ $.heightpicker._pos[1] += input.offsetHeight; // add the height
325
+ }
326
+ var isFixed = false;
327
+ $(input).parents().each(function () {
328
+ isFixed |= $(this).css('position') == 'fixed';
329
+ return !isFixed;
330
+ });
331
+
332
+ var offset = { left: $.heightpicker._pos[0], top: $.heightpicker._pos[1] };
333
+
334
+ $.heightpicker._pos = null;
335
+ // determine sizing offscreen
336
+ inst.tpDiv.css({ position: 'absolute', display: 'block', top: '-1000px' });
337
+ $.heightpicker._updateHeightpicker(inst);
338
+
339
+
340
+ // position with the ui position utility, if loaded
341
+ if ( ( ! inst.inline ) && ( typeof $.ui.position == 'object' ) ) {
342
+ inst.tpDiv.position({
343
+ of: inst.input,
344
+ my: $.heightpicker._get( inst, 'myPosition' ),
345
+ at: $.heightpicker._get( inst, 'atPosition' ),
346
+ // offset: $( "#offset" ).val(),
347
+ // using: using,
348
+ collision: 'flip'
349
+ });
350
+ var offset = inst.tpDiv.offset();
351
+ $.heightpicker._pos = [offset.top, offset.left];
352
+ }
353
+
354
+
355
+ // reset clicked state
356
+ inst._hoursClicked = false;
357
+ inst._minutesClicked = false;
358
+
359
+ // fix width for dynamic number of time pickers
360
+ // and adjust position before showing
361
+ offset = $.heightpicker._checkOffset(inst, offset, isFixed);
362
+ inst.tpDiv.css({ position: ($.heightpicker._inDialog && $.blockUI ?
363
+ 'static' : (isFixed ? 'fixed' : 'absolute')), display: 'none',
364
+ left: offset.left + 'px', top: offset.top + 'px'
365
+ });
366
+ if ( ! inst.inline ) {
367
+ var showAnim = $.heightpicker._get(inst, 'showAnim');
368
+ var duration = $.heightpicker._get(inst, 'duration');
369
+
370
+ var postProcess = function () {
371
+ $.heightpicker._heightpickerShowing = true;
372
+ var borders = $.heightpicker._getBorders(inst.tpDiv);
373
+ inst.tpDiv.find('iframe.ui-heightpicker-cover'). // IE6- only
374
+ css({ left: -borders[0], top: -borders[1],
375
+ width: inst.tpDiv.outerWidth(), height: inst.tpDiv.outerHeight()
376
+ });
377
+ };
378
+
379
+ // Fixed the zIndex problem for real (I hope) - FG - v 0.2.9
380
+ $.heightpicker._adjustZIndex(input);
381
+ //inst.tpDiv.css('zIndex', $.heightpicker._getZIndex(input) +1);
382
+
383
+ if ($.effects && $.effects[showAnim]) {
384
+ inst.tpDiv.show(showAnim, $.heightpicker._get(inst, 'showOptions'), duration, postProcess);
385
+ }
386
+ else {
387
+ inst.tpDiv.show((showAnim ? duration : null), postProcess);
388
+ }
389
+ if (!showAnim || !duration) { postProcess(); }
390
+ if (inst.input.is(':visible') && !inst.input.is(':disabled')) { inst.input.focus(); }
391
+ $.heightpicker._curInst = inst;
392
+ }
393
+ },
394
+
395
+ // This is an enhanced copy of the zIndex function of UI core 1.8.?? For backward compatibility.
396
+ // Enhancement returns maximum zindex value discovered while traversing parent elements,
397
+ // rather than the first zindex value found. Ensures the heightpicker popup will be in front,
398
+ // even in funky scenarios like non-jq dialog containers with large fixed zindex values and
399
+ // nested zindex-influenced elements of their own.
400
+ _getZIndex: function (target) {
401
+ var elem = $(target);
402
+ var maxValue = 0;
403
+ var position, value;
404
+ while (elem.length && elem[0] !== document) {
405
+ position = elem.css("position");
406
+ if (position === "absolute" || position === "relative" || position === "fixed") {
407
+ value = parseInt(elem.css("zIndex"), 10);
408
+ if (!isNaN(value) && value !== 0) {
409
+ if (value > maxValue) { maxValue = value; }
410
+ }
411
+ }
412
+ elem = elem.parent();
413
+ }
414
+
415
+ return maxValue;
416
+ },
417
+
418
+ /* Refresh the time picker
419
+ @param target element - The target input field or inline container element. */
420
+ _refreshHeightpicker: function(target) {
421
+ var inst = this._getInst(target);
422
+ if (inst) {
423
+ this._updateHeightpicker(inst);
424
+ }
425
+ },
426
+
427
+
428
+ /* Generate the time picker content. */
429
+ _updateHeightpicker: function (inst) {
430
+ inst.tpDiv.empty().append(this._generateHTML(inst));
431
+ this._rebindDialogEvents(inst);
432
+
433
+ },
434
+
435
+ _rebindDialogEvents: function (inst) {
436
+ var borders = $.heightpicker._getBorders(inst.tpDiv),
437
+ self = this;
438
+ inst.tpDiv
439
+ .find('iframe.ui-heightpicker-cover') // IE6- only
440
+ .css({ left: -borders[0], top: -borders[1],
441
+ width: inst.tpDiv.outerWidth(), height: inst.tpDiv.outerHeight()
442
+ })
443
+ .end()
444
+ // after the picker html is appended bind the click & double click events (faster in IE this way
445
+ // then letting the browser interpret the inline events)
446
+ // the binding for the minute cells also exists in _updateMinuteDisplay
447
+ .find('.ui-heightpicker-minute-cell')
448
+ .unbind()
449
+ .bind("click", { fromDoubleClick:false }, $.proxy($.heightpicker.selectMinutes, this))
450
+ .bind("dblclick", { fromDoubleClick:true }, $.proxy($.heightpicker.selectMinutes, this))
451
+ .end()
452
+ .find('.ui-heightpicker-hour-cell')
453
+ .unbind()
454
+ .bind("click", { fromDoubleClick:false }, $.proxy($.heightpicker.selectHours, this))
455
+ .bind("dblclick", { fromDoubleClick:true }, $.proxy($.heightpicker.selectHours, this))
456
+ .end()
457
+ .find('.ui-heightpicker td a')
458
+ .unbind()
459
+ .bind('mouseout', function () {
460
+ $(this).removeClass('ui-state-hover');
461
+ if (this.className.indexOf('ui-heightpicker-prev') != -1) $(this).removeClass('ui-heightpicker-prev-hover');
462
+ if (this.className.indexOf('ui-heightpicker-next') != -1) $(this).removeClass('ui-heightpicker-next-hover');
463
+ })
464
+ .bind('mouseover', function () {
465
+ if ( ! self._isDisabledHeightpicker(inst.inline ? inst.tpDiv.parent()[0] : inst.input[0])) {
466
+ $(this).parents('.ui-heightpicker-calendar').find('a').removeClass('ui-state-hover');
467
+ $(this).addClass('ui-state-hover');
468
+ if (this.className.indexOf('ui-heightpicker-prev') != -1) $(this).addClass('ui-heightpicker-prev-hover');
469
+ if (this.className.indexOf('ui-heightpicker-next') != -1) $(this).addClass('ui-heightpicker-next-hover');
470
+ }
471
+ })
472
+ .end()
473
+ .find('.' + this._dayOverClass + ' a')
474
+ .trigger('mouseover')
475
+ .end()
476
+ .find('.ui-heightpicker-now').bind("click", function(e) {
477
+ $.heightpicker.selectNow(e);
478
+ }).end()
479
+ .find('.ui-heightpicker-deselect').bind("click",function(e) {
480
+ $.heightpicker.deselectTime(e);
481
+ }).end()
482
+ .find('.ui-heightpicker-close').bind("click",function(e) {
483
+ $.heightpicker._hideHeightpicker();
484
+ }).end();
485
+ },
486
+
487
+ /* Generate the HTML for the current state of the time picker. */
488
+ _generateHTML: function (inst) {
489
+
490
+ var h, m, row, col, html, hoursHtml, minutesHtml = '',
491
+ showPeriod = (this._get(inst, 'showPeriod') == true),
492
+ showPeriodLabels = (this._get(inst, 'showPeriodLabels') == true),
493
+ showLeadingZero = (this._get(inst, 'showLeadingZero') == true),
494
+ showHours = (this._get(inst, 'showHours') == true),
495
+ showMinutes = (this._get(inst, 'showMinutes') == true),
496
+ amPmText = this._get(inst, 'amPmText'),
497
+ rows = this._get(inst, 'rows'),
498
+ amRows = 0,
499
+ pmRows = 0,
500
+ amItems = 0,
501
+ pmItems = 0,
502
+ amFirstRow = 0,
503
+ pmFirstRow = 0,
504
+ hours = Array(),
505
+ hours_options = this._get(inst, 'hours'),
506
+ hoursPerRow = null,
507
+ hourCounter = 0,
508
+ hourLabel = this._get(inst, 'hourText'),
509
+ showCloseButton = this._get(inst, 'showCloseButton'),
510
+ closeButtonText = this._get(inst, 'closeButtonText'),
511
+ showNowButton = this._get(inst, 'showNowButton'),
512
+ nowButtonText = this._get(inst, 'nowButtonText'),
513
+ showDeselectButton = this._get(inst, 'showDeselectButton'),
514
+ deselectButtonText = this._get(inst, 'deselectButtonText'),
515
+ showButtonPanel = showCloseButton || showNowButton || showDeselectButton;
516
+
517
+
518
+
519
+ // prepare all hours and minutes, makes it easier to distribute by rows
520
+ for (h = hours_options.starts; h <= hours_options.ends; h++) {
521
+ hours.push (h);
522
+ }
523
+ hoursPerRow = Math.ceil(hours.length / rows); // always round up
524
+
525
+ if (showPeriodLabels) {
526
+ for (hourCounter = 0; hourCounter < hours.length; hourCounter++) {
527
+ if (hours[hourCounter] < 12) {
528
+ amItems++;
529
+ }
530
+ else {
531
+ pmItems++;
532
+ }
533
+ }
534
+ hourCounter = 0;
535
+
536
+ amRows = Math.floor(amItems / hours.length * rows);
537
+ pmRows = Math.floor(pmItems / hours.length * rows);
538
+
539
+ // assign the extra row to the period that is more densely populated
540
+ if (rows != amRows + pmRows) {
541
+ // Make sure: AM Has Items and either PM Does Not, AM has no rows yet, or AM is more dense
542
+ if (amItems && (!pmItems || !amRows || (pmRows && amItems / amRows >= pmItems / pmRows))) {
543
+ amRows++;
544
+ } else {
545
+ pmRows++;
546
+ }
547
+ }
548
+ amFirstRow = Math.min(amRows, 1);
549
+ pmFirstRow = amRows + 1;
550
+
551
+ if (amRows == 0) {
552
+ hoursPerRow = Math.ceil(pmItems / pmRows);
553
+ } else if (pmRows == 0) {
554
+ hoursPerRow = Math.ceil(amItems / amRows);
555
+ } else {
556
+ hoursPerRow = Math.ceil(Math.max(amItems / amRows, pmItems / pmRows));
557
+ }
558
+ }
559
+
560
+
561
+ html = '<table class="ui-heightpicker-table ui-widget-content ui-corner-all"><tr>';
562
+
563
+ if (showHours) {
564
+
565
+ html += '<td class="ui-heightpicker-hours">' +
566
+ '<div class="ui-heightpicker-title ui-widget-header ui-helper-clearfix ui-corner-all">' +
567
+ hourLabel +
568
+ '</div>' +
569
+ '<table class="ui-heightpicker">';
570
+
571
+ for (row = 1; row <= rows; row++) {
572
+ html += '<tr>';
573
+ // AM
574
+ if (row == amFirstRow && showPeriodLabels) {
575
+ html += '<th rowspan="' + amRows.toString() + '" class="periods" scope="row">' + amPmText[0] + '</th>';
576
+ }
577
+ // PM
578
+ if (row == pmFirstRow && showPeriodLabels) {
579
+ html += '<th rowspan="' + pmRows.toString() + '" class="periods" scope="row">' + amPmText[1] + '</th>';
580
+ }
581
+ for (col = 1; col <= hoursPerRow; col++) {
582
+ if (showPeriodLabels && row < pmFirstRow && hours[hourCounter] >= 12) {
583
+ html += this._generateHTMLHourCell(inst, undefined, showPeriod, showLeadingZero);
584
+ } else {
585
+ html += this._generateHTMLHourCell(inst, hours[hourCounter], showPeriod, showLeadingZero);
586
+ hourCounter++;
587
+ }
588
+ }
589
+ html += '</tr>';
590
+ }
591
+ html += '</table>' + // Close the hours cells table
592
+ '</td>'; // Close the Hour td
593
+ }
594
+
595
+ if (showMinutes) {
596
+ html += '<td class="ui-heightpicker-minutes">';
597
+ html += this._generateHTMLMinutes(inst);
598
+ html += '</td>';
599
+ }
600
+
601
+ html += '</tr>';
602
+
603
+
604
+ if (showButtonPanel) {
605
+ var buttonPanel = '<tr><td colspan="3"><div class="ui-heightpicker-buttonpane ui-widget-content">';
606
+ if (showNowButton) {
607
+ buttonPanel += '<button type="button" class="ui-heightpicker-now ui-state-default ui-corner-all" '
608
+ + ' data-heightpicker-instance-id="#' + inst.id.replace(/\\\\/g,"\\") + '" >'
609
+ + nowButtonText + '</button>';
610
+ }
611
+ if (showDeselectButton) {
612
+ buttonPanel += '<button type="button" class="ui-heightpicker-deselect ui-state-default ui-corner-all" '
613
+ + ' data-heightpicker-instance-id="#' + inst.id.replace(/\\\\/g,"\\") + '" >'
614
+ + deselectButtonText + '</button>';
615
+ }
616
+ if (showCloseButton) {
617
+ buttonPanel += '<button type="button" class="ui-heightpicker-close ui-state-default ui-corner-all" '
618
+ + ' data-heightpicker-instance-id="#' + inst.id.replace(/\\\\/g,"\\") + '" >'
619
+ + closeButtonText + '</button>';
620
+ }
621
+
622
+ html += buttonPanel + '</div></td></tr>';
623
+ }
624
+ html += '</table>';
625
+
626
+ return html;
627
+ },
628
+
629
+ /* Special function that update the minutes selection in currently visible heightpicker
630
+ * called on hour selection when onMinuteShow is defined */
631
+ _updateMinuteDisplay: function (inst) {
632
+ var newHtml = this._generateHTMLMinutes(inst);
633
+ inst.tpDiv.find('td.ui-heightpicker-minutes').html(newHtml);
634
+ this._rebindDialogEvents(inst);
635
+ // after the picker html is appended bind the click & double click events (faster in IE this way
636
+ // then letting the browser interpret the inline events)
637
+ // yes I know, duplicate code, sorry
638
+ /* .find('.ui-heightpicker-minute-cell')
639
+ .bind("click", { fromDoubleClick:false }, $.proxy($.heightpicker.selectMinutes, this))
640
+ .bind("dblclick", { fromDoubleClick:true }, $.proxy($.heightpicker.selectMinutes, this));
641
+ */
642
+
643
+ },
644
+
645
+ /*
646
+ * Generate the minutes table
647
+ * This is separated from the _generateHTML function because is can be called separately (when hours changes)
648
+ */
649
+ _generateHTMLMinutes: function (inst) {
650
+
651
+ var m, row, html = '',
652
+ rows = this._get(inst, 'rows'),
653
+ minutes = Array(),
654
+ minutes_options = this._get(inst, 'minutes'),
655
+ minutesPerRow = null,
656
+ minuteCounter = 0,
657
+ showMinutesLeadingZero = (this._get(inst, 'showMinutesLeadingZero') == true),
658
+ onMinuteShow = this._get(inst, 'onMinuteShow'),
659
+ minuteLabel = this._get(inst, 'minuteText');
660
+
661
+ if ( ! minutes_options.starts) {
662
+ minutes_options.starts = 0;
663
+ }
664
+ if ( ! minutes_options.ends) {
665
+ minutes_options.ends = 59;
666
+ }
667
+ if ( ! minutes_options.manual) {
668
+ minutes_options.manual = [];
669
+ }
670
+ for (m = minutes_options.starts; m <= minutes_options.ends; m += minutes_options.interval) {
671
+ minutes.push(m);
672
+ }
673
+ for (i = 0; i < minutes_options.manual.length;i++) {
674
+ var currMin = minutes_options.manual[i];
675
+
676
+ // Validate & filter duplicates of manual minute input
677
+ if (typeof currMin != 'number' || currMin < 0 || currMin > 59 || $.inArray(currMin, minutes) >= 0) {
678
+ continue;
679
+ }
680
+ minutes.push(currMin);
681
+ }
682
+
683
+ // Sort to get correct order after adding manual minutes
684
+ // Use compare function to sort by number, instead of string (default)
685
+ minutes.sort(function(a, b) {
686
+ return a-b;
687
+ });
688
+
689
+ minutesPerRow = Math.round(minutes.length / rows + 0.49); // always round up
690
+
691
+ /*
692
+ * The minutes table
693
+ */
694
+ // if currently selected minute is not enabled, we have a problem and need to select a new minute.
695
+ if (onMinuteShow &&
696
+ (onMinuteShow.apply((inst.input ? inst.input[0] : null), [inst.hours , inst.minutes]) == false) ) {
697
+ // loop minutes and select first available
698
+ for (minuteCounter = 0; minuteCounter < minutes.length; minuteCounter += 1) {
699
+ m = minutes[minuteCounter];
700
+ if (onMinuteShow.apply((inst.input ? inst.input[0] : null), [inst.hours, m])) {
701
+ inst.minutes = m;
702
+ break;
703
+ }
704
+ }
705
+ }
706
+
707
+
708
+
709
+ html += '<div class="ui-heightpicker-title ui-widget-header ui-helper-clearfix ui-corner-all">' +
710
+ minuteLabel +
711
+ '</div>' +
712
+ '<table class="ui-heightpicker">';
713
+
714
+ minuteCounter = 0;
715
+ for (row = 1; row <= rows; row++) {
716
+ html += '<tr>';
717
+ while (minuteCounter < row * minutesPerRow) {
718
+ var m = minutes[minuteCounter];
719
+ var displayText = '';
720
+ if (m !== undefined ) {
721
+ displayText = (m < 10) && showMinutesLeadingZero ? "0" + m.toString() : m.toString();
722
+ }
723
+ html += this._generateHTMLMinuteCell(inst, m, displayText);
724
+ minuteCounter++;
725
+ }
726
+ html += '</tr>';
727
+ }
728
+
729
+ html += '</table>';
730
+
731
+ return html;
732
+ },
733
+
734
+ /* Generate the content of a "Hour" cell */
735
+ _generateHTMLHourCell: function (inst, hour, showPeriod, showLeadingZero) {
736
+
737
+ var displayHour = hour;
738
+ if ((hour > 12) && showPeriod) {
739
+ displayHour = hour - 12;
740
+ }
741
+ if ((displayHour == 0) && showPeriod) {
742
+ displayHour = 12;
743
+ }
744
+ if ((displayHour < 10) && showLeadingZero) {
745
+ displayHour = '0' + displayHour;
746
+ }
747
+
748
+ var html = "";
749
+ var enabled = true;
750
+ var onHourShow = this._get(inst, 'onHourShow'); //custom callback
751
+ var maxTime = this._get(inst, 'maxTime');
752
+ var minTime = this._get(inst, 'minTime');
753
+
754
+ if (hour == undefined) {
755
+ html = '<td><span class="ui-state-default ui-state-disabled">&nbsp;</span></td>';
756
+ return html;
757
+ }
758
+
759
+ if (onHourShow) {
760
+ enabled = onHourShow.apply((inst.input ? inst.input[0] : null), [hour]);
761
+ }
762
+
763
+ if (enabled) {
764
+ if ( !isNaN(parseInt(maxTime.hour)) && hour > maxTime.hour ) enabled = false;
765
+ if ( !isNaN(parseInt(minTime.hour)) && hour < minTime.hour ) enabled = false;
766
+ }
767
+
768
+ if (enabled) {
769
+ html = '<td class="ui-heightpicker-hour-cell" data-heightpicker-instance-id="#' + inst.id.replace(/\\\\/g,"\\") + '" data-hour="' + hour.toString() + '">' +
770
+ '<a class="ui-state-default ' +
771
+ (hour == inst.hours ? 'ui-state-active' : '') +
772
+ '">' +
773
+ displayHour.toString() +
774
+ '</a></td>';
775
+ }
776
+ else {
777
+ html =
778
+ '<td>' +
779
+ '<span class="ui-state-default ui-state-disabled ' +
780
+ (hour == inst.hours ? ' ui-state-active ' : ' ') +
781
+ '">' +
782
+ displayHour.toString() +
783
+ '</span>' +
784
+ '</td>';
785
+ }
786
+ return html;
787
+ },
788
+
789
+ /* Generate the content of a "Hour" cell */
790
+ _generateHTMLMinuteCell: function (inst, minute, displayText) {
791
+ var html = "";
792
+ var enabled = true;
793
+ var hour = inst.hours;
794
+ var onMinuteShow = this._get(inst, 'onMinuteShow'); //custom callback
795
+ var maxTime = this._get(inst, 'maxTime');
796
+ var minTime = this._get(inst, 'minTime');
797
+
798
+ if (onMinuteShow) {
799
+ //NEW: 2011-02-03 we should give the hour as a parameter as well!
800
+ enabled = onMinuteShow.apply((inst.input ? inst.input[0] : null), [inst.hours,minute]); //trigger callback
801
+ }
802
+
803
+ if (minute == undefined) {
804
+ html = '<td><span class="ui-state-default ui-state-disabled">&nbsp;</span></td>';
805
+ return html;
806
+ }
807
+
808
+ if (enabled && hour !== null) {
809
+ if ( !isNaN(parseInt(maxTime.hour)) && !isNaN(parseInt(maxTime.minute)) && hour >= maxTime.hour && minute > maxTime.minute ) enabled = false;
810
+ if ( !isNaN(parseInt(minTime.hour)) && !isNaN(parseInt(minTime.minute)) && hour <= minTime.hour && minute < minTime.minute ) enabled = false;
811
+ }
812
+
813
+ if (enabled) {
814
+ html = '<td class="ui-heightpicker-minute-cell" data-heightpicker-instance-id="#' + inst.id.replace(/\\\\/g,"\\") + '" data-minute="' + minute.toString() + '" >' +
815
+ '<a class="ui-state-default ' +
816
+ (minute == inst.minutes ? 'ui-state-active' : '') +
817
+ '" >' +
818
+ displayText +
819
+ '</a></td>';
820
+ }
821
+ else {
822
+
823
+ html = '<td>' +
824
+ '<span class="ui-state-default ui-state-disabled" >' +
825
+ displayText +
826
+ '</span>' +
827
+ '</td>';
828
+ }
829
+ return html;
830
+ },
831
+
832
+
833
+ /* Detach a heightpicker from its control.
834
+ @param target element - the target input field or division or span */
835
+ _destroyHeightpicker: function(target) {
836
+ var $target = $(target);
837
+ var inst = $.data(target, PROP_NAME);
838
+ if (!$target.hasClass(this.markerClassName)) {
839
+ return;
840
+ }
841
+ var nodeName = target.nodeName.toLowerCase();
842
+ $.removeData(target, PROP_NAME);
843
+ if (nodeName == 'input') {
844
+ inst.append.remove();
845
+ inst.trigger.remove();
846
+ $target.removeClass(this.markerClassName)
847
+ .unbind('focus.heightpicker', this._showHeightpicker)
848
+ .unbind('click.heightpicker', this._adjustZIndex);
849
+ } else if (nodeName == 'div' || nodeName == 'span')
850
+ $target.removeClass(this.markerClassName).empty();
851
+ },
852
+
853
+ /* Enable the date picker to a jQuery selection.
854
+ @param target element - the target input field or division or span */
855
+ _enableHeightpicker: function(target) {
856
+ var $target = $(target),
857
+ target_id = $target.attr('id'),
858
+ inst = $.data(target, PROP_NAME);
859
+
860
+ if (!$target.hasClass(this.markerClassName)) {
861
+ return;
862
+ }
863
+ var nodeName = target.nodeName.toLowerCase();
864
+ if (nodeName == 'input') {
865
+ target.disabled = false;
866
+ var button = this._get(inst, 'button');
867
+ $(button).removeClass('ui-state-disabled').disabled = false;
868
+ inst.trigger.filter('button').
869
+ each(function() { this.disabled = false; }).end();
870
+ }
871
+ else if (nodeName == 'div' || nodeName == 'span') {
872
+ var inline = $target.children('.' + this._inlineClass);
873
+ inline.children().removeClass('ui-state-disabled');
874
+ inline.find('button').each(
875
+ function() { this.disabled = false }
876
+ )
877
+ }
878
+ this._disabledInputs = $.map(this._disabledInputs,
879
+ function(value) { return (value == target_id ? null : value); }); // delete entry
880
+ },
881
+
882
+ /* Disable the time picker to a jQuery selection.
883
+ @param target element - the target input field or division or span */
884
+ _disableHeightpicker: function(target) {
885
+ var $target = $(target);
886
+ var inst = $.data(target, PROP_NAME);
887
+ if (!$target.hasClass(this.markerClassName)) {
888
+ return;
889
+ }
890
+ var nodeName = target.nodeName.toLowerCase();
891
+ if (nodeName == 'input') {
892
+ var button = this._get(inst, 'button');
893
+
894
+ $(button).addClass('ui-state-disabled').disabled = true;
895
+ target.disabled = true;
896
+
897
+ inst.trigger.filter('button').
898
+ each(function() { this.disabled = true; }).end();
899
+
900
+ }
901
+ else if (nodeName == 'div' || nodeName == 'span') {
902
+ var inline = $target.children('.' + this._inlineClass);
903
+ inline.children().addClass('ui-state-disabled');
904
+ inline.find('button').each(
905
+ function() { this.disabled = true }
906
+ )
907
+
908
+ }
909
+ this._disabledInputs = $.map(this._disabledInputs,
910
+ function(value) { return (value == target ? null : value); }); // delete entry
911
+ this._disabledInputs[this._disabledInputs.length] = $target.attr('id');
912
+ },
913
+
914
+ /* Is the first field in a jQuery collection disabled as a heightpicker?
915
+ @param target_id element - the target input field or division or span
916
+ @return boolean - true if disabled, false if enabled */
917
+ _isDisabledHeightpicker: function (target_id) {
918
+ if ( ! target_id) { return false; }
919
+ for (var i = 0; i < this._disabledInputs.length; i++) {
920
+ if (this._disabledInputs[i] == target_id) { return true; }
921
+ }
922
+ return false;
923
+ },
924
+
925
+ /* Check positioning to remain on screen. */
926
+ _checkOffset: function (inst, offset, isFixed) {
927
+ var tpWidth = inst.tpDiv.outerWidth();
928
+ var tpHeight = inst.tpDiv.outerHeight();
929
+ var inputWidth = inst.input ? inst.input.outerWidth() : 0;
930
+ var inputHeight = inst.input ? inst.input.outerHeight() : 0;
931
+ var viewWidth = document.documentElement.clientWidth + $(document).scrollLeft();
932
+ var viewHeight = document.documentElement.clientHeight + $(document).scrollTop();
933
+
934
+ offset.left -= (this._get(inst, 'isRTL') ? (tpWidth - inputWidth) : 0);
935
+ offset.left -= (isFixed && offset.left == inst.input.offset().left) ? $(document).scrollLeft() : 0;
936
+ offset.top -= (isFixed && offset.top == (inst.input.offset().top + inputHeight)) ? $(document).scrollTop() : 0;
937
+
938
+ // now check if heightpicker is showing outside window viewport - move to a better place if so.
939
+ offset.left -= Math.min(offset.left, (offset.left + tpWidth > viewWidth && viewWidth > tpWidth) ?
940
+ Math.abs(offset.left + tpWidth - viewWidth) : 0);
941
+ offset.top -= Math.min(offset.top, (offset.top + tpHeight > viewHeight && viewHeight > tpHeight) ?
942
+ Math.abs(tpHeight + inputHeight) : 0);
943
+
944
+ return offset;
945
+ },
946
+
947
+ /* Find an object's position on the screen. */
948
+ _findPos: function (obj) {
949
+ var inst = this._getInst(obj);
950
+ var isRTL = this._get(inst, 'isRTL');
951
+ while (obj && (obj.type == 'hidden' || obj.nodeType != 1)) {
952
+ obj = obj[isRTL ? 'previousSibling' : 'nextSibling'];
953
+ }
954
+ var position = $(obj).offset();
955
+ return [position.left, position.top];
956
+ },
957
+
958
+ /* Retrieve the size of left and top borders for an element.
959
+ @param elem (jQuery object) the element of interest
960
+ @return (number[2]) the left and top borders */
961
+ _getBorders: function (elem) {
962
+ var convert = function (value) {
963
+ return { thin: 1, medium: 2, thick: 3}[value] || value;
964
+ };
965
+ return [parseFloat(convert(elem.css('border-left-width'))),
966
+ parseFloat(convert(elem.css('border-top-width')))];
967
+ },
968
+
969
+
970
+ /* Close time picker if clicked elsewhere. */
971
+ _checkExternalClick: function (event) {
972
+ if (!$.heightpicker._curInst) { return; }
973
+ var $target = $(event.target);
974
+ if ($target[0].id != $.heightpicker._mainDivId &&
975
+ $target.parents('#' + $.heightpicker._mainDivId).length == 0 &&
976
+ !$target.hasClass($.heightpicker.markerClassName) &&
977
+ !$target.hasClass($.heightpicker._triggerClass) &&
978
+ $.heightpicker._heightpickerShowing && !($.heightpicker._inDialog && $.blockUI))
979
+ $.heightpicker._hideHeightpicker();
980
+ },
981
+
982
+ /* Hide the time picker from view.
983
+ @param input element - the input field attached to the time picker */
984
+ _hideHeightpicker: function (input) {
985
+ var inst = this._curInst;
986
+ if (!inst || (input && inst != $.data(input, PROP_NAME))) { return; }
987
+ if (this._heightpickerShowing) {
988
+ var showAnim = this._get(inst, 'showAnim');
989
+ var duration = this._get(inst, 'duration');
990
+ var postProcess = function () {
991
+ $.heightpicker._tidyDialog(inst);
992
+ this._curInst = null;
993
+ };
994
+ if ($.effects && $.effects[showAnim]) {
995
+ inst.tpDiv.hide(showAnim, $.heightpicker._get(inst, 'showOptions'), duration, postProcess);
996
+ }
997
+ else {
998
+ inst.tpDiv[(showAnim == 'slideDown' ? 'slideUp' :
999
+ (showAnim == 'fadeIn' ? 'fadeOut' : 'hide'))]((showAnim ? duration : null), postProcess);
1000
+ }
1001
+ if (!showAnim) { postProcess(); }
1002
+
1003
+ this._heightpickerShowing = false;
1004
+
1005
+ this._lastInput = null;
1006
+ if (this._inDialog) {
1007
+ this._dialogInput.css({ position: 'absolute', left: '0', top: '-100px' });
1008
+ if ($.blockUI) {
1009
+ $.unblockUI();
1010
+ $('body').append(this.tpDiv);
1011
+ }
1012
+ }
1013
+ this._inDialog = false;
1014
+
1015
+ var onClose = this._get(inst, 'onClose');
1016
+ if (onClose) {
1017
+ onClose.apply(
1018
+ (inst.input ? inst.input[0] : null),
1019
+ [(inst.input ? inst.input.val() : ''), inst]); // trigger custom callback
1020
+ }
1021
+
1022
+ }
1023
+ },
1024
+
1025
+
1026
+
1027
+ /* Tidy up after a dialog display. */
1028
+ _tidyDialog: function (inst) {
1029
+ inst.tpDiv.removeClass(this._dialogClass).unbind('.ui-heightpicker');
1030
+ },
1031
+
1032
+ /* Retrieve the instance data for the target control.
1033
+ @param target element - the target input field or division or span
1034
+ @return object - the associated instance data
1035
+ @throws error if a jQuery problem getting data */
1036
+ _getInst: function (target) {
1037
+ try {
1038
+ return $.data(target, PROP_NAME);
1039
+ }
1040
+ catch (err) {
1041
+ throw 'Missing instance data for this heightpicker';
1042
+ }
1043
+ },
1044
+
1045
+ /* Get a setting value, defaulting if necessary. */
1046
+ _get: function (inst, name) {
1047
+ return inst.settings[name] !== undefined ?
1048
+ inst.settings[name] : this._defaults[name];
1049
+ },
1050
+
1051
+ /* Parse existing time and initialise time picker. */
1052
+ _setTimeFromField: function (inst) {
1053
+ // if (inst.input.val() == inst.lastVal) { return; }
1054
+ // var defaultTime = this._get(inst, 'defaultTime');
1055
+
1056
+ // var timeToParse = defaultTime == 'now' ? this._getCurrentTimeRounded(inst) : defaultTime;
1057
+ // if ((inst.inline == false) && (inst.input.val() != '')) { timeToParse = inst.input.val() }
1058
+
1059
+ // if (timeToParse instanceof Date) {
1060
+ // inst.hours = timeToParse.getHours();
1061
+ // inst.minutes = timeToParse.getMinutes();
1062
+ // } else {
1063
+ // var timeVal = inst.lastVal = timeToParse;
1064
+ // if (timeToParse == '') {
1065
+ // inst.hours = -1;
1066
+ // inst.minutes = -1;
1067
+ // } else {
1068
+ // var time = this.parseTime(inst, timeVal);
1069
+ // inst.hours = time.hours;
1070
+ // inst.minutes = time.minutes;
1071
+ // }
1072
+ // }
1073
+
1074
+ inst.hours = -1;
1075
+ inst.minutes = -1;
1076
+
1077
+ $.heightpicker._updateHeightpicker(inst);
1078
+ },
1079
+
1080
+ /* Update or retrieve the settings for an existing time picker.
1081
+ @param target element - the target input field or division or span
1082
+ @param name object - the new settings to update or
1083
+ string - the name of the setting to change or retrieve,
1084
+ when retrieving also 'all' for all instance settings or
1085
+ 'defaults' for all global defaults
1086
+ @param value any - the new value for the setting
1087
+ (omit if above is an object or to retrieve a value) */
1088
+ _optionHeightpicker: function(target, name, value) {
1089
+ var inst = this._getInst(target);
1090
+ if (arguments.length == 2 && typeof name == 'string') {
1091
+ return (name == 'defaults' ? $.extend({}, $.heightpicker._defaults) :
1092
+ (inst ? (name == 'all' ? $.extend({}, inst.settings) :
1093
+ this._get(inst, name)) : null));
1094
+ }
1095
+ var settings = name || {};
1096
+ if (typeof name == 'string') {
1097
+ settings = {};
1098
+ settings[name] = value;
1099
+ }
1100
+ if (inst) {
1101
+ extendRemove(inst.settings, settings);
1102
+ if (this._curInst == inst) {
1103
+ this._hideHeightpicker();
1104
+ this._updateHeightpicker(inst);
1105
+ }
1106
+ if (inst.inline) {
1107
+ this._updateHeightpicker(inst);
1108
+ }
1109
+ }
1110
+ },
1111
+
1112
+
1113
+ /* Set the time for a jQuery selection.
1114
+ @param target element - the target input field or division or span
1115
+ @param time String - the new time */
1116
+ _setTimeHeightpicker: function(target, time) {
1117
+ var inst = this._getInst(target);
1118
+ if (inst) {
1119
+ // this._setTime(inst, time);
1120
+ this._updateHeightpicker(inst);
1121
+ this._updateAlternate(inst, time);
1122
+ }
1123
+ },
1124
+
1125
+ /* Set the time directly. */
1126
+ _setTime: function(inst, time, noChange) {
1127
+ var origHours = inst.hours;
1128
+ var origMinutes = inst.minutes;
1129
+ // if (time instanceof Date) {
1130
+ // inst.hours = time.getHours();
1131
+ // inst.minutes = time.getMinutes();
1132
+ // } else {
1133
+ // var time = this.parseTime(inst, time);
1134
+ // inst.hours = time.hours;
1135
+ // inst.minutes = time.minutes;
1136
+ // }
1137
+
1138
+ if ((origHours != inst.hours || origMinutes != inst.minutes) && !noChange) {
1139
+ inst.input.trigger('change');
1140
+ }
1141
+ this._updateHeightpicker(inst);
1142
+ this._updateSelectedValue(inst);
1143
+ },
1144
+
1145
+ /* Return the current time, ready to be parsed, rounded to the closest minute by interval */
1146
+ // _getCurrentTimeRounded: function (inst) {
1147
+ // var currentTime = new Date(),
1148
+ // currentMinutes = currentTime.getMinutes(),
1149
+ // minutes_options = this._get(inst, 'minutes'),
1150
+ // // round to closest interval
1151
+ // adjustedMinutes = Math.round(currentMinutes / minutes_options.interval) * minutes_options.interval;
1152
+ // currentTime.setMinutes(adjustedMinutes);
1153
+ // return currentTime;
1154
+ // },
1155
+
1156
+ /*
1157
+ * Parse a time string into hours and minutes
1158
+ */
1159
+ parseTime: function (inst, timeVal) {
1160
+ var retVal = new Object();
1161
+ retVal.hours = -1;
1162
+ retVal.minutes = -1;
1163
+
1164
+ if(!timeVal)
1165
+ return '';
1166
+
1167
+ var timeSeparator = this._get(inst, 'timeSeparator'),
1168
+ amPmText = this._get(inst, 'amPmText'),
1169
+ showHours = this._get(inst, 'showHours'),
1170
+ showMinutes = this._get(inst, 'showMinutes'),
1171
+ optionalMinutes = this._get(inst, 'optionalMinutes'),
1172
+ showPeriod = (this._get(inst, 'showPeriod') == true),
1173
+ p = timeVal.indexOf(timeSeparator);
1174
+
1175
+ // check if time separator found
1176
+ if (p != -1) {
1177
+ retVal.hours = parseInt(timeVal.substr(0, p), 10);
1178
+ retVal.minutes = parseInt(timeVal.substr(p + 1), 10);
1179
+ }
1180
+ // check for hours only
1181
+ else if ( (showHours) && ( !showMinutes || optionalMinutes ) ) {
1182
+ retVal.hours = parseInt(timeVal, 10);
1183
+ }
1184
+ // check for minutes only
1185
+ else if ( ( ! showHours) && (showMinutes) ) {
1186
+ retVal.minutes = parseInt(timeVal, 10);
1187
+ }
1188
+
1189
+ if (showHours) {
1190
+ var timeValUpper = timeVal.toUpperCase();
1191
+ if ((retVal.hours < 12) && (showPeriod) && (timeValUpper.indexOf(amPmText[1].toUpperCase()) != -1)) {
1192
+ retVal.hours += 12;
1193
+ }
1194
+ // fix for 12 AM
1195
+ if ((retVal.hours == 12) && (showPeriod) && (timeValUpper.indexOf(amPmText[0].toUpperCase()) != -1)) {
1196
+ retVal.hours = 0;
1197
+ }
1198
+ }
1199
+
1200
+ return retVal;
1201
+ },
1202
+
1203
+ selectNow: function(event) {
1204
+ var id = $(event.target).attr("data-heightpicker-instance-id"),
1205
+ $target = $(id),
1206
+ inst = this._getInst($target[0]);
1207
+ //if (!inst || (input && inst != $.data(input, PROP_NAME))) { return; }
1208
+ inst.hours = -1;
1209
+ inst.minutes = -1;
1210
+ this._updateSelectedValue(inst);
1211
+ this._updateHeightpicker(inst);
1212
+ this._hideHeightpicker();
1213
+ },
1214
+
1215
+ deselectTime: function(event) {
1216
+ var id = $(event.target).attr("data-heightpicker-instance-id"),
1217
+ $target = $(id),
1218
+ inst = this._getInst($target[0]);
1219
+ inst.hours = -1;
1220
+ inst.minutes = -1;
1221
+ this._updateSelectedValue(inst);
1222
+ this._hideHeightpicker();
1223
+ },
1224
+
1225
+
1226
+ selectHours: function (event) {
1227
+ var $td = $(event.currentTarget),
1228
+ id = $td.attr("data-heightpicker-instance-id"),
1229
+ newHours = parseInt($td.attr("data-hour")),
1230
+ fromDoubleClick = event.data.fromDoubleClick,
1231
+ $target = $(id),
1232
+ inst = this._getInst($target[0]),
1233
+ showMinutes = (this._get(inst, 'showMinutes') == true);
1234
+
1235
+ // don't select if disabled
1236
+ if ( $.heightpicker._isDisabledHeightpicker($target.attr('id')) ) { return false }
1237
+
1238
+ $td.parents('.ui-heightpicker-hours:first').find('a').removeClass('ui-state-active');
1239
+ $td.children('a').addClass('ui-state-active');
1240
+ inst.hours = newHours;
1241
+
1242
+ // added for onMinuteShow callback
1243
+ var onMinuteShow = this._get(inst, 'onMinuteShow'),
1244
+ maxTime = this._get(inst, 'maxTime'),
1245
+ minTime = this._get(inst, 'minTime');
1246
+ if (onMinuteShow || maxTime.minute || minTime.minute) {
1247
+ // this will trigger a callback on selected hour to make sure selected minute is allowed.
1248
+ this._updateMinuteDisplay(inst);
1249
+ }
1250
+
1251
+ this._updateSelectedValue(inst);
1252
+
1253
+ inst._hoursClicked = true;
1254
+ if ((inst._minutesClicked) || (fromDoubleClick) || (showMinutes == false)) {
1255
+ $.heightpicker._hideHeightpicker();
1256
+ }
1257
+ // return false because if used inline, prevent the url to change to a hashtag
1258
+ return false;
1259
+ },
1260
+
1261
+ selectMinutes: function (event) {
1262
+ var $td = $(event.currentTarget),
1263
+ id = $td.attr("data-heightpicker-instance-id"),
1264
+ newMinutes = parseInt($td.attr("data-minute")),
1265
+ fromDoubleClick = event.data.fromDoubleClick,
1266
+ $target = $(id),
1267
+ inst = this._getInst($target[0]),
1268
+ showHours = (this._get(inst, 'showHours') == true);
1269
+
1270
+ // don't select if disabled
1271
+ if ( $.heightpicker._isDisabledHeightpicker($target.attr('id')) ) { return false }
1272
+
1273
+ $td.parents('.ui-heightpicker-minutes:first').find('a').removeClass('ui-state-active');
1274
+ $td.children('a').addClass('ui-state-active');
1275
+
1276
+ inst.minutes = newMinutes;
1277
+ this._updateSelectedValue(inst);
1278
+
1279
+ inst._minutesClicked = true;
1280
+ if ((inst._hoursClicked) || (fromDoubleClick) || (showHours == false)) {
1281
+ $.heightpicker._hideHeightpicker();
1282
+ // return false because if used inline, prevent the url to change to a hashtag
1283
+ return false;
1284
+ }
1285
+
1286
+ // return false because if used inline, prevent the url to change to a hashtag
1287
+ return false;
1288
+ },
1289
+
1290
+ _updateSelectedValue: function (inst) {
1291
+ var newTime = this._getParsedTime(inst);
1292
+ if (inst.input) {
1293
+ inst.input.val(newTime);
1294
+ inst.input.trigger('change');
1295
+ }
1296
+ var onSelect = this._get(inst, 'onSelect');
1297
+ if (onSelect) { onSelect.apply((inst.input ? inst.input[0] : null), [newTime, inst]); } // trigger custom callback
1298
+ this._updateAlternate(inst, newTime);
1299
+ return newTime;
1300
+ },
1301
+
1302
+ /* this function process selected time and return it parsed according to instance options */
1303
+ _getParsedTime: function(inst) {
1304
+ if (inst.hours == -1 && inst.minutes == -1) {
1305
+ return '';
1306
+ }else{
1307
+ if(inst.hours > -1 && inst.minutes >-1) {
1308
+ return inst.hours+"ft "+inst.minutes+"in";
1309
+ }
1310
+ if(inst.hours > 0 && inst.minutes < 0){
1311
+ return inst.hours+"ft 0in";
1312
+ }
1313
+ if(inst.hours < 0 && inst.minutes >= 0){
1314
+ return "4ft "+inst.minutes+"in";
1315
+ }
1316
+ }
1317
+ },
1318
+
1319
+ /* Update any alternate field to synchronise with the main field. */
1320
+ _updateAlternate: function(inst, newTime) {
1321
+ var altField = this._get(inst, 'altField');
1322
+ if (altField) { // update alternate field too
1323
+ $(altField).each(function(i,e) {
1324
+ $(e).val(newTime);
1325
+ });
1326
+ }
1327
+ },
1328
+
1329
+ _getTimeAsDateHeightpicker: function(input) {
1330
+ var inst = this._getInst(input);
1331
+ if (inst.hours == -1 && inst.minutes == -1) {
1332
+ return '';
1333
+ }
1334
+
1335
+ return inst;
1336
+ },
1337
+ /* This might look unused but it's called by the $.fn.heightpicker function with param getTime */
1338
+ /* added v 0.2.3 - gitHub issue #5 - Thanks edanuff */
1339
+ _getTimeHeightpicker : function(input) {
1340
+ var inst = this._getInst(input);
1341
+ return this._getParsedTime(inst);
1342
+ },
1343
+ _getHourHeightpicker: function(input) {
1344
+ var inst = this._getInst(input);
1345
+ if ( inst == undefined) { return -1; }
1346
+ return inst.hours;
1347
+ },
1348
+ _getMinuteHeightpicker: function(input) {
1349
+ var inst= this._getInst(input);
1350
+ if ( inst == undefined) { return -1; }
1351
+ return inst.minutes;
1352
+ }
1353
+
1354
+ });
1355
+
1356
+
1357
+
1358
+ /* Invoke the heightpicker functionality.
1359
+ @param options string - a command, optionally followed by additional parameters or
1360
+ Object - settings for attaching new heightpicker functionality
1361
+ @return jQuery object */
1362
+ $.fn.heightpicker = function (options) {
1363
+ /* Initialise the time picker. */
1364
+ if (!$.heightpicker.initialized) {
1365
+ $(document).mousedown($.heightpicker._checkExternalClick);
1366
+ $.heightpicker.initialized = true;
1367
+ }
1368
+
1369
+ /* Append heightpicker main container to body if not exist. */
1370
+ if ($("#"+$.heightpicker._mainDivId).length === 0) {
1371
+ $('body').append($.heightpicker.tpDiv);
1372
+ }
1373
+
1374
+ var otherArgs = Array.prototype.slice.call(arguments, 1);
1375
+ if (typeof options == 'string' && (options == 'getTime' || options == 'getTimeAsDate' || options == 'getHour' || options == 'getMinute' ))
1376
+ return $.heightpicker['_' + options + 'Heightpicker'].
1377
+ apply($.heightpicker, [this[0]].concat(otherArgs));
1378
+ if (options == 'option' && arguments.length == 2 && typeof arguments[1] == 'string')
1379
+ return $.heightpicker['_' + options + 'Heightpicker'].
1380
+ apply($.heightpicker, [this[0]].concat(otherArgs));
1381
+ return this.each(function () {
1382
+ typeof options == 'string' ?
1383
+ $.heightpicker['_' + options + 'Heightpicker'].
1384
+ apply($.heightpicker, [this].concat(otherArgs)) :
1385
+ $.heightpicker._attachHeightpicker(this, options);
1386
+ });
1387
+ };
1388
+
1389
+ /* jQuery extend now ignores nulls! */
1390
+ function extendRemove(target, props) {
1391
+ $.extend(target, props);
1392
+ for (var name in props)
1393
+ if (props[name] == null || props[name] == undefined)
1394
+ target[name] = props[name];
1395
+ return target;
1396
+ };
1397
+
1398
+ $.heightpicker = new Heightpicker(); // singleton instance
1399
+ $.heightpicker.initialized = false;
1400
+ $.heightpicker.version = "0.1";
1401
+
1402
+ // Workaround for #4055
1403
+ // Add another global to avoid noConflict issues with inline event handlers
1404
+ window['TP_jQuery_' + tpuuid] = $;
1405
+
1406
+ })(jQuery);