PluginProbe
weForms – Easy Drag & Drop Contact Form Builder For WordPress / 1.6.4
weForms – Easy Drag & Drop Contact Form Builder For WordPress v1.6.4
1.6.7 1.6.8 1.6.9 1.6.12 1.6.13 1.6.14 1.6.15 1.6.16 1.6.17 1.6.18 1.6.19 1.6.2 1.6.20 1.6.21 1.6.22 1.6.23 1.6.24 1.6.25 1.6.26 1.6.27 1.6.28 1.6.3 1.6.4 1.6.5 1.6.6 All 74 releases
weforms / assets / js / weforms.js

weforms.js in weForms – Easy Drag & Drop Contact Form Builder For WordPress 1.6.4, at assets/js/weforms.js

4,861 lines 166.0 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 /* assets/wpuf/js/frontend-form.js */
2 ;(function($, window) {
3
4 $.fn.listautowidth = function() {
5 return this.each(function() {
6 var w = $(this).width();
7 var liw = w / $(this).children('li').length;
8 $(this).children('li').each(function(){
9 var s = $(this).outerWidth(true)-$(this).width();
10 $(this).width(liw-s);
11 });
12 });
13 };
14
15 window.WP_User_Frontend = {
16
17 init: function() {
18
19 //enable multistep
20 this.enableMultistep(this);
21
22 // clone and remove repeated field
23 $('.wpuf-form').on('click', 'img.wpuf-clone-field', this.cloneField);
24 $('.wpuf-form').on('click', 'img.wpuf-remove-field', this.removeField);
25 $('.wpuf-form').on('click', 'a.wpuf-delete-avatar', this.deleteAvatar);
26 $('.wpuf-form').on('click', 'a#wpuf-post-draft', this.draftPost);
27 $('.wpuf-form').on('click', 'button#wpuf-account-update-profile', this.account_update_profile);
28
29 $('.wpuf-form-add').on('submit', this.formSubmit);
30 $('form#post').on('submit', this.adminPostSubmit);
31 // $( '.wpuf-form').on('keyup', '#pass1', this.check_pass_strength );
32
33 // refresh pluploads on each step change (multistep form)
34 $('.wpuf-form').on('step-change-fieldset', function(event, number, step) {
35 if ( wpuf_plupload_items.length ) {
36 for (var i = wpuf_plupload_items.length - 1; i >= 0; i--) {
37 wpuf_plupload_items[i].refresh();
38 }
39 }
40 if ( wpuf_map_items.length ) {
41 for (var i = wpuf_map_items.length - 1; i >= 0; i--) {
42 google.maps.event.trigger(wpuf_map_items[i].map, 'resize');
43 wpuf_map_items[i].map.setCenter(wpuf_map_items[i].center);
44 }
45 }
46 });
47
48 this.ajaxCategory();
49 // image insert
50 // this.insertImage();
51
52 //comfirmation alert for canceling subscription
53 $( ':submit[name="wpuf_user_subscription_cancel"]').click(function(e){
54 e.preventDefault();
55
56 swal({
57 text: wpuf_frontend.cancelSubMsg,
58 type: 'warning',
59 showCancelButton: true,
60 confirmButtonColor: '#d54e21',
61 confirmButtonText: wpuf_frontend.delete_it,
62 cancelButtonText: wpuf_frontend.cancel_it,
63 confirmButtonClass: 'btn btn-success',
64 cancelButtonClass: 'btn btn-danger',
65 }).then(function ( isConfirmed ) {
66 if ( !isConfirmed ) {
67 return false;
68 }
69 $('#wpuf_cancel_subscription').submit();
70 });
71 });
72 },
73
74 check_pass_strength : function() {
75 var pass1 = $('#pass1').val(), strength;
76
77 $('#pass-strength-result').show();
78
79 $('#pass-strength-result').removeClass('short bad good strong');
80 if ( ! pass1 ) {
81 $('#pass-strength-result').html( ' ' );
82 $('#pass-strength-result').hide();
83 return;
84 }
85
86 if ( typeof wp.passwordStrength != 'undefined' ) {
87
88 strength = wp.passwordStrength.meter( pass1, wp.passwordStrength.userInputBlacklist(), pass1 );
89
90 switch ( strength ) {
91 case 2:
92 $('#pass-strength-result').addClass('bad').html( pwsL10n.bad );
93 break;
94 case 3:
95 $('#pass-strength-result').addClass('good').html( pwsL10n.good );
96 break;
97 case 4:
98 $('#pass-strength-result').addClass('strong').html( pwsL10n.strong );
99 break;
100 case 5:
101 $('#pass-strength-result').addClass('short').html( pwsL10n.mismatch );
102 break;
103 default:
104 $('#pass-strength-result').addClass('short').html( pwsL10n['short'] );
105 }
106
107 }
108 },
109
110 enableMultistep: function(o) {
111
112 var js_obj = this;
113 var step_number = 0;
114 var progressbar_type = $(':hidden[name="wpuf_multistep_type"]').val();
115
116 if ( progressbar_type == null ) {
117 return;
118 }
119
120 // first fieldset doesn't have prev button,
121 // last fieldset doesn't have next button
122 $('fieldset.wpuf-multistep-fieldset').find('.wpuf-multistep-prev-btn').first().remove();
123 $('fieldset.wpuf-multistep-fieldset').find('.wpuf-multistep-next-btn').last().remove();
124
125 // at first first fieldset will be shown, and others will be hidden
126 $('.wpuf-form fieldset').removeClass('field-active').first().addClass('field-active');
127
128 if ( progressbar_type == 'progressive' && $('.wpuf-form .wpuf-multistep-fieldset').length != 0 ) {
129
130 var firstLegend = $('fieldset.wpuf-multistep-fieldset legend').first();
131 $('.wpuf-multistep-progressbar').html('<div class="wpuf-progress-percentage"></div>' );
132
133 var progressbar = $( ".wpuf-multistep-progressbar" ),
134 progressLabel = $( ".wpuf-progress-percentage" );
135
136 $( ".wpuf-multistep-progressbar" ).progressbar({
137 change: function() {
138 progressLabel.text( progressbar.progressbar( "value" ) + "%" );
139 }
140 });
141
142 $('.wpuf-multistep-fieldset legend').hide();
143
144 } else {
145 $('.wpuf-form').each(function() {
146 var this_obj = $(this);
147 var progressbar = $('.wpuf-multistep-progressbar', this_obj);
148 var nav = '';
149
150 progressbar.addClass('wizard-steps');
151 nav += '<ul class="wpuf-step-wizard">';
152
153 $('.wpuf-multistep-fieldset', this).each(function(){
154 nav += '<li>' + $.trim( $('legend', this).text() ) + '</li>';
155 $('legend', this).hide();
156 });
157
158 nav += '</ul>';
159 progressbar.append( nav );
160
161 $('.wpuf-step-wizard li', progressbar).first().addClass('active-step');
162 $('.wpuf-step-wizard', progressbar).listautowidth();
163 });
164 }
165
166 this.change_fieldset(step_number, progressbar_type);
167
168 $('fieldset .wpuf-multistep-prev-btn, fieldset .wpuf-multistep-next-btn').click(function(e) {
169 // js_obj.formSubmit();
170 if ( $(this).hasClass('wpuf-multistep-next-btn') ) {
171 var result = js_obj.formStepCheck( '', $(this).closest('fieldset') );
172
173 if ( result != false ) {
174 o.change_fieldset(++step_number,progressbar_type);
175 }
176
177 } else if ( $(this).hasClass('wpuf-multistep-prev-btn') ) {
178 o.change_fieldset( --step_number,progressbar_type );
179 }
180
181 var formDiv = $( "form.wpuf-form-add" );
182 var position = formDiv.offset().top;
183
184 // this changes the scrolling behavior to "smooth"
185 window.scrollTo({
186 top: position - 32,
187 behavior: "smooth"
188 });
189
190 return false;
191 });
192 },
193
194 change_fieldset: function(step_number, progressbar_type) {
195 var current_step = $('fieldset.wpuf-multistep-fieldset').eq(step_number);
196
197 $('fieldset.wpuf-multistep-fieldset').removeClass('field-active').eq(step_number).addClass('field-active');
198
199 $('.wpuf-step-wizard li').each(function(){
200 if ( $(this).index() <= step_number ){
201 progressbar_type == 'step_by_step'? $(this).addClass('passed-wpuf-ms-bar') : $('.wpuf-ps-bar',this).addClass('passed-wpuf-ms-bar');
202 } else {
203 progressbar_type == 'step_by_step'? $(this).removeClass('passed-wpuf-ms-bar') : $('.wpuf-ps-bar',this).removeClass('passed-wpuf-ms-bar');
204 }
205 });
206
207 $('.wpuf-step-wizard li').removeClass('wpuf-ms-bar-active active-step completed-step');
208 $('.passed-wpuf-ms-bar').addClass('completed-step').last().addClass('wpuf-ms-bar-active');
209 $('.wpuf-ms-bar-active').addClass('active-step');
210
211 var legend = $('fieldset.wpuf-multistep-fieldset').eq(step_number).find('legend').text();
212 legend = $.trim( legend );
213
214 if ( progressbar_type == 'progressive' && $('.wpuf-form .wpuf-multistep-fieldset').length != 0 ) {
215 var progress_percent = ( step_number + 1 ) * 100 / $('fieldset.wpuf-multistep-fieldset').length ;
216 var progress_percent = Number( progress_percent.toFixed(2) );
217 $( ".wpuf-multistep-progressbar" ).progressbar({value: progress_percent });
218 $( '.wpuf-progress-percentage' ).text( legend + ' (' + progress_percent + '%)');
219 }
220
221 // trigger a change event
222 $('.wpuf-form').trigger('step-change-fieldset', [ step_number, current_step ]);
223 },
224
225 ajaxCategory: function () {
226
227 var el = '.cat-ajax',
228 wrap = '.category-wrap';
229
230 $(wrap).on('change', el, function(){
231 currentLevel = parseInt( $(this).parent().attr('level') );
232 WP_User_Frontend.getChildCats( $(this), 'lvl', currentLevel+1, wrap, 'category');
233 });
234 },
235
236 getChildCats: function (dropdown, result_div, level, wrap_div, taxonomy) {
237
238 cat = $(dropdown).val();
239 results_div = result_div + level;
240 taxonomy = typeof taxonomy !== 'undefined' ? taxonomy : 'category';
241 field_attr = $(dropdown).siblings('span').data('taxonomy');
242
243 $.ajax({
244 type: 'post',
245 url: wpuf_frontend.ajaxurl,
246 data: {
247 action: 'wpuf_get_child_cat',
248 catID: cat,
249 nonce: wpuf_frontend.nonce,
250 field_attr: field_attr
251 },
252 beforeSend: function() {
253 $(dropdown).parent().parent().next('.loading').addClass('wpuf-loading');
254 },
255 complete: function() {
256 $(dropdown).parent().parent().next('.loading').removeClass('wpuf-loading');
257 },
258 success: function(html) {
259 //console.log( html ); return;
260 $(dropdown).parent().nextAll().each(function(){
261 $(this).remove();
262 });
263
264 if(html != "") {
265 $(dropdown).parent().addClass('hasChild').parent().append('<div id="'+result_div+level+'" level="'+level+'"></div>');
266 dropdown.parent().parent().find('#'+results_div).html(html).slideDown('fast');
267 }
268 }
269 });
270 },
271
272 cloneField: function(e) {
273 e.preventDefault();
274
275 var $div = $(this).closest('tr');
276 var $clone = $div.clone();
277 // console.log($clone);
278
279 //clear the inputs
280 $clone.find('input').val('');
281 $clone.find(':checked').attr('checked', '');
282 $div.after($clone);
283 },
284
285 removeField: function() {
286 //check if it's the only item
287 var $parent = $(this).closest('tr');
288 var items = $parent.siblings().andSelf().length;
289
290 if( items > 1 ) {
291 $parent.remove();
292 }
293 },
294
295 adminPostSubmit: function(e) {
296 e.preventDefault();
297
298 var form = $(this),
299 form_data = WP_User_Frontend.validateForm(form);
300
301 if (form_data) {
302 return true;
303 }
304 },
305
306 draftPost: function (e) {
307 e.preventDefault();
308
309 var self = $(this),
310 form = $(this).closest('form'),
311 form_data = form.serialize() + '&action=wpuf_draft_post',
312 post_id = form.find('input[type="hidden"][name="post_id"]').val();
313
314 var rich_texts = [],
315 val;
316
317 // grab rich texts from tinyMCE
318 $('.wpuf-rich-validation').each(function (index, item) {
319 var item = $(item);
320 var editor_id = item.data('id');
321 var item_name = item.data('name');
322 var val = $.trim( tinyMCE.get(editor_id).getContent() );
323
324 rich_texts.push(item_name + '=' + encodeURIComponent( val ) );
325 });
326
327 // append them to the form var
328 form_data = form_data + '&' + rich_texts.join('&');
329
330
331 self.after(' <span class="wpuf-loading"></span>');
332 $.post(wpuf_frontend.ajaxurl, form_data, function(res) {
333 // console.log(res, post_id);
334 if ( typeof post_id === 'undefined') {
335 var html = '<input type="hidden" name="post_id" value="' + res.post_id +'">';
336 html += '<input type="hidden" name="post_date" value="' + res.date +'">';
337 html += '<input type="hidden" name="post_author" value="' + res.post_author +'">';
338 html += '<input type="hidden" name="comment_status" value="' + res.comment_status +'">';
339
340 form.append( html );
341 }
342
343 self.next('span.wpuf-loading').remove();
344
345 self.after('<span class="wpuf-draft-saved">&nbsp; Post Saved</span>');
346 $('.wpuf-draft-saved').delay(2500).fadeOut('fast', function(){
347 $(this).remove();
348 });
349 })
350 },
351
352 // Frontend account dashboard update profile
353 account_update_profile: function (e) {
354 e.preventDefault();
355 var form = $(this).closest('form');
356
357 $.post(wpuf_frontend.ajaxurl, form.serialize(), function (res) {
358 if (res.success) {
359 form.find('.wpuf-error').hide();
360 form.find('.wpuf-success').show();
361 } else {
362 form.find('.wpuf-success').hide();
363 form.find('.wpuf-error').show();
364 form.find('.wpuf-error').text(res.data);
365 }
366 });
367 },
368
369 formStepCheck : function(e,fieldset) {
370 var form = fieldset,
371 submitButton = form.find('input[type=submit]');
372 form_data = WP_User_Frontend.validateForm(form);
373
374 if ( form_data == false ) {
375 WP_User_Frontend.addErrorNotice( self, 'bottom' );
376 }
377 return form_data;
378 },
379
380 formSubmit: function(e) {
381 e.preventDefault();
382
383 var form = $(this),
384 submitButton = form.find('input[type=submit]')
385 form_data = WP_User_Frontend.validateForm(form);
386
387 if (form_data) {
388
389 // send the request
390 form.find('li.wpuf-submit').append('<span class="wpuf-loading"></span>');
391 submitButton.attr('disabled', 'disabled').addClass('button-primary-disabled');
392
393 $.post(wpuf_frontend.ajaxurl, form_data, function(res) {
394 // var res = $.parseJSON(res);
395
396 if ( res.success) {
397
398 // enable external plugins to use events
399 $('body').trigger('wpuf:postform:success', res);
400
401 if ( res.show_message == true) {
402 form.before( '<div class="wpuf-success">' + res.message + '</div>');
403 form.slideUp( 'fast', function() {
404 form.remove();
405 });
406
407 //focus
408 $('html, body').animate({
409 scrollTop: $('.wpuf-success').offset().top - 100
410 }, 'fast');
411
412 } else {
413 window.location = res.redirect_to;
414 }
415
416 } else {
417
418 if ( typeof res.type !== 'undefined' && res.type === 'login' ) {
419
420 if ( confirm(res.error) ) {
421 window.location = res.redirect_to;
422 } else {
423 submitButton.removeAttr('disabled');
424 submitButton.removeClass('button-primary-disabled');
425 form.find('span.wpuf-loading').remove();
426 }
427
428 return;
429 } else {
430 if ( form.find('.g-recaptcha').length > 0 ) {
431 grecaptcha.reset();
432 }
433
434 swal({
435 html: res.error,
436 type: 'warning',
437 showCancelButton: false,
438 confirmButtonColor: '#d54e21',
439 confirmButtonText: 'OK',
440 cancelButtonClass: 'btn btn-danger',
441 });
442
443 }
444
445 submitButton.removeAttr('disabled');
446 }
447
448 submitButton.removeClass('button-primary-disabled');
449 form.find('span.wpuf-loading').remove();
450 });
451 }
452 },
453
454 validateForm: function( self ) {
455
456 var temp,
457 temp_val = '',
458 error = false,
459 error_items = [];
460 error_type = '';
461
462 // remove all initial errors if any
463 WP_User_Frontend.removeErrors(self);
464 WP_User_Frontend.removeErrorNotice(self);
465
466 // ===== Validate: Text and Textarea ========
467 var required = self.find('[data-required="yes"]:visible');
468
469 required.each(function(i, item) {
470 // temp_val = $.trim($(item).val());
471
472 // console.log( $(item).data('type') );
473 var data_type = $(item).data('type')
474 val = '';
475
476 switch(data_type) {
477 case 'rich':
478 var name = $(item).data('id')
479 val = $.trim( tinyMCE.get(name).getContent() );
480
481 if ( val === '') {
482 error = true;
483
484 // make it warn collor
485 WP_User_Frontend.markError(item);
486 }
487 break;
488
489 case 'textarea':
490 case 'text':
491
492 val = $.trim( $(item).val() );
493
494 if ( val === '') {
495 error = true;
496 error_type = 'required';
497
498 // make it warn collor
499 WP_User_Frontend.markError( item, error_type );
500 }
501 break;
502
503 case 'password':
504 case 'confirm_password':
505 var hasRepeat = $(item).data('repeat');
506
507 val = $.trim( $(item).val() );
508
509 if ( val === '') {
510 error = true;
511 error_type = 'required';
512
513 // make it warn collor
514 WP_User_Frontend.markError( item, error_type );
515 }
516
517 if ( hasRepeat ) {
518 var repeatItem = $('[data-type="confirm_password"]').eq(0);;
519
520 if ( repeatItem.val() != val ) {
521 error = true;
522 error_type = 'mismatch';
523
524 WP_User_Frontend.markError( repeatItem, error_type );
525 }
526 }
527
528 break;
529
530 case 'select':
531 val = $(item).val();
532
533 // console.log(val);
534 if ( !val || val === '-1' ) {
535 error = true;
536 error_type = 'required';
537
538 // make it warn collor
539 WP_User_Frontend.markError( item, error_type );
540 }
541 break;
542
543 case 'multiselect':
544 val = $(item).val();
545
546 if ( val === null || val.length === 0 ) {
547 error = true;
548 error_type = 'required';
549
550 // make it warn collor
551 WP_User_Frontend.markError( item, error_type );
552 }
553 break;
554
555 case 'tax-checkbox':
556 var length = $(item).children().find('input:checked').length;
557
558 if ( !length ) {
559 error = true;
560 error_type = 'required';
561
562 // make it warn collor
563 WP_User_Frontend.markError( item, error_type );
564 }
565 break;
566
567 case 'radio':
568 var length = $(item).find('input:checked').length;
569
570 if ( !length ) {
571 error = true;
572 error_type = 'required';
573
574 // make it warn collor
575 WP_User_Frontend.markError( item, error_type );
576 }
577 break;
578
579 case 'file':
580 var length = $(item).find('ul').children().length;
581
582 if ( !length ) {
583 error = true;
584 error_type = 'required';
585
586 // make it warn collor
587 WP_User_Frontend.markError( item, error_type );
588 }
589 break;
590
591 case 'email':
592 var val = $(item).val();
593
594 if ( val !== '' ) {
595 //run the validation
596 if( !WP_User_Frontend.isValidEmail( val ) ) {
597 error = true;
598 error_type = 'validation';
599
600 WP_User_Frontend.markError( item, error_type );
601 }
602 } else if( val === '' ) {
603 error = true;
604 error_type = 'required';
605
606 WP_User_Frontend.markError( item, error_type );
607 }
608 break;
609
610
611 case 'url':
612 var val = $(item).val();
613
614 if ( val !== '' ) {
615 //run the validation
616 if( !WP_User_Frontend.isValidURL( val ) ) {
617 error = true;
618 error_type = 'validation';
619
620 WP_User_Frontend.markError( item, error_type );
621 }
622 }
623 break;
624
625 };
626
627 });
628
629 //check Google Map is required
630 var map_required = self.find('[data-required="yes"][name="google_map"]');
631 if ( map_required ) {
632 var val = $(map_required).val();
633 if ( val == ',' ) {
634 error = true;
635 error_type = 'required';
636
637 WP_User_Frontend.markError( map_required, error_type );
638 }
639 }
640
641 // if already some error found, bail out
642 if (error) {
643 // add error notice
644 WP_User_Frontend.addErrorNotice(self,'end');
645
646 return false;
647 }
648
649 var form_data = self.serialize(),
650 rich_texts = [];
651
652 // grab rich texts from tinyMCE
653 $('.wpuf-rich-validation', self).each(function (index, item) {
654 var item = $(item);
655 var editor_id = item.data('id');
656 var item_name = item.data('name');
657 var val = $.trim( tinyMCE.get(editor_id).getContent() );
658
659 rich_texts.push(item_name + '=' + encodeURIComponent( val ) );
660 });
661
662 // append them to the form var
663 form_data = form_data + '&' + rich_texts.join('&');
664 return form_data;
665 },
666
667 /**
668 *
669 * @param form
670 * @param position (value = bottom or end) end if form is onepare, bottom, if form is multistep
671 */
672 addErrorNotice: function( form, position ) {
673 if( position == 'bottom' ) {
674 $('.wpuf-multistep-fieldset:visible').append('<div class="wpuf-errors">' + wpuf_frontend.error_message + '</div>');
675 } else {
676 $(form).find('li.wpuf-submit').append('<div class="wpuf-errors">' + wpuf_frontend.error_message + '</div>');
677 }
678
679 },
680
681 removeErrorNotice: function(form) {
682 $(form).find('.wpuf-errors').remove();
683 },
684
685 markError: function(item, error_type) {
686
687 var error_string = '';
688 $(item).closest('li').addClass('has-error');
689
690 if ( error_type ) {
691 error_string = $(item).closest('li').data('label');
692 switch ( error_type ) {
693 case 'required' :
694 error_string = error_string + ' ' + error_str_obj[error_type];
695 break;
696 case 'mismatch' :
697 error_string = error_string + ' ' +error_str_obj[error_type];
698 break;
699 case 'validation' :
700 error_string = error_string + ' ' + error_str_obj[error_type];
701 break
702 }
703 $(item).siblings('.wpuf-error-msg').remove();
704 $(item).after('<div class="wpuf-error-msg">'+ error_string +'</div>')
705 }
706
707 $(item).focus();
708 },
709
710 removeErrors: function(item) {
711 $(item).find('.has-error').removeClass('has-error');
712 $('.wpuf-error-msg').remove();
713 },
714
715 isValidEmail: function( email ) {
716 var pattern = new RegExp(/^((([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+(\.([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+)*)|((\x22)((((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(([\x01-\x08\x0b\x0c\x0e-\x1f\x7f]|\x21|[\x23-\x5b]|[\x5d-\x7e]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(\\([\x01-\x09\x0b\x0c\x0d-\x7f]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]))))*(((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(\x22)))@((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.?$/i);
717 return pattern.test(email);
718 },
719
720 isValidURL: function(url) {
721 var urlregex = new RegExp("^(http:\/\/www.|https:\/\/www.|ftp:\/\/www.|www.|http:\/\/|https:\/\/){1}([0-9A-Za-z]+\.)");
722 return urlregex.test(url);
723 },
724
725 insertImage: function(button, form_id) {
726
727 var container = 'wpuf-insert-image-container';
728
729 if ( ! $( '#' + button ).length ) {
730 return;
731 };
732
733 var imageUploader = new plupload.Uploader({
734 runtimes: 'html5,html4',
735 browse_button: button,
736 container: container,
737 multipart: true,
738 multipart_params: {
739 action: 'wpuf_insert_image',
740 form_id: $( '#' + button ).data('form_id')
741 },
742 multiple_queues: false,
743 multi_selection: false,
744 urlstream_upload: true,
745 file_data_name: 'wpuf_file',
746 max_file_size: '2mb',
747 url: wpuf_frontend_upload.plupload.url,
748 flash_swf_url: wpuf_frontend_upload.flash_swf_url,
749 filters: [{
750 title: 'Allowed Files',
751 extensions: 'jpg,jpeg,gif,png,bmp'
752 }]
753 });
754
755 imageUploader.bind('Init', function(up, params) {
756 // console.log("Current runtime environment: " + params.runtime);
757 });
758
759 imageUploader.bind('FilesAdded', function(up, files) {
760 var $container = $('#' + container);
761
762 $.each(files, function(i, file) {
763 $container.append(
764 '<div class="upload-item" id="' + file.id + '"><div class="progress progress-striped active"><div class="bar"></div></div></div>');
765 });
766
767 up.refresh();
768 up.start();
769 });
770
771 imageUploader.bind('QueueChanged', function (uploader) {
772 imageUploader.start();
773 });
774
775 imageUploader.bind('UploadProgress', function(up, file) {
776 var item = $('#' + file.id);
777
778 $('.bar', item).css({ width: file.percent + '%' });
779 $('.percent', item).html( file.percent + '%' );
780 });
781
782 imageUploader.bind('Error', function(up, error) {
783 alert('Error #' + error.code + ': ' + error.message);
784 });
785
786 imageUploader.bind('FileUploaded', function(up, file, response) {
787
788 $('#' + file.id).remove();
789
790 if ( response.response !== 'error' ) {
791 var success = false;
792
793 if ( typeof tinyMCE !== 'undefined' ) {
794
795 if ( typeof tinyMCE.execInstanceCommand !== 'function' ) {
796 // tinyMCE 4.x
797 var mce = tinyMCE.get( 'post_content_' + form_id );
798
799 if ( mce !== null ) {
800 mce.insertContent(response.response);
801 }
802 } else {
803 // tinyMCE 3.x
804 tinyMCE.execInstanceCommand( 'post_content_' + form_id, 'mceInsertContent', false, response.response);
805 }
806 }
807
808 // insert failed to the edit, perhaps insert into textarea
809 var post_content = $('#post_content_' + form_id);
810 post_content.val( post_content.val() + response.response );
811
812 } else {
813 alert('Something went wrong');
814 }
815 });
816
817 imageUploader.init();
818 },
819
820 deleteAvatar: function(e) {
821 e.preventDefault();
822
823 if ( confirm( $(this).data('confirm') ) ) {
824 $.post(wpuf_frontend.ajaxurl, {action: 'wpuf_delete_avatar', _wpnonce: wpuf_frontend.nonce}, function() {
825 $(e.target).parent().remove();
826 $('[id^=wpuf-avatar]').css("display", "");
827 });
828 }
829 },
830
831 editorLimit: {
832
833 bind: function(limit, field, type) {
834 if ( type === 'no' ) {
835 // it's a textarea
836 $('textarea#' + field).keydown( function(event) {
837 WP_User_Frontend.editorLimit.textLimit.call(this, event, limit);
838 });
839
840 $('input#' + field).keydown( function(event) {
841 WP_User_Frontend.editorLimit.textLimit.call(this, event, limit);
842 });
843
844 $('textarea#' + field).on('paste', function(event) {
845 var self = $(this);
846
847 setTimeout(function() {
848 WP_User_Frontend.editorLimit.textLimit.call(self, event, limit);
849 }, 100);
850 });
851
852 $('input#' + field).on('paste', function(event) {
853 var self = $(this);
854
855 setTimeout(function() {
856 WP_User_Frontend.editorLimit.textLimit.call(self, event, limit);
857 }, 100);
858 });
859
860 } else {
861 // it's a rich textarea
862 setTimeout(function () {
863 tinyMCE.get(field).onKeyDown.add(function(ed, event) {
864 WP_User_Frontend.editorLimit.tinymce.onKeyDown(ed, event, limit);
865 } );
866
867 tinyMCE.get(field).onPaste.add(function(ed, event) {
868 setTimeout(function() {
869 WP_User_Frontend.editorLimit.tinymce.onPaste(ed, event, limit);
870 }, 100);
871 });
872
873 }, 1000);
874 }
875 },
876
877 tinymce: {
878
879 getStats: function(ed) {
880 var body = ed.getBody(), text = tinymce.trim(body.innerText || body.textContent);
881
882 return {
883 chars: text.length,
884 words: text.split(/[\w\u2019\'-]+/).length
885 };
886 },
887
888 onKeyDown: function(ed, event, limit) {
889 var numWords = WP_User_Frontend.editorLimit.tinymce.getStats(ed).words - 1;
890
891 limit ? $('.mce-path-item.mce-last', ed.container).html('Word Limit : '+ numWords +'/'+limit):'';
892
893 if ( limit && numWords > limit ) {
894 WP_User_Frontend.editorLimit.blockTyping(event);
895 jQuery('.mce-path-item.mce-last', ed.container).html( wpuf_frontend.word_limit );
896 }
897 },
898
899 onPaste: function(ed, event, limit) {
900 var editorContent = ed.getContent().split(' ').slice(0, limit).join(' ');
901
902 // Let TinyMCE do the heavy lifting for inserting that content into the editor.
903 // ed.insertContent(content); //ed.execCommand('mceInsertContent', false, content);
904 ed.setContent(editorContent);
905
906 WP_User_Frontend.editorLimit.make_media_embed_code(editorContent, ed);
907 }
908 },
909
910 textLimit: function(event, limit) {
911 var self = $(this),
912 content = self.val().split(' ');
913
914 if ( limit && content.length > limit ) {
915 self.closest('.wpuf-fields').find('span.wpuf-wordlimit-message').html( wpuf_frontend.word_limit );
916 WP_User_Frontend.editorLimit.blockTyping(event);
917 } else {
918 self.closest('.wpuf-fields').find('span.wpuf-wordlimit-message').html('');
919 }
920
921 // handle the paste event
922 if ( event.type === 'paste' ) {
923 self.val( content.slice(0, limit).join( ' ' ) );
924 }
925 },
926
927 blockTyping: function(event) {
928 // Allow: backspace, delete, tab, escape, minus enter and . backspace = 8,delete=46,tab=9,enter=13,.=190,escape=27, minus = 189
929 if ($.inArray(event.keyCode, [46, 8, 9, 27, 13, 110, 190, 189]) !== -1 ||
930 // Allow: Ctrl+A
931 (event.keyCode == 65 && event.ctrlKey === true) ||
932 // Allow: home, end, left, right, down, up
933 (event.keyCode >= 35 && event.keyCode <= 40)) {
934 // let it happen, don't do anything
935 return;
936 }
937
938 event.preventDefault();
939 event.stopPropagation();
940 },
941
942 make_media_embed_code: function(content, editor){
943 $.post( ajaxurl, {
944 action:'make_media_embed_code',
945 content: content
946 },
947 function(data){
948 // console.log(data);
949 editor.setContent(editor.getContent() + editor.setContent(data));
950 }
951 )
952 }
953 }
954 };
955
956 $(function() {
957 WP_User_Frontend.init();
958
959 // payment gateway selection
960 $('ul.wpuf-payment-gateways').on('click', 'input[type=radio]', function(e) {
961 $('.wpuf-payment-instruction').slideUp(250);
962
963 $(this).parents('li').find('.wpuf-payment-instruction').slideDown(250);
964 });
965
966 if( !$('ul.wpuf-payment-gateways li').find('input[type=radio]').is(':checked') ) {
967 $('ul.wpuf-payment-gateways li').first().find('input[type=radio]').click()
968 } else {
969 var el = $('ul.wpuf-payment-gateways li').find('input[type=radio]:checked');
970 el.parents('li').find('.wpuf-payment-instruction').slideDown(250);
971 }
972 });
973
974 $(function() {
975 $('input[name="first_name"], input[name="last_name"]').on('change keyup', function() {
976 var myVal, newVal = $.makeArray($('input[name="first_name"], input[name="last_name"]').map(function(){
977 if (myVal = $(this).val()) {
978 return(myVal);
979 }
980 })).join(' ');
981 $('input[name="display_name"]').val(newVal);
982 });
983 });
984
985 // script for Dokan vendor registration template
986 $(function($) {
987
988 $('.wpuf-form-add input[name="dokan_store_name"]').on('focusout', function() {
989 var value = $(this).val().toLowerCase().replace(/-+/g, '').replace(/\s+/g, '-').replace(/[^a-z0-9-]/g, '');
990 $('input[name="shopurl"]').val(value);
991 $('#url-alart').text( value );
992 $('input[name="shopurl"]').focus();
993 });
994
995 $('.wpuf-form-add input[name="shopurl"]').keydown(function(e) {
996 var text = $(this).val();
997
998 // Allow: backspace, delete, tab, escape, enter and .
999 if ($.inArray(e.keyCode, [46, 8, 9, 27, 13, 91, 109, 110, 173, 189, 190]) !== -1 ||
1000 // Allow: Ctrl+A
1001 (e.keyCode == 65 && e.ctrlKey === true) ||
1002 // Allow: home, end, left, right
1003 (e.keyCode >= 35 && e.keyCode <= 39)) {
1004 // let it happen, don't do anything
1005 return;
1006 }
1007
1008 if ((e.shiftKey || (e.keyCode < 65 || e.keyCode > 90) && (e.keyCode < 48 || e.keyCode > 57)) && (e.keyCode < 96 || e.keyCode > 105) ) {
1009 e.preventDefault();
1010 }
1011 });
1012
1013 $('.wpuf-form-add input[name="shopurl"]').keyup(function(e) {
1014 $('#url-alart').text( $(this).val() );
1015 });
1016
1017 $('.wpuf-form-add input[name="shopurl"]').on('focusout', function() {
1018 var self = $(this),
1019 data = {
1020 action : 'shop_url',
1021 url_slug : self.val(),
1022 _nonce : dokan.nonce,
1023 };
1024
1025 if ( self.val() === '' ) {
1026 return;
1027 }
1028
1029 $.post( dokan.ajaxurl, data, function(resp) {
1030
1031 if ( resp == 0){
1032 $('#url-alart').removeClass('text-success').addClass('text-danger');
1033 $('#url-alart-mgs').removeClass('text-success').addClass('text-danger').text(dokan.seller.notAvailable);
1034 } else {
1035 $('#url-alart').removeClass('text-danger').addClass('text-success');
1036 $('#url-alart-mgs').removeClass('text-danger').addClass('text-success').text(dokan.seller.available);
1037 }
1038
1039 } );
1040
1041 });
1042
1043 // Set name attribute for google map search field
1044 $(".wpuf-form-add #wpuf-map-add-location").attr("name", "find_address");
1045 });
1046
1047 })(jQuery, window);
1048
1049 /* assets/wpuf/vendor/sweetalert2/dist/sweetalert2.js */
1050 /*!
1051 * sweetalert2 v6.6.4
1052 * Released under the MIT License.
1053 */
1054 (function (global, factory) {
1055 typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
1056 typeof define === 'function' && define.amd ? define(factory) :
1057 (global.Sweetalert2 = factory());
1058 }(this, (function () { 'use strict';
1059
1060 var defaultParams = {
1061 title: '',
1062 titleText: '',
1063 text: '',
1064 html: '',
1065 type: null,
1066 customClass: '',
1067 target: 'body',
1068 animation: true,
1069 allowOutsideClick: true,
1070 allowEscapeKey: true,
1071 allowEnterKey: true,
1072 showConfirmButton: true,
1073 showCancelButton: false,
1074 preConfirm: null,
1075 confirmButtonText: 'OK',
1076 confirmButtonColor: '#3085d6',
1077 confirmButtonClass: null,
1078 cancelButtonText: 'Cancel',
1079 cancelButtonColor: '#aaa',
1080 cancelButtonClass: null,
1081 buttonsStyling: true,
1082 reverseButtons: false,
1083 focusCancel: false,
1084 showCloseButton: false,
1085 showLoaderOnConfirm: false,
1086 imageUrl: null,
1087 imageWidth: null,
1088 imageHeight: null,
1089 imageClass: null,
1090 timer: null,
1091 width: 500,
1092 padding: 20,
1093 background: '#fff',
1094 input: null,
1095 inputPlaceholder: '',
1096 inputValue: '',
1097 inputOptions: {},
1098 inputAutoTrim: true,
1099 inputClass: null,
1100 inputAttributes: {},
1101 inputValidator: null,
1102 progressSteps: [],
1103 currentProgressStep: null,
1104 progressStepsDistance: '40px',
1105 onOpen: null,
1106 onClose: null,
1107 useRejections: true
1108 };
1109
1110 var swalPrefix = 'swal2-';
1111
1112 var prefix = function prefix(items) {
1113 var result = {};
1114 for (var i in items) {
1115 result[items[i]] = swalPrefix + items[i];
1116 }
1117 return result;
1118 };
1119
1120 var swalClasses = prefix(['container', 'shown', 'iosfix', 'modal', 'overlay', 'fade', 'show', 'hide', 'noanimation', 'close', 'title', 'content', 'buttonswrapper', 'confirm', 'cancel', 'icon', 'image', 'input', 'file', 'range', 'select', 'radio', 'checkbox', 'textarea', 'inputerror', 'validationerror', 'progresssteps', 'activeprogressstep', 'progresscircle', 'progressline', 'loading', 'styled']);
1121
1122 var iconTypes = prefix(['success', 'warning', 'info', 'question', 'error']);
1123
1124 /*
1125 * Set hover, active and focus-states for buttons (source: http://www.sitepoint.com/javascript-generate-lighter-darker-color)
1126 */
1127 var colorLuminance = function colorLuminance(hex, lum) {
1128 // Validate hex string
1129 hex = String(hex).replace(/[^0-9a-f]/gi, '');
1130 if (hex.length < 6) {
1131 hex = hex[0] + hex[0] + hex[1] + hex[1] + hex[2] + hex[2];
1132 }
1133 lum = lum || 0;
1134
1135 // Convert to decimal and change luminosity
1136 var rgb = '#';
1137 for (var i = 0; i < 3; i++) {
1138 var c = parseInt(hex.substr(i * 2, 2), 16);
1139 c = Math.round(Math.min(Math.max(0, c + c * lum), 255)).toString(16);
1140 rgb += ('00' + c).substr(c.length);
1141 }
1142
1143 return rgb;
1144 };
1145
1146 var uniqueArray = function uniqueArray(arr) {
1147 var result = [];
1148 for (var i in arr) {
1149 if (result.indexOf(arr[i]) === -1) {
1150 result.push(arr[i]);
1151 }
1152 }
1153 return result;
1154 };
1155
1156 /* global MouseEvent */
1157
1158 // Remember state in cases where opening and handling a modal will fiddle with it.
1159 var states = {
1160 previousWindowKeyDown: null,
1161 previousActiveElement: null,
1162 previousBodyPadding: null
1163 };
1164
1165 /*
1166 * Add modal + overlay to DOM
1167 */
1168 var init = function init(params) {
1169 if (typeof document === 'undefined') {
1170 console.error('SweetAlert2 requires document to initialize');
1171 return;
1172 }
1173
1174 var container = document.createElement('div');
1175 container.className = swalClasses.container;
1176 container.innerHTML = sweetHTML;
1177
1178 var targetElement = document.querySelector(params.target);
1179 if (!targetElement) {
1180 console.warn('SweetAlert2: Can\'t find the target "' + params.target + '"');
1181 targetElement = document.body;
1182 }
1183 targetElement.appendChild(container);
1184
1185 var modal = getModal();
1186 var input = getChildByClass(modal, swalClasses.input);
1187 var file = getChildByClass(modal, swalClasses.file);
1188 var range = modal.querySelector('.' + swalClasses.range + ' input');
1189 var rangeOutput = modal.querySelector('.' + swalClasses.range + ' output');
1190 var select = getChildByClass(modal, swalClasses.select);
1191 var checkbox = modal.querySelector('.' + swalClasses.checkbox + ' input');
1192 var textarea = getChildByClass(modal, swalClasses.textarea);
1193
1194 input.oninput = function () {
1195 sweetAlert.resetValidationError();
1196 };
1197
1198 input.onkeydown = function (event) {
1199 setTimeout(function () {
1200 if (event.keyCode === 13 && params.allowEnterKey) {
1201 event.stopPropagation();
1202 sweetAlert.clickConfirm();
1203 }
1204 }, 0);
1205 };
1206
1207 file.onchange = function () {
1208 sweetAlert.resetValidationError();
1209 };
1210
1211 range.oninput = function () {
1212 sweetAlert.resetValidationError();
1213 rangeOutput.value = range.value;
1214 };
1215
1216 range.onchange = function () {
1217 sweetAlert.resetValidationError();
1218 range.previousSibling.value = range.value;
1219 };
1220
1221 select.onchange = function () {
1222 sweetAlert.resetValidationError();
1223 };
1224
1225 checkbox.onchange = function () {
1226 sweetAlert.resetValidationError();
1227 };
1228
1229 textarea.oninput = function () {
1230 sweetAlert.resetValidationError();
1231 };
1232
1233 return modal;
1234 };
1235
1236 /*
1237 * Manipulate DOM
1238 */
1239
1240 var sweetHTML = ('\n <div role="dialog" aria-labelledby="' + swalClasses.title + '" aria-describedby="' + swalClasses.content + '" class="' + swalClasses.modal + '" tabindex="-1">\n <ul class="' + swalClasses.progresssteps + '"></ul>\n <div class="' + swalClasses.icon + ' ' + iconTypes.error + '">\n <span class="swal2-x-mark"><span class="swal2-x-mark-line-left"></span><span class="swal2-x-mark-line-right"></span></span>\n </div>\n <div class="' + swalClasses.icon + ' ' + iconTypes.question + '">?</div>\n <div class="' + swalClasses.icon + ' ' + iconTypes.warning + '">!</div>\n <div class="' + swalClasses.icon + ' ' + iconTypes.info + '">i</div>\n <div class="' + swalClasses.icon + ' ' + iconTypes.success + '">\n <div class="swal2-success-circular-line-left"></div>\n <span class="swal2-success-line-tip"></span> <span class="swal2-success-line-long"></span>\n <div class="swal2-success-ring"></div> <div class="swal2-success-fix"></div>\n <div class="swal2-success-circular-line-right"></div>\n </div>\n <img class="' + swalClasses.image + '">\n <h2 class="' + swalClasses.title + '" id="' + swalClasses.title + '"></h2>\n <div id="' + swalClasses.content + '" class="' + swalClasses.content + '"></div>\n <input class="' + swalClasses.input + '">\n <input type="file" class="' + swalClasses.file + '">\n <div class="' + swalClasses.range + '">\n <output></output>\n <input type="range">\n </div>\n <select class="' + swalClasses.select + '"></select>\n <div class="' + swalClasses.radio + '"></div>\n <label for="' + swalClasses.checkbox + '" class="' + swalClasses.checkbox + '">\n <input type="checkbox">\n </label>\n <textarea class="' + swalClasses.textarea + '"></textarea>\n <div class="' + swalClasses.validationerror + '"></div>\n <div class="' + swalClasses.buttonswrapper + '">\n <button type="button" class="' + swalClasses.confirm + '">OK</button>\n <button type="button" class="' + swalClasses.cancel + '">Cancel</button>\n </div>\n <button type="button" class="' + swalClasses.close + '" aria-label="Close this dialog">&times;</button>\n </div>\n').replace(/(^|\n)\s*/g, '');
1241
1242 var getContainer = function getContainer() {
1243 return document.body.querySelector('.' + swalClasses.container);
1244 };
1245
1246 var getModal = function getModal() {
1247 return getContainer() ? getContainer().querySelector('.' + swalClasses.modal) : null;
1248 };
1249
1250 var getIcons = function getIcons() {
1251 var modal = getModal();
1252 return modal.querySelectorAll('.' + swalClasses.icon);
1253 };
1254
1255 var elementByClass = function elementByClass(className) {
1256 return getContainer() ? getContainer().querySelector('.' + className) : null;
1257 };
1258
1259 var getTitle = function getTitle() {
1260 return elementByClass(swalClasses.title);
1261 };
1262
1263 var getContent = function getContent() {
1264 return elementByClass(swalClasses.content);
1265 };
1266
1267 var getImage = function getImage() {
1268 return elementByClass(swalClasses.image);
1269 };
1270
1271 var getButtonsWrapper = function getButtonsWrapper() {
1272 return elementByClass(swalClasses.buttonswrapper);
1273 };
1274
1275 var getProgressSteps = function getProgressSteps() {
1276 return elementByClass(swalClasses.progresssteps);
1277 };
1278
1279 var getValidationError = function getValidationError() {
1280 return elementByClass(swalClasses.validationerror);
1281 };
1282
1283 var getConfirmButton = function getConfirmButton() {
1284 return elementByClass(swalClasses.confirm);
1285 };
1286
1287 var getCancelButton = function getCancelButton() {
1288 return elementByClass(swalClasses.cancel);
1289 };
1290
1291 var getCloseButton = function getCloseButton() {
1292 return elementByClass(swalClasses.close);
1293 };
1294
1295 var getFocusableElements = function getFocusableElements(focusCancel) {
1296 var buttons = [getConfirmButton(), getCancelButton()];
1297 if (focusCancel) {
1298 buttons.reverse();
1299 }
1300 var focusableElements = buttons.concat(Array.prototype.slice.call(getModal().querySelectorAll('button, input:not([type=hidden]), textarea, select, a, *[tabindex]:not([tabindex="-1"])')));
1301 return uniqueArray(focusableElements);
1302 };
1303
1304 var hasClass = function hasClass(elem, className) {
1305 if (elem.classList) {
1306 return elem.classList.contains(className);
1307 }
1308 return false;
1309 };
1310
1311 var focusInput = function focusInput(input) {
1312 input.focus();
1313
1314 // place cursor at end of text in text input
1315 if (input.type !== 'file') {
1316 // http://stackoverflow.com/a/2345915/1331425
1317 var val = input.value;
1318 input.value = '';
1319 input.value = val;
1320 }
1321 };
1322
1323 var addClass = function addClass(elem, className) {
1324 if (!elem || !className) {
1325 return;
1326 }
1327 var classes = className.split(/\s+/).filter(Boolean);
1328 classes.forEach(function (className) {
1329 elem.classList.add(className);
1330 });
1331 };
1332
1333 var removeClass = function removeClass(elem, className) {
1334 if (!elem || !className) {
1335 return;
1336 }
1337 var classes = className.split(/\s+/).filter(Boolean);
1338 classes.forEach(function (className) {
1339 elem.classList.remove(className);
1340 });
1341 };
1342
1343 var getChildByClass = function getChildByClass(elem, className) {
1344 for (var i = 0; i < elem.childNodes.length; i++) {
1345 if (hasClass(elem.childNodes[i], className)) {
1346 return elem.childNodes[i];
1347 }
1348 }
1349 };
1350
1351 var show = function show(elem, display) {
1352 if (!display) {
1353 display = 'block';
1354 }
1355 elem.style.opacity = '';
1356 elem.style.display = display;
1357 };
1358
1359 var hide = function hide(elem) {
1360 elem.style.opacity = '';
1361 elem.style.display = 'none';
1362 };
1363
1364 var empty = function empty(elem) {
1365 while (elem.firstChild) {
1366 elem.removeChild(elem.firstChild);
1367 }
1368 };
1369
1370 // borrowed from jqeury $(elem).is(':visible') implementation
1371 var isVisible = function isVisible(elem) {
1372 return elem.offsetWidth || elem.offsetHeight || elem.getClientRects().length;
1373 };
1374
1375 var removeStyleProperty = function removeStyleProperty(elem, property) {
1376 if (elem.style.removeProperty) {
1377 elem.style.removeProperty(property);
1378 } else {
1379 elem.style.removeAttribute(property);
1380 }
1381 };
1382
1383 var fireClick = function fireClick(node) {
1384 if (!isVisible(node)) {
1385 return false;
1386 }
1387
1388 // Taken from http://www.nonobtrusive.com/2011/11/29/programatically-fire-crossbrowser-click-event-with-javascript/
1389 // Then fixed for today's Chrome browser.
1390 if (typeof MouseEvent === 'function') {
1391 // Up-to-date approach
1392 var mevt = new MouseEvent('click', {
1393 view: window,
1394 bubbles: false,
1395 cancelable: true
1396 });
1397 node.dispatchEvent(mevt);
1398 } else if (document.createEvent) {
1399 // Fallback
1400 var evt = document.createEvent('MouseEvents');
1401 evt.initEvent('click', false, false);
1402 node.dispatchEvent(evt);
1403 } else if (document.createEventObject) {
1404 node.fireEvent('onclick');
1405 } else if (typeof node.onclick === 'function') {
1406 node.onclick();
1407 }
1408 };
1409
1410 var animationEndEvent = function () {
1411 var testEl = document.createElement('div');
1412 var transEndEventNames = {
1413 'WebkitAnimation': 'webkitAnimationEnd',
1414 'OAnimation': 'oAnimationEnd oanimationend',
1415 'msAnimation': 'MSAnimationEnd',
1416 'animation': 'animationend'
1417 };
1418 for (var i in transEndEventNames) {
1419 if (transEndEventNames.hasOwnProperty(i) && testEl.style[i] !== undefined) {
1420 return transEndEventNames[i];
1421 }
1422 }
1423
1424 return false;
1425 }();
1426
1427 // Reset previous window keydown handler and focued element
1428 var resetPrevState = function resetPrevState() {
1429 window.onkeydown = states.previousWindowKeyDown;
1430 if (states.previousActiveElement && states.previousActiveElement.focus) {
1431 var x = window.scrollX;
1432 var y = window.scrollY;
1433 states.previousActiveElement.focus();
1434 if (x && y) {
1435 // IE has no scrollX/scrollY support
1436 window.scrollTo(x, y);
1437 }
1438 }
1439 };
1440
1441 // Measure width of scrollbar
1442 // https://github.com/twbs/bootstrap/blob/master/js/modal.js#L279-L286
1443 var measureScrollbar = function measureScrollbar() {
1444 var supportsTouch = 'ontouchstart' in window || navigator.msMaxTouchPoints;
1445 if (supportsTouch) {
1446 return 0;
1447 }
1448 var scrollDiv = document.createElement('div');
1449 scrollDiv.style.width = '50px';
1450 scrollDiv.style.height = '50px';
1451 scrollDiv.style.overflow = 'scroll';
1452 document.body.appendChild(scrollDiv);
1453 var scrollbarWidth = scrollDiv.offsetWidth - scrollDiv.clientWidth;
1454 document.body.removeChild(scrollDiv);
1455 return scrollbarWidth;
1456 };
1457
1458 // JavaScript Debounce Function
1459 // Simplivied version of https://davidwalsh.name/javascript-debounce-function
1460 var debounce = function debounce(func, wait) {
1461 var timeout = void 0;
1462 return function () {
1463 var later = function later() {
1464 timeout = null;
1465 func();
1466 };
1467 clearTimeout(timeout);
1468 timeout = setTimeout(later, wait);
1469 };
1470 };
1471
1472 var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) {
1473 return typeof obj;
1474 } : function (obj) {
1475 return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj;
1476 };
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498 var _extends = Object.assign || function (target) {
1499 for (var i = 1; i < arguments.length; i++) {
1500 var source = arguments[i];
1501
1502 for (var key in source) {
1503 if (Object.prototype.hasOwnProperty.call(source, key)) {
1504 target[key] = source[key];
1505 }
1506 }
1507 }
1508
1509 return target;
1510 };
1511
1512 var modalParams = _extends({}, defaultParams);
1513 var queue = [];
1514 var swal2Observer = void 0;
1515
1516 /*
1517 * Set type, text and actions on modal
1518 */
1519 var setParameters = function setParameters(params) {
1520 var modal = getModal() || init(params);
1521
1522 for (var param in params) {
1523 if (!defaultParams.hasOwnProperty(param) && param !== 'extraParams') {
1524 console.warn('SweetAlert2: Unknown parameter "' + param + '"');
1525 }
1526 }
1527
1528 // Set modal width
1529 modal.style.width = typeof params.width === 'number' ? params.width + 'px' : params.width;
1530
1531 modal.style.padding = params.padding + 'px';
1532 modal.style.background = params.background;
1533 var successIconParts = modal.querySelectorAll('[class^=swal2-success-circular-line], .swal2-success-fix');
1534 for (var i = 0; i < successIconParts.length; i++) {
1535 successIconParts[i].style.background = params.background;
1536 }
1537
1538 var title = getTitle();
1539 var content = getContent();
1540 var buttonsWrapper = getButtonsWrapper();
1541 var confirmButton = getConfirmButton();
1542 var cancelButton = getCancelButton();
1543 var closeButton = getCloseButton();
1544
1545 // Title
1546 if (params.titleText) {
1547 title.innerText = params.titleText;
1548 } else {
1549 title.innerHTML = params.title.split('\n').join('<br>');
1550 }
1551
1552 // Content
1553 if (params.text || params.html) {
1554 if (_typeof(params.html) === 'object') {
1555 content.innerHTML = '';
1556 if (0 in params.html) {
1557 for (var _i = 0; _i in params.html; _i++) {
1558 content.appendChild(params.html[_i].cloneNode(true));
1559 }
1560 } else {
1561 content.appendChild(params.html.cloneNode(true));
1562 }
1563 } else if (params.html) {
1564 content.innerHTML = params.html;
1565 } else if (params.text) {
1566 content.textContent = params.text;
1567 }
1568 show(content);
1569 } else {
1570 hide(content);
1571 }
1572
1573 // Close button
1574 if (params.showCloseButton) {
1575 show(closeButton);
1576 } else {
1577 hide(closeButton);
1578 }
1579
1580 // Custom Class
1581 modal.className = swalClasses.modal;
1582 if (params.customClass) {
1583 addClass(modal, params.customClass);
1584 }
1585
1586 // Progress steps
1587 var progressStepsContainer = getProgressSteps();
1588 var currentProgressStep = parseInt(params.currentProgressStep === null ? sweetAlert.getQueueStep() : params.currentProgressStep, 10);
1589 if (params.progressSteps.length) {
1590 show(progressStepsContainer);
1591 empty(progressStepsContainer);
1592 if (currentProgressStep >= params.progressSteps.length) {
1593 console.warn('SweetAlert2: Invalid currentProgressStep parameter, it should be less than progressSteps.length ' + '(currentProgressStep like JS arrays starts from 0)');
1594 }
1595 params.progressSteps.forEach(function (step, index) {
1596 var circle = document.createElement('li');
1597 addClass(circle, swalClasses.progresscircle);
1598 circle.innerHTML = step;
1599 if (index === currentProgressStep) {
1600 addClass(circle, swalClasses.activeprogressstep);
1601 }
1602 progressStepsContainer.appendChild(circle);
1603 if (index !== params.progressSteps.length - 1) {
1604 var line = document.createElement('li');
1605 addClass(line, swalClasses.progressline);
1606 line.style.width = params.progressStepsDistance;
1607 progressStepsContainer.appendChild(line);
1608 }
1609 });
1610 } else {
1611 hide(progressStepsContainer);
1612 }
1613
1614 // Icon
1615 var icons = getIcons();
1616 for (var _i2 = 0; _i2 < icons.length; _i2++) {
1617 hide(icons[_i2]);
1618 }
1619 if (params.type) {
1620 var validType = false;
1621 for (var iconType in iconTypes) {
1622 if (params.type === iconType) {
1623 validType = true;
1624 break;
1625 }
1626 }
1627 if (!validType) {
1628 console.error('SweetAlert2: Unknown alert type: ' + params.type);
1629 return false;
1630 }
1631 var icon = modal.querySelector('.' + swalClasses.icon + '.' + iconTypes[params.type]);
1632 show(icon);
1633
1634 // Animate icon
1635 if (params.animation) {
1636 switch (params.type) {
1637 case 'success':
1638 addClass(icon, 'swal2-animate-success-icon');
1639 addClass(icon.querySelector('.swal2-success-line-tip'), 'swal2-animate-success-line-tip');
1640 addClass(icon.querySelector('.swal2-success-line-long'), 'swal2-animate-success-line-long');
1641 break;
1642 case 'error':
1643 addClass(icon, 'swal2-animate-error-icon');
1644 addClass(icon.querySelector('.swal2-x-mark'), 'swal2-animate-x-mark');
1645 break;
1646 default:
1647 break;
1648 }
1649 }
1650 }
1651
1652 // Custom image
1653 var image = getImage();
1654 if (params.imageUrl) {
1655 image.setAttribute('src', params.imageUrl);
1656 show(image);
1657
1658 if (params.imageWidth) {
1659 image.setAttribute('width', params.imageWidth);
1660 } else {
1661 image.removeAttribute('width');
1662 }
1663
1664 if (params.imageHeight) {
1665 image.setAttribute('height', params.imageHeight);
1666 } else {
1667 image.removeAttribute('height');
1668 }
1669
1670 image.className = swalClasses.image;
1671 if (params.imageClass) {
1672 addClass(image, params.imageClass);
1673 }
1674 } else {
1675 hide(image);
1676 }
1677
1678 // Cancel button
1679 if (params.showCancelButton) {
1680 cancelButton.style.display = 'inline-block';
1681 } else {
1682 hide(cancelButton);
1683 }
1684
1685 // Confirm button
1686 if (params.showConfirmButton) {
1687 removeStyleProperty(confirmButton, 'display');
1688 } else {
1689 hide(confirmButton);
1690 }
1691
1692 // Buttons wrapper
1693 if (!params.showConfirmButton && !params.showCancelButton) {
1694 hide(buttonsWrapper);
1695 } else {
1696 show(buttonsWrapper);
1697 }
1698
1699 // Edit text on cancel and confirm buttons
1700 confirmButton.innerHTML = params.confirmButtonText;
1701 cancelButton.innerHTML = params.cancelButtonText;
1702
1703 // Set buttons to selected background colors
1704 if (params.buttonsStyling) {
1705 confirmButton.style.backgroundColor = params.confirmButtonColor;
1706 cancelButton.style.backgroundColor = params.cancelButtonColor;
1707 }
1708
1709 // Add buttons custom classes
1710 confirmButton.className = swalClasses.confirm;
1711 addClass(confirmButton, params.confirmButtonClass);
1712 cancelButton.className = swalClasses.cancel;
1713 addClass(cancelButton, params.cancelButtonClass);
1714
1715 // Buttons styling
1716 if (params.buttonsStyling) {
1717 addClass(confirmButton, swalClasses.styled);
1718 addClass(cancelButton, swalClasses.styled);
1719 } else {
1720 removeClass(confirmButton, swalClasses.styled);
1721 removeClass(cancelButton, swalClasses.styled);
1722
1723 confirmButton.style.backgroundColor = confirmButton.style.borderLeftColor = confirmButton.style.borderRightColor = '';
1724 cancelButton.style.backgroundColor = cancelButton.style.borderLeftColor = cancelButton.style.borderRightColor = '';
1725 }
1726
1727 // CSS animation
1728 if (params.animation === true) {
1729 removeClass(modal, swalClasses.noanimation);
1730 } else {
1731 addClass(modal, swalClasses.noanimation);
1732 }
1733 };
1734
1735 /*
1736 * Animations
1737 */
1738 var openModal = function openModal(animation, onComplete) {
1739 var container = getContainer();
1740 var modal = getModal();
1741
1742 if (animation) {
1743 addClass(modal, swalClasses.show);
1744 addClass(container, swalClasses.fade);
1745 removeClass(modal, swalClasses.hide);
1746 } else {
1747 removeClass(modal, swalClasses.fade);
1748 }
1749 show(modal);
1750
1751 // scrolling is 'hidden' until animation is done, after that 'auto'
1752 container.style.overflowY = 'hidden';
1753 if (animationEndEvent && !hasClass(modal, swalClasses.noanimation)) {
1754 modal.addEventListener(animationEndEvent, function swalCloseEventFinished() {
1755 modal.removeEventListener(animationEndEvent, swalCloseEventFinished);
1756 container.style.overflowY = 'auto';
1757 });
1758 } else {
1759 container.style.overflowY = 'auto';
1760 }
1761
1762 addClass(document.documentElement, swalClasses.shown);
1763 addClass(document.body, swalClasses.shown);
1764 addClass(container, swalClasses.shown);
1765 fixScrollbar();
1766 iOSfix();
1767 states.previousActiveElement = document.activeElement;
1768 if (onComplete !== null && typeof onComplete === 'function') {
1769 setTimeout(function () {
1770 onComplete(modal);
1771 });
1772 }
1773 };
1774
1775 var fixScrollbar = function fixScrollbar() {
1776 // for queues, do not do this more than once
1777 if (states.previousBodyPadding !== null) {
1778 return;
1779 }
1780 // if the body has overflow
1781 if (document.body.scrollHeight > window.innerHeight) {
1782 // add padding so the content doesn't shift after removal of scrollbar
1783 states.previousBodyPadding = document.body.style.paddingRight;
1784 document.body.style.paddingRight = measureScrollbar() + 'px';
1785 }
1786 };
1787
1788 var undoScrollbar = function undoScrollbar() {
1789 if (states.previousBodyPadding !== null) {
1790 document.body.style.paddingRight = states.previousBodyPadding;
1791 states.previousBodyPadding = null;
1792 }
1793 };
1794
1795 // Fix iOS scrolling http://stackoverflow.com/q/39626302/1331425
1796 var iOSfix = function iOSfix() {
1797 var iOS = /iPad|iPhone|iPod/.test(navigator.userAgent) && !window.MSStream;
1798 if (iOS && !hasClass(document.body, swalClasses.iosfix)) {
1799 var offset = document.body.scrollTop;
1800 document.body.style.top = offset * -1 + 'px';
1801 addClass(document.body, swalClasses.iosfix);
1802 }
1803 };
1804
1805 var undoIOSfix = function undoIOSfix() {
1806 if (hasClass(document.body, swalClasses.iosfix)) {
1807 var offset = parseInt(document.body.style.top, 10);
1808 removeClass(document.body, swalClasses.iosfix);
1809 document.body.style.top = '';
1810 document.body.scrollTop = offset * -1;
1811 }
1812 };
1813
1814 // SweetAlert entry point
1815 var sweetAlert = function sweetAlert() {
1816 for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) {
1817 args[_key] = arguments[_key];
1818 }
1819
1820 if (args[0] === undefined) {
1821 console.error('SweetAlert2 expects at least 1 attribute!');
1822 return false;
1823 }
1824
1825 var params = _extends({}, modalParams);
1826
1827 switch (_typeof(args[0])) {
1828 case 'string':
1829 params.title = args[0];
1830 params.html = args[1];
1831 params.type = args[2];
1832
1833 break;
1834
1835 case 'object':
1836 _extends(params, args[0]);
1837 params.extraParams = args[0].extraParams;
1838
1839 if (params.input === 'email' && params.inputValidator === null) {
1840 params.inputValidator = function (email) {
1841 return new Promise(function (resolve, reject) {
1842 var emailRegex = /^[a-zA-Z0-9.+_-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,6}$/;
1843 if (emailRegex.test(email)) {
1844 resolve();
1845 } else {
1846 reject('Invalid email address');
1847 }
1848 });
1849 };
1850 }
1851
1852 if (params.input === 'url' && params.inputValidator === null) {
1853 params.inputValidator = function (url) {
1854 return new Promise(function (resolve, reject) {
1855 var urlRegex = /^(https?:\/\/)?([\da-z.-]+)\.([a-z.]{2,6})([/\w .-]*)*\/?$/;
1856 if (urlRegex.test(url)) {
1857 resolve();
1858 } else {
1859 reject('Invalid URL');
1860 }
1861 });
1862 };
1863 }
1864 break;
1865
1866 default:
1867 console.error('SweetAlert2: Unexpected type of argument! Expected "string" or "object", got ' + _typeof(args[0]));
1868 return false;
1869 }
1870
1871 setParameters(params);
1872
1873 var container = getContainer();
1874 var modal = getModal();
1875
1876 return new Promise(function (resolve, reject) {
1877 // Close on timer
1878 if (params.timer) {
1879 modal.timeout = setTimeout(function () {
1880 sweetAlert.closeModal(params.onClose);
1881 if (params.useRejections) {
1882 reject('timer');
1883 } else {
1884 resolve({ dismiss: 'timer' });
1885 }
1886 }, params.timer);
1887 }
1888
1889 // Get input element by specified type or, if type isn't specified, by params.input
1890 var getInput = function getInput(inputType) {
1891 inputType = inputType || params.input;
1892 if (!inputType) {
1893 return null;
1894 }
1895 switch (inputType) {
1896 case 'select':
1897 case 'textarea':
1898 case 'file':
1899 return getChildByClass(modal, swalClasses[inputType]);
1900 case 'checkbox':
1901 return modal.querySelector('.' + swalClasses.checkbox + ' input');
1902 case 'radio':
1903 return modal.querySelector('.' + swalClasses.radio + ' input:checked') || modal.querySelector('.' + swalClasses.radio + ' input:first-child');
1904 case 'range':
1905 return modal.querySelector('.' + swalClasses.range + ' input');
1906 default:
1907 return getChildByClass(modal, swalClasses.input);
1908 }
1909 };
1910
1911 // Get the value of the modal input
1912 var getInputValue = function getInputValue() {
1913 var input = getInput();
1914 if (!input) {
1915 return null;
1916 }
1917 switch (params.input) {
1918 case 'checkbox':
1919 return input.checked ? 1 : 0;
1920 case 'radio':
1921 return input.checked ? input.value : null;
1922 case 'file':
1923 return input.files.length ? input.files[0] : null;
1924 default:
1925 return params.inputAutoTrim ? input.value.trim() : input.value;
1926 }
1927 };
1928
1929 // input autofocus
1930 if (params.input) {
1931 setTimeout(function () {
1932 var input = getInput();
1933 if (input) {
1934 focusInput(input);
1935 }
1936 }, 0);
1937 }
1938
1939 var confirm = function confirm(value) {
1940 if (params.showLoaderOnConfirm) {
1941 sweetAlert.showLoading();
1942 }
1943
1944 if (params.preConfirm) {
1945 params.preConfirm(value, params.extraParams).then(function (preConfirmValue) {
1946 sweetAlert.closeModal(params.onClose);
1947 resolve(preConfirmValue || value);
1948 }, function (error) {
1949 sweetAlert.hideLoading();
1950 if (error) {
1951 sweetAlert.showValidationError(error);
1952 }
1953 });
1954 } else {
1955 sweetAlert.closeModal(params.onClose);
1956 if (params.useRejections) {
1957 resolve(value);
1958 } else {
1959 resolve({ value: value });
1960 }
1961 }
1962 };
1963
1964 // Mouse interactions
1965 var onButtonEvent = function onButtonEvent(event) {
1966 var e = event || window.event;
1967 var target = e.target || e.srcElement;
1968 var confirmButton = getConfirmButton();
1969 var cancelButton = getCancelButton();
1970 var targetedConfirm = confirmButton && (confirmButton === target || confirmButton.contains(target));
1971 var targetedCancel = cancelButton && (cancelButton === target || cancelButton.contains(target));
1972
1973 switch (e.type) {
1974 case 'mouseover':
1975 case 'mouseup':
1976 if (params.buttonsStyling) {
1977 if (targetedConfirm) {
1978 confirmButton.style.backgroundColor = colorLuminance(params.confirmButtonColor, -0.1);
1979 } else if (targetedCancel) {
1980 cancelButton.style.backgroundColor = colorLuminance(params.cancelButtonColor, -0.1);
1981 }
1982 }
1983 break;
1984 case 'mouseout':
1985 if (params.buttonsStyling) {
1986 if (targetedConfirm) {
1987 confirmButton.style.backgroundColor = params.confirmButtonColor;
1988 } else if (targetedCancel) {
1989 cancelButton.style.backgroundColor = params.cancelButtonColor;
1990 }
1991 }
1992 break;
1993 case 'mousedown':
1994 if (params.buttonsStyling) {
1995 if (targetedConfirm) {
1996 confirmButton.style.backgroundColor = colorLuminance(params.confirmButtonColor, -0.2);
1997 } else if (targetedCancel) {
1998 cancelButton.style.backgroundColor = colorLuminance(params.cancelButtonColor, -0.2);
1999 }
2000 }
2001 break;
2002 case 'click':
2003 // Clicked 'confirm'
2004 if (targetedConfirm && sweetAlert.isVisible()) {
2005 sweetAlert.disableButtons();
2006 if (params.input) {
2007 var inputValue = getInputValue();
2008
2009 if (params.inputValidator) {
2010 sweetAlert.disableInput();
2011 params.inputValidator(inputValue, params.extraParams).then(function () {
2012 sweetAlert.enableButtons();
2013 sweetAlert.enableInput();
2014 confirm(inputValue);
2015 }, function (error) {
2016 sweetAlert.enableButtons();
2017 sweetAlert.enableInput();
2018 if (error) {
2019 sweetAlert.showValidationError(error);
2020 }
2021 });
2022 } else {
2023 confirm(inputValue);
2024 }
2025 } else {
2026 confirm(true);
2027 }
2028
2029 // Clicked 'cancel'
2030 } else if (targetedCancel && sweetAlert.isVisible()) {
2031 sweetAlert.disableButtons();
2032 sweetAlert.closeModal(params.onClose);
2033 if (params.useRejections) {
2034 reject('cancel');
2035 } else {
2036 resolve({ dismiss: 'cancel' });
2037 }
2038 }
2039 break;
2040 default:
2041 }
2042 };
2043
2044 var buttons = modal.querySelectorAll('button');
2045 for (var i = 0; i < buttons.length; i++) {
2046 buttons[i].onclick = onButtonEvent;
2047 buttons[i].onmouseover = onButtonEvent;
2048 buttons[i].onmouseout = onButtonEvent;
2049 buttons[i].onmousedown = onButtonEvent;
2050 }
2051
2052 // Closing modal by close button
2053 getCloseButton().onclick = function () {
2054 sweetAlert.closeModal(params.onClose);
2055 if (params.useRejections) {
2056 reject('close');
2057 } else {
2058 resolve({ dismiss: 'close' });
2059 }
2060 };
2061
2062 // Closing modal by overlay click
2063 container.onclick = function (e) {
2064 if (e.target !== container) {
2065 return;
2066 }
2067 if (params.allowOutsideClick) {
2068 sweetAlert.closeModal(params.onClose);
2069 if (params.useRejections) {
2070 reject('overlay');
2071 } else {
2072 resolve({ dismiss: 'overlay' });
2073 }
2074 }
2075 };
2076
2077 var buttonsWrapper = getButtonsWrapper();
2078 var confirmButton = getConfirmButton();
2079 var cancelButton = getCancelButton();
2080
2081 // Reverse buttons (Confirm on the right side)
2082 if (params.reverseButtons) {
2083 confirmButton.parentNode.insertBefore(cancelButton, confirmButton);
2084 } else {
2085 confirmButton.parentNode.insertBefore(confirmButton, cancelButton);
2086 }
2087
2088 // Focus handling
2089 var setFocus = function setFocus(index, increment) {
2090 var focusableElements = getFocusableElements(params.focusCancel);
2091 // search for visible elements and select the next possible match
2092 for (var _i3 = 0; _i3 < focusableElements.length; _i3++) {
2093 index = index + increment;
2094
2095 // rollover to first item
2096 if (index === focusableElements.length) {
2097 index = 0;
2098
2099 // go to last item
2100 } else if (index === -1) {
2101 index = focusableElements.length - 1;
2102 }
2103
2104 // determine if element is visible
2105 var el = focusableElements[index];
2106 if (isVisible(el)) {
2107 return el.focus();
2108 }
2109 }
2110 };
2111
2112 var handleKeyDown = function handleKeyDown(event) {
2113 var e = event || window.event;
2114 var keyCode = e.keyCode || e.which;
2115
2116 if ([9, 13, 32, 27, 37, 38, 39, 40].indexOf(keyCode) === -1) {
2117 // Don't do work on keys we don't care about.
2118 return;
2119 }
2120
2121 var targetElement = e.target || e.srcElement;
2122
2123 var focusableElements = getFocusableElements(params.focusCancel);
2124 var btnIndex = -1; // Find the button - note, this is a nodelist, not an array.
2125 for (var _i4 = 0; _i4 < focusableElements.length; _i4++) {
2126 if (targetElement === focusableElements[_i4]) {
2127 btnIndex = _i4;
2128 break;
2129 }
2130 }
2131
2132 // TAB
2133 if (keyCode === 9) {
2134 if (!e.shiftKey) {
2135 // Cycle to the next button
2136 setFocus(btnIndex, 1);
2137 } else {
2138 // Cycle to the prev button
2139 setFocus(btnIndex, -1);
2140 }
2141 e.stopPropagation();
2142 e.preventDefault();
2143
2144 // ARROWS - switch focus between buttons
2145 } else if (keyCode === 37 || keyCode === 38 || keyCode === 39 || keyCode === 40) {
2146 // focus Cancel button if Confirm button is currently focused
2147 if (document.activeElement === confirmButton && isVisible(cancelButton)) {
2148 cancelButton.focus();
2149 // and vice versa
2150 } else if (document.activeElement === cancelButton && isVisible(confirmButton)) {
2151 confirmButton.focus();
2152 }
2153
2154 // ENTER/SPACE
2155 } else if (keyCode === 13 || keyCode === 32) {
2156 if (btnIndex === -1 && params.allowEnterKey) {
2157 // ENTER/SPACE clicked outside of a button.
2158 if (params.focusCancel) {
2159 fireClick(cancelButton, e);
2160 } else {
2161 fireClick(confirmButton, e);
2162 }
2163 e.stopPropagation();
2164 e.preventDefault();
2165 }
2166
2167 // ESC
2168 } else if (keyCode === 27 && params.allowEscapeKey === true) {
2169 sweetAlert.closeModal(params.onClose);
2170 if (params.useRejections) {
2171 reject('esc');
2172 } else {
2173 resolve({ dismiss: 'esc' });
2174 }
2175 }
2176 };
2177
2178 if (!window.onkeydown || window.onkeydown.toString() !== handleKeyDown.toString()) {
2179 states.previousWindowKeyDown = window.onkeydown;
2180 window.onkeydown = handleKeyDown;
2181 }
2182
2183 // Loading state
2184 if (params.buttonsStyling) {
2185 confirmButton.style.borderLeftColor = params.confirmButtonColor;
2186 confirmButton.style.borderRightColor = params.confirmButtonColor;
2187 }
2188
2189 /**
2190 * Show spinner instead of Confirm button and disable Cancel button
2191 */
2192 sweetAlert.hideLoading = sweetAlert.disableLoading = function () {
2193 if (!params.showConfirmButton) {
2194 hide(confirmButton);
2195 if (!params.showCancelButton) {
2196 hide(getButtonsWrapper());
2197 }
2198 }
2199 removeClass(buttonsWrapper, swalClasses.loading);
2200 removeClass(modal, swalClasses.loading);
2201 confirmButton.disabled = false;
2202 cancelButton.disabled = false;
2203 };
2204
2205 sweetAlert.getTitle = function () {
2206 return getTitle();
2207 };
2208 sweetAlert.getContent = function () {
2209 return getContent();
2210 };
2211 sweetAlert.getInput = function () {
2212 return getInput();
2213 };
2214 sweetAlert.getImage = function () {
2215 return getImage();
2216 };
2217 sweetAlert.getButtonsWrapper = function () {
2218 return getButtonsWrapper();
2219 };
2220 sweetAlert.getConfirmButton = function () {
2221 return getConfirmButton();
2222 };
2223 sweetAlert.getCancelButton = function () {
2224 return getCancelButton();
2225 };
2226
2227 sweetAlert.enableButtons = function () {
2228 confirmButton.disabled = false;
2229 cancelButton.disabled = false;
2230 };
2231
2232 sweetAlert.disableButtons = function () {
2233 confirmButton.disabled = true;
2234 cancelButton.disabled = true;
2235 };
2236
2237 sweetAlert.enableConfirmButton = function () {
2238 confirmButton.disabled = false;
2239 };
2240
2241 sweetAlert.disableConfirmButton = function () {
2242 confirmButton.disabled = true;
2243 };
2244
2245 sweetAlert.enableInput = function () {
2246 var input = getInput();
2247 if (!input) {
2248 return false;
2249 }
2250 if (input.type === 'radio') {
2251 var radiosContainer = input.parentNode.parentNode;
2252 var radios = radiosContainer.querySelectorAll('input');
2253 for (var _i5 = 0; _i5 < radios.length; _i5++) {
2254 radios[_i5].disabled = false;
2255 }
2256 } else {
2257 input.disabled = false;
2258 }
2259 };
2260
2261 sweetAlert.disableInput = function () {
2262 var input = getInput();
2263 if (!input) {
2264 return false;
2265 }
2266 if (input && input.type === 'radio') {
2267 var radiosContainer = input.parentNode.parentNode;
2268 var radios = radiosContainer.querySelectorAll('input');
2269 for (var _i6 = 0; _i6 < radios.length; _i6++) {
2270 radios[_i6].disabled = true;
2271 }
2272 } else {
2273 input.disabled = true;
2274 }
2275 };
2276
2277 // Set modal min-height to disable scrolling inside the modal
2278 sweetAlert.recalculateHeight = debounce(function () {
2279 var modal = getModal();
2280 if (!modal) {
2281 return;
2282 }
2283 var prevState = modal.style.display;
2284 modal.style.minHeight = '';
2285 show(modal);
2286 modal.style.minHeight = modal.scrollHeight + 1 + 'px';
2287 modal.style.display = prevState;
2288 }, 50);
2289
2290 // Show block with validation error
2291 sweetAlert.showValidationError = function (error) {
2292 var validationError = getValidationError();
2293 validationError.innerHTML = error;
2294 show(validationError);
2295
2296 var input = getInput();
2297 if (input) {
2298 focusInput(input);
2299 addClass(input, swalClasses.inputerror);
2300 }
2301 };
2302
2303 // Hide block with validation error
2304 sweetAlert.resetValidationError = function () {
2305 var validationError = getValidationError();
2306 hide(validationError);
2307 sweetAlert.recalculateHeight();
2308
2309 var input = getInput();
2310 if (input) {
2311 removeClass(input, swalClasses.inputerror);
2312 }
2313 };
2314
2315 sweetAlert.getProgressSteps = function () {
2316 return params.progressSteps;
2317 };
2318
2319 sweetAlert.setProgressSteps = function (progressSteps) {
2320 params.progressSteps = progressSteps;
2321 setParameters(params);
2322 };
2323
2324 sweetAlert.showProgressSteps = function () {
2325 show(getProgressSteps());
2326 };
2327
2328 sweetAlert.hideProgressSteps = function () {
2329 hide(getProgressSteps());
2330 };
2331
2332 sweetAlert.enableButtons();
2333 sweetAlert.hideLoading();
2334 sweetAlert.resetValidationError();
2335
2336 // inputs
2337 var inputTypes = ['input', 'file', 'range', 'select', 'radio', 'checkbox', 'textarea'];
2338 var input = void 0;
2339 for (var _i7 = 0; _i7 < inputTypes.length; _i7++) {
2340 var inputClass = swalClasses[inputTypes[_i7]];
2341 var inputContainer = getChildByClass(modal, inputClass);
2342 input = getInput(inputTypes[_i7]);
2343
2344 // set attributes
2345 if (input) {
2346 for (var j in input.attributes) {
2347 if (input.attributes.hasOwnProperty(j)) {
2348 var attrName = input.attributes[j].name;
2349 if (attrName !== 'type' && attrName !== 'value') {
2350 input.removeAttribute(attrName);
2351 }
2352 }
2353 }
2354 for (var attr in params.inputAttributes) {
2355 input.setAttribute(attr, params.inputAttributes[attr]);
2356 }
2357 }
2358
2359 // set class
2360 inputContainer.className = inputClass;
2361 if (params.inputClass) {
2362 addClass(inputContainer, params.inputClass);
2363 }
2364
2365 hide(inputContainer);
2366 }
2367
2368 var populateInputOptions = void 0;
2369 switch (params.input) {
2370 case 'text':
2371 case 'email':
2372 case 'password':
2373 case 'number':
2374 case 'tel':
2375 case 'url':
2376 input = getChildByClass(modal, swalClasses.input);
2377 input.value = params.inputValue;
2378 input.placeholder = params.inputPlaceholder;
2379 input.type = params.input;
2380 show(input);
2381 break;
2382 case 'file':
2383 input = getChildByClass(modal, swalClasses.file);
2384 input.placeholder = params.inputPlaceholder;
2385 input.type = params.input;
2386 show(input);
2387 break;
2388 case 'range':
2389 var range = getChildByClass(modal, swalClasses.range);
2390 var rangeInput = range.querySelector('input');
2391 var rangeOutput = range.querySelector('output');
2392 rangeInput.value = params.inputValue;
2393 rangeInput.type = params.input;
2394 rangeOutput.value = params.inputValue;
2395 show(range);
2396 break;
2397 case 'select':
2398 var select = getChildByClass(modal, swalClasses.select);
2399 select.innerHTML = '';
2400 if (params.inputPlaceholder) {
2401 var placeholder = document.createElement('option');
2402 placeholder.innerHTML = params.inputPlaceholder;
2403 placeholder.value = '';
2404 placeholder.disabled = true;
2405 placeholder.selected = true;
2406 select.appendChild(placeholder);
2407 }
2408 populateInputOptions = function populateInputOptions(inputOptions) {
2409 for (var optionValue in inputOptions) {
2410 var option = document.createElement('option');
2411 option.value = optionValue;
2412 option.innerHTML = inputOptions[optionValue];
2413 if (params.inputValue === optionValue) {
2414 option.selected = true;
2415 }
2416 select.appendChild(option);
2417 }
2418 show(select);
2419 select.focus();
2420 };
2421 break;
2422 case 'radio':
2423 var radio = getChildByClass(modal, swalClasses.radio);
2424 radio.innerHTML = '';
2425 populateInputOptions = function populateInputOptions(inputOptions) {
2426 for (var radioValue in inputOptions) {
2427 var radioInput = document.createElement('input');
2428 var radioLabel = document.createElement('label');
2429 var radioLabelSpan = document.createElement('span');
2430 radioInput.type = 'radio';
2431 radioInput.name = swalClasses.radio;
2432 radioInput.value = radioValue;
2433 if (params.inputValue === radioValue) {
2434 radioInput.checked = true;
2435 }
2436 radioLabelSpan.innerHTML = inputOptions[radioValue];
2437 radioLabel.appendChild(radioInput);
2438 radioLabel.appendChild(radioLabelSpan);
2439 radioLabel.for = radioInput.id;
2440 radio.appendChild(radioLabel);
2441 }
2442 show(radio);
2443 var radios = radio.querySelectorAll('input');
2444 if (radios.length) {
2445 radios[0].focus();
2446 }
2447 };
2448 break;
2449 case 'checkbox':
2450 var checkbox = getChildByClass(modal, swalClasses.checkbox);
2451 var checkboxInput = getInput('checkbox');
2452 checkboxInput.type = 'checkbox';
2453 checkboxInput.value = 1;
2454 checkboxInput.id = swalClasses.checkbox;
2455 checkboxInput.checked = Boolean(params.inputValue);
2456 var label = checkbox.getElementsByTagName('span');
2457 if (label.length) {
2458 checkbox.removeChild(label[0]);
2459 }
2460 label = document.createElement('span');
2461 label.innerHTML = params.inputPlaceholder;
2462 checkbox.appendChild(label);
2463 show(checkbox);
2464 break;
2465 case 'textarea':
2466 var textarea = getChildByClass(modal, swalClasses.textarea);
2467 textarea.value = params.inputValue;
2468 textarea.placeholder = params.inputPlaceholder;
2469 show(textarea);
2470 break;
2471 case null:
2472 break;
2473 default:
2474 console.error('SweetAlert2: Unexpected type of input! Expected "text", "email", "password", "number", "tel", "select", "radio", "checkbox", "textarea", "file" or "url", got "' + params.input + '"');
2475 break;
2476 }
2477
2478 if (params.input === 'select' || params.input === 'radio') {
2479 if (params.inputOptions instanceof Promise) {
2480 sweetAlert.showLoading();
2481 params.inputOptions.then(function (inputOptions) {
2482 sweetAlert.hideLoading();
2483 populateInputOptions(inputOptions);
2484 });
2485 } else if (_typeof(params.inputOptions) === 'object') {
2486 populateInputOptions(params.inputOptions);
2487 } else {
2488 console.error('SweetAlert2: Unexpected type of inputOptions! Expected object or Promise, got ' + _typeof(params.inputOptions));
2489 }
2490 }
2491
2492 openModal(params.animation, params.onOpen);
2493
2494 // Focus the first element (input or button)
2495 if (params.allowEnterKey) {
2496 setFocus(-1, 1);
2497 } else {
2498 if (document.activeElement) {
2499 document.activeElement.blur();
2500 }
2501 }
2502
2503 // fix scroll
2504 getContainer().scrollTop = 0;
2505
2506 // Observe changes inside the modal and adjust height
2507 if (typeof MutationObserver !== 'undefined' && !swal2Observer) {
2508 swal2Observer = new MutationObserver(sweetAlert.recalculateHeight);
2509 swal2Observer.observe(modal, { childList: true, characterData: true, subtree: true });
2510 }
2511 });
2512 };
2513
2514 /*
2515 * Global function to determine if swal2 modal is shown
2516 */
2517 sweetAlert.isVisible = function () {
2518 return !!getModal();
2519 };
2520
2521 /*
2522 * Global function for chaining sweetAlert modals
2523 */
2524 sweetAlert.queue = function (steps) {
2525 queue = steps;
2526 var resetQueue = function resetQueue() {
2527 queue = [];
2528 document.body.removeAttribute('data-swal2-queue-step');
2529 };
2530 var queueResult = [];
2531 return new Promise(function (resolve, reject) {
2532 (function step(i, callback) {
2533 if (i < queue.length) {
2534 document.body.setAttribute('data-swal2-queue-step', i);
2535
2536 sweetAlert(queue[i]).then(function (result) {
2537 queueResult.push(result);
2538 step(i + 1, callback);
2539 }, function (dismiss) {
2540 resetQueue();
2541 reject(dismiss);
2542 });
2543 } else {
2544 resetQueue();
2545 resolve(queueResult);
2546 }
2547 })(0);
2548 });
2549 };
2550
2551 /*
2552 * Global function for getting the index of current modal in queue
2553 */
2554 sweetAlert.getQueueStep = function () {
2555 return document.body.getAttribute('data-swal2-queue-step');
2556 };
2557
2558 /*
2559 * Global function for inserting a modal to the queue
2560 */
2561 sweetAlert.insertQueueStep = function (step, index) {
2562 if (index && index < queue.length) {
2563 return queue.splice(index, 0, step);
2564 }
2565 return queue.push(step);
2566 };
2567
2568 /*
2569 * Global function for deleting a modal from the queue
2570 */
2571 sweetAlert.deleteQueueStep = function (index) {
2572 if (typeof queue[index] !== 'undefined') {
2573 queue.splice(index, 1);
2574 }
2575 };
2576
2577 /*
2578 * Global function to close sweetAlert
2579 */
2580 sweetAlert.close = sweetAlert.closeModal = function (onComplete) {
2581 var container = getContainer();
2582 var modal = getModal();
2583 if (!modal) {
2584 return;
2585 }
2586 removeClass(modal, swalClasses.show);
2587 addClass(modal, swalClasses.hide);
2588 clearTimeout(modal.timeout);
2589
2590 resetPrevState();
2591
2592 var removeModalAndResetState = function removeModalAndResetState() {
2593 if (container.parentNode) {
2594 container.parentNode.removeChild(container);
2595 }
2596 removeClass(document.documentElement, swalClasses.shown);
2597 removeClass(document.body, swalClasses.shown);
2598 undoScrollbar();
2599 undoIOSfix();
2600 };
2601
2602 // If animation is supported, animate
2603 if (animationEndEvent && !hasClass(modal, swalClasses.noanimation)) {
2604 modal.addEventListener(animationEndEvent, function swalCloseEventFinished() {
2605 modal.removeEventListener(animationEndEvent, swalCloseEventFinished);
2606 if (hasClass(modal, swalClasses.hide)) {
2607 removeModalAndResetState();
2608 }
2609 });
2610 } else {
2611 // Otherwise, remove immediately
2612 removeModalAndResetState();
2613 }
2614 if (onComplete !== null && typeof onComplete === 'function') {
2615 setTimeout(function () {
2616 onComplete(modal);
2617 });
2618 }
2619 };
2620
2621 /*
2622 * Global function to click 'Confirm' button
2623 */
2624 sweetAlert.clickConfirm = function () {
2625 return getConfirmButton().click();
2626 };
2627
2628 /*
2629 * Global function to click 'Cancel' button
2630 */
2631 sweetAlert.clickCancel = function () {
2632 return getCancelButton().click();
2633 };
2634
2635 /**
2636 * Show spinner instead of Confirm button and disable Cancel button
2637 */
2638 sweetAlert.showLoading = sweetAlert.enableLoading = function () {
2639 var modal = getModal();
2640 if (!modal) {
2641 sweetAlert('');
2642 }
2643 var buttonsWrapper = getButtonsWrapper();
2644 var confirmButton = getConfirmButton();
2645 var cancelButton = getCancelButton();
2646
2647 show(buttonsWrapper);
2648 show(confirmButton, 'inline-block');
2649 addClass(buttonsWrapper, swalClasses.loading);
2650 addClass(modal, swalClasses.loading);
2651 confirmButton.disabled = true;
2652 cancelButton.disabled = true;
2653 };
2654
2655 /**
2656 * Set default params for each popup
2657 * @param {Object} userParams
2658 */
2659 sweetAlert.setDefaults = function (userParams) {
2660 if (!userParams || (typeof userParams === 'undefined' ? 'undefined' : _typeof(userParams)) !== 'object') {
2661 return console.error('SweetAlert2: the argument for setDefaults() is required and has to be a object');
2662 }
2663
2664 for (var param in userParams) {
2665 if (!defaultParams.hasOwnProperty(param) && param !== 'extraParams') {
2666 console.warn('SweetAlert2: Unknown parameter "' + param + '"');
2667 delete userParams[param];
2668 }
2669 }
2670
2671 _extends(modalParams, userParams);
2672 };
2673
2674 /**
2675 * Reset default params for each popup
2676 */
2677 sweetAlert.resetDefaults = function () {
2678 modalParams = _extends({}, defaultParams);
2679 };
2680
2681 sweetAlert.noop = function () {};
2682
2683 sweetAlert.version = '6.6.4';
2684
2685 sweetAlert.default = sweetAlert;
2686
2687 return sweetAlert;
2688
2689 })));
2690 if (window.Sweetalert2) window.sweetAlert = window.swal = window.Sweetalert2;
2691
2692 /* assets/wpuf/js/jquery-ui-timepicker-addon.js */
2693 /*
2694 * jQuery timepicker addon
2695 * By: Trent Richardson [http://trentrichardson.com]
2696 * Version 1.2
2697 * Last Modified: 02/02/2013
2698 *
2699 * Copyright 2013 Trent Richardson
2700 * You may use this project under MIT or GPL licenses.
2701 * http://trentrichardson.com/Impromptu/GPL-LICENSE.txt
2702 * http://trentrichardson.com/Impromptu/MIT-LICENSE.txt
2703 */
2704
2705 /*jslint evil: true, white: false, undef: false, nomen: false */
2706
2707 (function($) {
2708
2709 /*
2710 * Lets not redefine timepicker, Prevent "Uncaught RangeError: Maximum call stack size exceeded"
2711 */
2712 $.ui.timepicker = $.ui.timepicker || {};
2713 if ($.ui.timepicker.version) {
2714 return;
2715 }
2716
2717 /*
2718 * Extend jQueryUI, get it started with our version number
2719 */
2720 $.extend($.ui, {
2721 timepicker: {
2722 version: "1.2"
2723 }
2724 });
2725
2726 /*
2727 * Timepicker manager.
2728 * Use the singleton instance of this class, $.timepicker, to interact with the time picker.
2729 * Settings for (groups of) time pickers are maintained in an instance object,
2730 * allowing multiple different settings on the same page.
2731 */
2732 var Timepicker = function() {
2733 this.regional = []; // Available regional settings, indexed by language code
2734 this.regional[''] = { // Default regional settings
2735 currentText: 'Now',
2736 closeText: 'Done',
2737 amNames: ['AM', 'A'],
2738 pmNames: ['PM', 'P'],
2739 timeFormat: 'HH:mm',
2740 timeSuffix: '',
2741 timeOnlyTitle: 'Choose Time',
2742 timeText: 'Time',
2743 hourText: 'Hour',
2744 minuteText: 'Minute',
2745 secondText: 'Second',
2746 millisecText: 'Millisecond',
2747 timezoneText: 'Time Zone',
2748 isRTL: false
2749 };
2750 this._defaults = { // Global defaults for all the datetime picker instances
2751 showButtonPanel: true,
2752 timeOnly: false,
2753 showHour: true,
2754 showMinute: true,
2755 showSecond: false,
2756 showMillisec: false,
2757 showTimezone: false,
2758 showTime: true,
2759 stepHour: 1,
2760 stepMinute: 1,
2761 stepSecond: 1,
2762 stepMillisec: 1,
2763 hour: 0,
2764 minute: 0,
2765 second: 0,
2766 millisec: 0,
2767 timezone: null,
2768 useLocalTimezone: false,
2769 defaultTimezone: "+0000",
2770 hourMin: 0,
2771 minuteMin: 0,
2772 secondMin: 0,
2773 millisecMin: 0,
2774 hourMax: 23,
2775 minuteMax: 59,
2776 secondMax: 59,
2777 millisecMax: 999,
2778 minDateTime: null,
2779 maxDateTime: null,
2780 onSelect: null,
2781 hourGrid: 0,
2782 minuteGrid: 0,
2783 secondGrid: 0,
2784 millisecGrid: 0,
2785 alwaysSetTime: true,
2786 separator: ' ',
2787 altFieldTimeOnly: true,
2788 altTimeFormat: null,
2789 altSeparator: null,
2790 altTimeSuffix: null,
2791 pickerTimeFormat: null,
2792 pickerTimeSuffix: null,
2793 showTimepicker: true,
2794 timezoneIso8601: false,
2795 timezoneList: null,
2796 addSliderAccess: false,
2797 sliderAccessArgs: null,
2798 controlType: 'slider',
2799 defaultValue: null,
2800 parse: 'strict'
2801 };
2802 $.extend(this._defaults, this.regional['']);
2803 };
2804
2805 $.extend(Timepicker.prototype, {
2806 $input: null,
2807 $altInput: null,
2808 $timeObj: null,
2809 inst: null,
2810 hour_slider: null,
2811 minute_slider: null,
2812 second_slider: null,
2813 millisec_slider: null,
2814 timezone_select: null,
2815 hour: 0,
2816 minute: 0,
2817 second: 0,
2818 millisec: 0,
2819 timezone: null,
2820 defaultTimezone: "+0000",
2821 hourMinOriginal: null,
2822 minuteMinOriginal: null,
2823 secondMinOriginal: null,
2824 millisecMinOriginal: null,
2825 hourMaxOriginal: null,
2826 minuteMaxOriginal: null,
2827 secondMaxOriginal: null,
2828 millisecMaxOriginal: null,
2829 ampm: '',
2830 formattedDate: '',
2831 formattedTime: '',
2832 formattedDateTime: '',
2833 timezoneList: null,
2834 units: ['hour','minute','second','millisec'],
2835 control: null,
2836
2837 /*
2838 * Override the default settings for all instances of the time picker.
2839 * @param settings object - the new settings to use as defaults (anonymous object)
2840 * @return the manager object
2841 */
2842 setDefaults: function(settings) {
2843 extendRemove(this._defaults, settings || {});
2844 return this;
2845 },
2846
2847 /*
2848 * Create a new Timepicker instance
2849 */
2850 _newInst: function($input, o) {
2851 var tp_inst = new Timepicker(),
2852 inlineSettings = {},
2853 fns = {},
2854 overrides, i;
2855
2856 for (var attrName in this._defaults) {
2857 if(this._defaults.hasOwnProperty(attrName)){
2858 var attrValue = $input.attr('time:' + attrName);
2859 if (attrValue) {
2860 try {
2861 inlineSettings[attrName] = eval(attrValue);
2862 } catch (err) {
2863 inlineSettings[attrName] = attrValue;
2864 }
2865 }
2866 }
2867 }
2868 overrides = {
2869 beforeShow: function (input, dp_inst) {
2870 if ($.isFunction(tp_inst._defaults.evnts.beforeShow)) {
2871 return tp_inst._defaults.evnts.beforeShow.call($input[0], input, dp_inst, tp_inst);
2872 }
2873 },
2874 onChangeMonthYear: function (year, month, dp_inst) {
2875 // Update the time as well : this prevents the time from disappearing from the $input field.
2876 tp_inst._updateDateTime(dp_inst);
2877 if ($.isFunction(tp_inst._defaults.evnts.onChangeMonthYear)) {
2878 tp_inst._defaults.evnts.onChangeMonthYear.call($input[0], year, month, dp_inst, tp_inst);
2879 }
2880 },
2881 onClose: function (dateText, dp_inst) {
2882 if (tp_inst.timeDefined === true && $input.val() !== '') {
2883 tp_inst._updateDateTime(dp_inst);
2884 }
2885 if ($.isFunction(tp_inst._defaults.evnts.onClose)) {
2886 tp_inst._defaults.evnts.onClose.call($input[0], dateText, dp_inst, tp_inst);
2887 }
2888 }
2889 };
2890 for (i in overrides) {
2891 if (overrides.hasOwnProperty(i)) {
2892 fns[i] = o[i] || null;
2893 }
2894 }
2895 tp_inst._defaults = $.extend({}, this._defaults, inlineSettings, o, overrides, {
2896 evnts:fns,
2897 timepicker: tp_inst // add timepicker as a property of datepicker: $.datepicker._get(dp_inst, 'timepicker');
2898 });
2899 tp_inst.amNames = $.map(tp_inst._defaults.amNames, function(val) {
2900 return val.toUpperCase();
2901 });
2902 tp_inst.pmNames = $.map(tp_inst._defaults.pmNames, function(val) {
2903 return val.toUpperCase();
2904 });
2905
2906 // controlType is string - key to our this._controls
2907 if(typeof(tp_inst._defaults.controlType) === 'string'){
2908 if($.fn[tp_inst._defaults.controlType] === undefined){
2909 tp_inst._defaults.controlType = 'select';
2910 }
2911 tp_inst.control = tp_inst._controls[tp_inst._defaults.controlType];
2912 }
2913 // controlType is an object and must implement create, options, value methods
2914 else{
2915 tp_inst.control = tp_inst._defaults.controlType;
2916 }
2917
2918 if (tp_inst._defaults.timezoneList === null) {
2919 var timezoneList = ['-1200', '-1100', '-1000', '-0930', '-0900', '-0800', '-0700', '-0600', '-0500', '-0430', '-0400', '-0330', '-0300', '-0200', '-0100', '+0000',
2920 '+0100', '+0200', '+0300', '+0330', '+0400', '+0430', '+0500', '+0530', '+0545', '+0600', '+0630', '+0700', '+0800', '+0845', '+0900', '+0930',
2921 '+1000', '+1030', '+1100', '+1130', '+1200', '+1245', '+1300', '+1400'];
2922
2923 if (tp_inst._defaults.timezoneIso8601) {
2924 timezoneList = $.map(timezoneList, function(val) {
2925 return val == '+0000' ? 'Z' : (val.substring(0, 3) + ':' + val.substring(3));
2926 });
2927 }
2928 tp_inst._defaults.timezoneList = timezoneList;
2929 }
2930
2931 tp_inst.timezone = tp_inst._defaults.timezone;
2932 tp_inst.hour = tp_inst._defaults.hour < tp_inst._defaults.hourMin? tp_inst._defaults.hourMin :
2933 tp_inst._defaults.hour > tp_inst._defaults.hourMax? tp_inst._defaults.hourMax : tp_inst._defaults.hour;
2934 tp_inst.minute = tp_inst._defaults.minute < tp_inst._defaults.minuteMin? tp_inst._defaults.minuteMin :
2935 tp_inst._defaults.minute > tp_inst._defaults.minuteMax? tp_inst._defaults.minuteMax : tp_inst._defaults.minute;
2936 tp_inst.second = tp_inst._defaults.second < tp_inst._defaults.secondMin? tp_inst._defaults.secondMin :
2937 tp_inst._defaults.second > tp_inst._defaults.secondMax? tp_inst._defaults.secondMax : tp_inst._defaults.second;
2938 tp_inst.millisec = tp_inst._defaults.millisec < tp_inst._defaults.millisecMin? tp_inst._defaults.millisecMin :
2939 tp_inst._defaults.millisec > tp_inst._defaults.millisecMax? tp_inst._defaults.millisecMax : tp_inst._defaults.millisec;
2940 tp_inst.ampm = '';
2941 tp_inst.$input = $input;
2942
2943 if (o.altField) {
2944 tp_inst.$altInput = $(o.altField).css({
2945 cursor: 'pointer'
2946 }).focus(function() {
2947 $input.trigger("focus");
2948 });
2949 }
2950
2951 if (tp_inst._defaults.minDate === 0 || tp_inst._defaults.minDateTime === 0) {
2952 tp_inst._defaults.minDate = new Date();
2953 }
2954 if (tp_inst._defaults.maxDate === 0 || tp_inst._defaults.maxDateTime === 0) {
2955 tp_inst._defaults.maxDate = new Date();
2956 }
2957
2958 // datepicker needs minDate/maxDate, timepicker needs minDateTime/maxDateTime..
2959 if (tp_inst._defaults.minDate !== undefined && tp_inst._defaults.minDate instanceof Date) {
2960 tp_inst._defaults.minDateTime = new Date(tp_inst._defaults.minDate.getTime());
2961 }
2962 if (tp_inst._defaults.minDateTime !== undefined && tp_inst._defaults.minDateTime instanceof Date) {
2963 tp_inst._defaults.minDate = new Date(tp_inst._defaults.minDateTime.getTime());
2964 }
2965 if (tp_inst._defaults.maxDate !== undefined && tp_inst._defaults.maxDate instanceof Date) {
2966 tp_inst._defaults.maxDateTime = new Date(tp_inst._defaults.maxDate.getTime());
2967 }
2968 if (tp_inst._defaults.maxDateTime !== undefined && tp_inst._defaults.maxDateTime instanceof Date) {
2969 tp_inst._defaults.maxDate = new Date(tp_inst._defaults.maxDateTime.getTime());
2970 }
2971 tp_inst.$input.bind('focus', function() {
2972 tp_inst._onFocus();
2973 });
2974
2975 return tp_inst;
2976 },
2977
2978 /*
2979 * add our sliders to the calendar
2980 */
2981 _addTimePicker: function(dp_inst) {
2982 var currDT = (this.$altInput && this._defaults.altFieldTimeOnly) ? this.$input.val() + ' ' + this.$altInput.val() : this.$input.val();
2983
2984 this.timeDefined = this._parseTime(currDT);
2985 this._limitMinMaxDateTime(dp_inst, false);
2986 this._injectTimePicker();
2987 },
2988
2989 /*
2990 * parse the time string from input value or _setTime
2991 */
2992 _parseTime: function(timeString, withDate) {
2993 if (!this.inst) {
2994 this.inst = $.datepicker._getInst(this.$input[0]);
2995 }
2996
2997 if (withDate || !this._defaults.timeOnly) {
2998 var dp_dateFormat = $.datepicker._get(this.inst, 'dateFormat');
2999 try {
3000 var parseRes = parseDateTimeInternal(dp_dateFormat, this._defaults.timeFormat, timeString, $.datepicker._getFormatConfig(this.inst), this._defaults);
3001 if (!parseRes.timeObj) {
3002 return false;
3003 }
3004 $.extend(this, parseRes.timeObj);
3005 } catch (err) {
3006 $.timepicker.log("Error parsing the date/time string: " + err +
3007 "\ndate/time string = " + timeString +
3008 "\ntimeFormat = " + this._defaults.timeFormat +
3009 "\ndateFormat = " + dp_dateFormat);
3010 return false;
3011 }
3012 return true;
3013 } else {
3014 var timeObj = $.datepicker.parseTime(this._defaults.timeFormat, timeString, this._defaults);
3015 if (!timeObj) {
3016 return false;
3017 }
3018 $.extend(this, timeObj);
3019 return true;
3020 }
3021 },
3022
3023 /*
3024 * generate and inject html for timepicker into ui datepicker
3025 */
3026 _injectTimePicker: function() {
3027 var $dp = this.inst.dpDiv,
3028 o = this.inst.settings,
3029 tp_inst = this,
3030 litem = '',
3031 uitem = '',
3032 max = {},
3033 gridSize = {},
3034 size = null;
3035
3036 // Prevent displaying twice
3037 if ($dp.find("div.ui-timepicker-div").length === 0 && o.showTimepicker) {
3038 var noDisplay = ' style="display:none;"',
3039 html = '<div class="ui-timepicker-div'+ (o.isRTL? ' ui-timepicker-rtl' : '') +'"><dl>' + '<dt class="ui_tpicker_time_label"' + ((o.showTime) ? '' : noDisplay) + '>' + o.timeText + '</dt>' +
3040 '<dd class="ui_tpicker_time"' + ((o.showTime) ? '' : noDisplay) + '></dd>';
3041
3042 // Create the markup
3043 for(var i=0,l=this.units.length; i<l; i++){
3044 litem = this.units[i];
3045 uitem = litem.substr(0,1).toUpperCase() + litem.substr(1);
3046 // Added by Peter Medeiros:
3047 // - Figure out what the hour/minute/second max should be based on the step values.
3048 // - Example: if stepMinute is 15, then minMax is 45.
3049 max[litem] = parseInt((o[litem+'Max'] - ((o[litem+'Max'] - o[litem+'Min']) % o['step'+uitem])), 10);
3050 gridSize[litem] = 0;
3051
3052 html += '<dt class="ui_tpicker_'+ litem +'_label"' + ((o['show'+uitem]) ? '' : noDisplay) + '>' + o[litem +'Text'] + '</dt>' +
3053 '<dd class="ui_tpicker_'+ litem +'"><div class="ui_tpicker_'+ litem +'_slider"' + ((o['show'+uitem]) ? '' : noDisplay) + '></div>';
3054
3055 if (o['show'+uitem] && o[litem+'Grid'] > 0) {
3056 html += '<div style="padding-left: 1px"><table class="ui-tpicker-grid-label"><tr>';
3057
3058 if(litem == 'hour'){
3059 for (var h = o[litem+'Min']; h <= max[litem]; h += parseInt(o[litem+'Grid'], 10)) {
3060 gridSize[litem]++;
3061 var tmph = $.datepicker.formatTime(useAmpm(o.pickerTimeFormat || o.timeFormat)? 'hht':'HH', {hour:h}, o);
3062 html += '<td data-for="'+litem+'">' + tmph + '</td>';
3063 }
3064 }
3065 else{
3066 for (var m = o[litem+'Min']; m <= max[litem]; m += parseInt(o[litem+'Grid'], 10)) {
3067 gridSize[litem]++;
3068 html += '<td data-for="'+litem+'">' + ((m < 10) ? '0' : '') + m + '</td>';
3069 }
3070 }
3071
3072 html += '</tr></table></div>';
3073 }
3074 html += '</dd>';
3075 }
3076
3077 // Timezone
3078 html += '<dt class="ui_tpicker_timezone_label"' + ((o.showTimezone) ? '' : noDisplay) + '>' + o.timezoneText + '</dt>';
3079 html += '<dd class="ui_tpicker_timezone" ' + ((o.showTimezone) ? '' : noDisplay) + '></dd>';
3080
3081 // Create the elements from string
3082 html += '</dl></div>';
3083 var $tp = $(html);
3084
3085 // if we only want time picker...
3086 if (o.timeOnly === true) {
3087 $tp.prepend('<div class="ui-widget-header ui-helper-clearfix ui-corner-all">' + '<div class="ui-datepicker-title">' + o.timeOnlyTitle + '</div>' + '</div>');
3088 $dp.find('.ui-datepicker-header, .ui-datepicker-calendar').hide();
3089 }
3090
3091 // add sliders, adjust grids, add events
3092 for(var i=0,l=tp_inst.units.length; i<l; i++){
3093 litem = tp_inst.units[i];
3094 uitem = litem.substr(0,1).toUpperCase() + litem.substr(1);
3095
3096 // add the slider
3097 tp_inst[litem+'_slider'] = tp_inst.control.create(tp_inst, $tp.find('.ui_tpicker_'+litem+'_slider'), litem, tp_inst[litem], o[litem+'Min'], max[litem], o['step'+uitem]);
3098
3099 // adjust the grid and add click event
3100 if (o['show'+uitem] && o[litem+'Grid'] > 0) {
3101 size = 100 * gridSize[litem] * o[litem+'Grid'] / (max[litem] - o[litem+'Min']);
3102 $tp.find('.ui_tpicker_'+litem+' table').css({
3103 width: size + "%",
3104 marginLeft: o.isRTL? '0' : ((size / (-2 * gridSize[litem])) + "%"),
3105 marginRight: o.isRTL? ((size / (-2 * gridSize[litem])) + "%") : '0',
3106 borderCollapse: 'collapse'
3107 }).find("td").click(function(e){
3108 var $t = $(this),
3109 h = $t.html(),
3110 n = parseInt(h.replace(/[^0-9]/g),10),
3111 ap = h.replace(/[^apm]/ig),
3112 f = $t.data('for'); // loses scope, so we use data-for
3113
3114 if(f == 'hour'){
3115 if(ap.indexOf('p') !== -1 && n < 12){
3116 n += 12;
3117 }
3118 else{
3119 if(ap.indexOf('a') !== -1 && n === 12){
3120 n = 0;
3121 }
3122 }
3123 }
3124
3125 tp_inst.control.value(tp_inst, tp_inst[f+'_slider'], litem, n);
3126
3127 tp_inst._onTimeChange();
3128 tp_inst._onSelectHandler();
3129 })
3130 .css({
3131 cursor: 'pointer',
3132 width: (100 / gridSize[litem]) + '%',
3133 textAlign: 'center',
3134 overflow: 'hidden'
3135 });
3136 } // end if grid > 0
3137 } // end for loop
3138
3139 // Add timezone options
3140 this.timezone_select = $tp.find('.ui_tpicker_timezone').append('<select></select>').find("select");
3141 $.fn.append.apply(this.timezone_select,
3142 $.map(o.timezoneList, function(val, idx) {
3143 return $("<option />").val(typeof val == "object" ? val.value : val).text(typeof val == "object" ? val.label : val);
3144 }));
3145 if (typeof(this.timezone) != "undefined" && this.timezone !== null && this.timezone !== "") {
3146 var local_date = new Date(this.inst.selectedYear, this.inst.selectedMonth, this.inst.selectedDay, 12);
3147 var local_timezone = $.timepicker.timeZoneOffsetString(local_date);
3148 if (local_timezone == this.timezone) {
3149 selectLocalTimeZone(tp_inst);
3150 } else {
3151 this.timezone_select.val(this.timezone);
3152 }
3153 } else {
3154 if (typeof(this.hour) != "undefined" && this.hour !== null && this.hour !== "") {
3155 this.timezone_select.val(o.defaultTimezone);
3156 } else {
3157 selectLocalTimeZone(tp_inst);
3158 }
3159 }
3160 this.timezone_select.change(function() {
3161 tp_inst._defaults.useLocalTimezone = false;
3162 tp_inst._onTimeChange();
3163 tp_inst._onSelectHandler();
3164 });
3165 // End timezone options
3166
3167 // inject timepicker into datepicker
3168 var $buttonPanel = $dp.find('.ui-datepicker-buttonpane');
3169 if ($buttonPanel.length) {
3170 $buttonPanel.before($tp);
3171 } else {
3172 $dp.append($tp);
3173 }
3174
3175 this.$timeObj = $tp.find('.ui_tpicker_time');
3176
3177 if (this.inst !== null) {
3178 var timeDefined = this.timeDefined;
3179 this._onTimeChange();
3180 this.timeDefined = timeDefined;
3181 }
3182
3183 // slideAccess integration: http://trentrichardson.com/2011/11/11/jquery-ui-sliders-and-touch-accessibility/
3184 if (this._defaults.addSliderAccess) {
3185 var sliderAccessArgs = this._defaults.sliderAccessArgs,
3186 rtl = this._defaults.isRTL;
3187 sliderAccessArgs.isRTL = rtl;
3188
3189 setTimeout(function() { // fix for inline mode
3190 if ($tp.find('.ui-slider-access').length === 0) {
3191 $tp.find('.ui-slider:visible').sliderAccess(sliderAccessArgs);
3192
3193 // fix any grids since sliders are shorter
3194 var sliderAccessWidth = $tp.find('.ui-slider-access:eq(0)').outerWidth(true);
3195 if (sliderAccessWidth) {
3196 $tp.find('table:visible').each(function() {
3197 var $g = $(this),
3198 oldWidth = $g.outerWidth(),
3199 oldMarginLeft = $g.css(rtl? 'marginRight':'marginLeft').toString().replace('%', ''),
3200 newWidth = oldWidth - sliderAccessWidth,
3201 newMarginLeft = ((oldMarginLeft * newWidth) / oldWidth) + '%',
3202 css = { width: newWidth, marginRight: 0, marginLeft: 0 };
3203 css[rtl? 'marginRight':'marginLeft'] = newMarginLeft;
3204 $g.css(css);
3205 });
3206 }
3207 }
3208 }, 10);
3209 }
3210 // end slideAccess integration
3211
3212 }
3213 },
3214
3215 /*
3216 * This function tries to limit the ability to go outside the
3217 * min/max date range
3218 */
3219 _limitMinMaxDateTime: function(dp_inst, adjustSliders) {
3220 var o = this._defaults,
3221 dp_date = new Date(dp_inst.selectedYear, dp_inst.selectedMonth, dp_inst.selectedDay);
3222
3223 if (!this._defaults.showTimepicker) {
3224 return;
3225 } // No time so nothing to check here
3226
3227 if ($.datepicker._get(dp_inst, 'minDateTime') !== null && $.datepicker._get(dp_inst, 'minDateTime') !== undefined && dp_date) {
3228 var minDateTime = $.datepicker._get(dp_inst, 'minDateTime'),
3229 minDateTimeDate = new Date(minDateTime.getFullYear(), minDateTime.getMonth(), minDateTime.getDate(), 0, 0, 0, 0);
3230
3231 if (this.hourMinOriginal === null || this.minuteMinOriginal === null || this.secondMinOriginal === null || this.millisecMinOriginal === null) {
3232 this.hourMinOriginal = o.hourMin;
3233 this.minuteMinOriginal = o.minuteMin;
3234 this.secondMinOriginal = o.secondMin;
3235 this.millisecMinOriginal = o.millisecMin;
3236 }
3237
3238 if (dp_inst.settings.timeOnly || minDateTimeDate.getTime() == dp_date.getTime()) {
3239 this._defaults.hourMin = minDateTime.getHours();
3240 if (this.hour <= this._defaults.hourMin) {
3241 this.hour = this._defaults.hourMin;
3242 this._defaults.minuteMin = minDateTime.getMinutes();
3243 if (this.minute <= this._defaults.minuteMin) {
3244 this.minute = this._defaults.minuteMin;
3245 this._defaults.secondMin = minDateTime.getSeconds();
3246 if (this.second <= this._defaults.secondMin) {
3247 this.second = this._defaults.secondMin;
3248 this._defaults.millisecMin = minDateTime.getMilliseconds();
3249 } else {
3250 if (this.millisec < this._defaults.millisecMin) {
3251 this.millisec = this._defaults.millisecMin;
3252 }
3253 this._defaults.millisecMin = this.millisecMinOriginal;
3254 }
3255 } else {
3256 this._defaults.secondMin = this.secondMinOriginal;
3257 this._defaults.millisecMin = this.millisecMinOriginal;
3258 }
3259 } else {
3260 this._defaults.minuteMin = this.minuteMinOriginal;
3261 this._defaults.secondMin = this.secondMinOriginal;
3262 this._defaults.millisecMin = this.millisecMinOriginal;
3263 }
3264 } else {
3265 this._defaults.hourMin = this.hourMinOriginal;
3266 this._defaults.minuteMin = this.minuteMinOriginal;
3267 this._defaults.secondMin = this.secondMinOriginal;
3268 this._defaults.millisecMin = this.millisecMinOriginal;
3269 }
3270 }
3271
3272 if ($.datepicker._get(dp_inst, 'maxDateTime') !== null && $.datepicker._get(dp_inst, 'maxDateTime') !== undefined && dp_date) {
3273 var maxDateTime = $.datepicker._get(dp_inst, 'maxDateTime'),
3274 maxDateTimeDate = new Date(maxDateTime.getFullYear(), maxDateTime.getMonth(), maxDateTime.getDate(), 0, 0, 0, 0);
3275
3276 if (this.hourMaxOriginal === null || this.minuteMaxOriginal === null || this.secondMaxOriginal === null) {
3277 this.hourMaxOriginal = o.hourMax;
3278 this.minuteMaxOriginal = o.minuteMax;
3279 this.secondMaxOriginal = o.secondMax;
3280 this.millisecMaxOriginal = o.millisecMax;
3281 }
3282
3283 if (dp_inst.settings.timeOnly || maxDateTimeDate.getTime() == dp_date.getTime()) {
3284 this._defaults.hourMax = maxDateTime.getHours();
3285 if (this.hour >= this._defaults.hourMax) {
3286 this.hour = this._defaults.hourMax;
3287 this._defaults.minuteMax = maxDateTime.getMinutes();
3288 if (this.minute >= this._defaults.minuteMax) {
3289 this.minute = this._defaults.minuteMax;
3290 this._defaults.secondMax = maxDateTime.getSeconds();
3291 if (this.second >= this._defaults.secondMax) {
3292 this.second = this._defaults.secondMax;
3293 this._defaults.millisecMax = maxDateTime.getMilliseconds();
3294 } else {
3295 if (this.millisec > this._defaults.millisecMax) {
3296 this.millisec = this._defaults.millisecMax;
3297 }
3298 this._defaults.millisecMax = this.millisecMaxOriginal;
3299 }
3300 } else {
3301 this._defaults.secondMax = this.secondMaxOriginal;
3302 this._defaults.millisecMax = this.millisecMaxOriginal;
3303 }
3304 } else {
3305 this._defaults.minuteMax = this.minuteMaxOriginal;
3306 this._defaults.secondMax = this.secondMaxOriginal;
3307 this._defaults.millisecMax = this.millisecMaxOriginal;
3308 }
3309 } else {
3310 this._defaults.hourMax = this.hourMaxOriginal;
3311 this._defaults.minuteMax = this.minuteMaxOriginal;
3312 this._defaults.secondMax = this.secondMaxOriginal;
3313 this._defaults.millisecMax = this.millisecMaxOriginal;
3314 }
3315 }
3316
3317 if (adjustSliders !== undefined && adjustSliders === true) {
3318 var hourMax = parseInt((this._defaults.hourMax - ((this._defaults.hourMax - this._defaults.hourMin) % this._defaults.stepHour)), 10),
3319 minMax = parseInt((this._defaults.minuteMax - ((this._defaults.minuteMax - this._defaults.minuteMin) % this._defaults.stepMinute)), 10),
3320 secMax = parseInt((this._defaults.secondMax - ((this._defaults.secondMax - this._defaults.secondMin) % this._defaults.stepSecond)), 10),
3321 millisecMax = parseInt((this._defaults.millisecMax - ((this._defaults.millisecMax - this._defaults.millisecMin) % this._defaults.stepMillisec)), 10);
3322
3323 if (this.hour_slider) {
3324 this.control.options(this, this.hour_slider, 'hour', { min: this._defaults.hourMin, max: hourMax });
3325 this.control.value(this, this.hour_slider, 'hour', this.hour - (this.hour % this._defaults.stepHour));
3326 }
3327 if (this.minute_slider) {
3328 this.control.options(this, this.minute_slider, 'minute', { min: this._defaults.minuteMin, max: minMax });
3329 this.control.value(this, this.minute_slider, 'minute', this.minute - (this.minute % this._defaults.stepMinute));
3330 }
3331 if (this.second_slider) {
3332 this.control.options(this, this.second_slider, 'second', { min: this._defaults.secondMin, max: secMax });
3333 this.control.value(this, this.second_slider, 'second', this.second - (this.second % this._defaults.stepSecond));
3334 }
3335 if (this.millisec_slider) {
3336 this.control.options(this, this.millisec_slider, 'millisec', { min: this._defaults.millisecMin, max: millisecMax });
3337 this.control.value(this, this.millisec_slider, 'millisec', this.millisec - (this.millisec % this._defaults.stepMillisec));
3338 }
3339 }
3340
3341 },
3342
3343 /*
3344 * when a slider moves, set the internal time...
3345 * on time change is also called when the time is updated in the text field
3346 */
3347 _onTimeChange: function() {
3348 var hour = (this.hour_slider) ? this.control.value(this, this.hour_slider, 'hour') : false,
3349 minute = (this.minute_slider) ? this.control.value(this, this.minute_slider, 'minute') : false,
3350 second = (this.second_slider) ? this.control.value(this, this.second_slider, 'second') : false,
3351 millisec = (this.millisec_slider) ? this.control.value(this, this.millisec_slider, 'millisec') : false,
3352 timezone = (this.timezone_select) ? this.timezone_select.val() : false,
3353 o = this._defaults,
3354 pickerTimeFormat = o.pickerTimeFormat || o.timeFormat,
3355 pickerTimeSuffix = o.pickerTimeSuffix || o.timeSuffix;
3356
3357 if (typeof(hour) == 'object') {
3358 hour = false;
3359 }
3360 if (typeof(minute) == 'object') {
3361 minute = false;
3362 }
3363 if (typeof(second) == 'object') {
3364 second = false;
3365 }
3366 if (typeof(millisec) == 'object') {
3367 millisec = false;
3368 }
3369 if (typeof(timezone) == 'object') {
3370 timezone = false;
3371 }
3372
3373 if (hour !== false) {
3374 hour = parseInt(hour, 10);
3375 }
3376 if (minute !== false) {
3377 minute = parseInt(minute, 10);
3378 }
3379 if (second !== false) {
3380 second = parseInt(second, 10);
3381 }
3382 if (millisec !== false) {
3383 millisec = parseInt(millisec, 10);
3384 }
3385
3386 var ampm = o[hour < 12 ? 'amNames' : 'pmNames'][0];
3387
3388 // If the update was done in the input field, the input field should not be updated.
3389 // If the update was done using the sliders, update the input field.
3390 var hasChanged = (hour != this.hour || minute != this.minute || second != this.second || millisec != this.millisec
3391 || (this.ampm.length > 0 && (hour < 12) != ($.inArray(this.ampm.toUpperCase(), this.amNames) !== -1))
3392 || ((this.timezone === null && timezone != this.defaultTimezone) || (this.timezone !== null && timezone != this.timezone)));
3393
3394 if (hasChanged) {
3395
3396 if (hour !== false) {
3397 this.hour = hour;
3398 }
3399 if (minute !== false) {
3400 this.minute = minute;
3401 }
3402 if (second !== false) {
3403 this.second = second;
3404 }
3405 if (millisec !== false) {
3406 this.millisec = millisec;
3407 }
3408 if (timezone !== false) {
3409 this.timezone = timezone;
3410 }
3411
3412 if (!this.inst) {
3413 this.inst = $.datepicker._getInst(this.$input[0]);
3414 }
3415
3416 this._limitMinMaxDateTime(this.inst, true);
3417 }
3418 if (useAmpm(o.timeFormat)) {
3419 this.ampm = ampm;
3420 }
3421
3422 // Updates the time within the timepicker
3423 this.formattedTime = $.datepicker.formatTime(o.timeFormat, this, o);
3424 if (this.$timeObj) {
3425 if(pickerTimeFormat === o.timeFormat){
3426 this.$timeObj.text(this.formattedTime + pickerTimeSuffix);
3427 }
3428 else{
3429 this.$timeObj.text($.datepicker.formatTime(pickerTimeFormat, this, o) + pickerTimeSuffix);
3430 }
3431 }
3432
3433 this.timeDefined = true;
3434 if (hasChanged) {
3435 this._updateDateTime();
3436 }
3437 },
3438
3439 /*
3440 * call custom onSelect.
3441 * bind to sliders slidestop, and grid click.
3442 */
3443 _onSelectHandler: function() {
3444 var onSelect = this._defaults.onSelect || this.inst.settings.onSelect;
3445 var inputEl = this.$input ? this.$input[0] : null;
3446 if (onSelect && inputEl) {
3447 onSelect.apply(inputEl, [this.formattedDateTime, this]);
3448 }
3449 },
3450
3451 /*
3452 * update our input with the new date time..
3453 */
3454 _updateDateTime: function(dp_inst) {
3455 dp_inst = this.inst || dp_inst;
3456 var dt = $.datepicker._daylightSavingAdjust(new Date(dp_inst.selectedYear, dp_inst.selectedMonth, dp_inst.selectedDay)),
3457 dateFmt = $.datepicker._get(dp_inst, 'dateFormat'),
3458 formatCfg = $.datepicker._getFormatConfig(dp_inst),
3459 timeAvailable = dt !== null && this.timeDefined;
3460 this.formattedDate = $.datepicker.formatDate(dateFmt, (dt === null ? new Date() : dt), formatCfg);
3461 var formattedDateTime = this.formattedDate;
3462
3463 // if a slider was changed but datepicker doesn't have a value yet, set it
3464 if(dp_inst.lastVal==""){
3465 dp_inst.currentYear=dp_inst.selectedYear;
3466 dp_inst.currentMonth=dp_inst.selectedMonth;
3467 dp_inst.currentDay=dp_inst.selectedDay;
3468 }
3469
3470 /*
3471 * remove following lines to force every changes in date picker to change the input value
3472 * Bug descriptions: when an input field has a default value, and click on the field to pop up the date picker.
3473 * If the user manually empty the value in the input field, the date picker will never change selected value.
3474 */
3475 //if (dp_inst.lastVal !== undefined && (dp_inst.lastVal.length > 0 && this.$input.val().length === 0)) {
3476 // return;
3477 //}
3478
3479 if (this._defaults.timeOnly === true) {
3480 formattedDateTime = this.formattedTime;
3481 } else if (this._defaults.timeOnly !== true && (this._defaults.alwaysSetTime || timeAvailable)) {
3482 formattedDateTime += this._defaults.separator + this.formattedTime + this._defaults.timeSuffix;
3483 }
3484
3485 this.formattedDateTime = formattedDateTime;
3486
3487 if (!this._defaults.showTimepicker) {
3488 this.$input.val(this.formattedDate);
3489 } else if (this.$altInput && this._defaults.altFieldTimeOnly === true) {
3490 this.$altInput.val(this.formattedTime);
3491 this.$input.val(this.formattedDate);
3492 } else if (this.$altInput) {
3493 this.$input.val(formattedDateTime);
3494 var altFormattedDateTime = '',
3495 altSeparator = this._defaults.altSeparator ? this._defaults.altSeparator : this._defaults.separator,
3496 altTimeSuffix = this._defaults.altTimeSuffix ? this._defaults.altTimeSuffix : this._defaults.timeSuffix;
3497
3498 if (this._defaults.altFormat) altFormattedDateTime = $.datepicker.formatDate(this._defaults.altFormat, (dt === null ? new Date() : dt), formatCfg);
3499 else altFormattedDateTime = this.formattedDate;
3500 if (altFormattedDateTime) altFormattedDateTime += altSeparator;
3501 if (this._defaults.altTimeFormat) altFormattedDateTime += $.datepicker.formatTime(this._defaults.altTimeFormat, this, this._defaults) + altTimeSuffix;
3502 else altFormattedDateTime += this.formattedTime + altTimeSuffix;
3503 this.$altInput.val(altFormattedDateTime);
3504 } else {
3505 this.$input.val(formattedDateTime);
3506 }
3507
3508 this.$input.trigger("change");
3509 },
3510
3511 _onFocus: function() {
3512 if (!this.$input.val() && this._defaults.defaultValue) {
3513 this.$input.val(this._defaults.defaultValue);
3514 var inst = $.datepicker._getInst(this.$input.get(0)),
3515 tp_inst = $.datepicker._get(inst, 'timepicker');
3516 if (tp_inst) {
3517 if (tp_inst._defaults.timeOnly && (inst.input.val() != inst.lastVal)) {
3518 try {
3519 $.datepicker._updateDatepicker(inst);
3520 } catch (err) {
3521 $.timepicker.log(err);
3522 }
3523 }
3524 }
3525 }
3526 },
3527
3528 /*
3529 * Small abstraction to control types
3530 * We can add more, just be sure to follow the pattern: create, options, value
3531 */
3532 _controls: {
3533 // slider methods
3534 slider: {
3535 create: function(tp_inst, obj, unit, val, min, max, step){
3536 var rtl = tp_inst._defaults.isRTL; // if rtl go -60->0 instead of 0->60
3537 return obj.prop('slide', null).slider({
3538 orientation: "horizontal",
3539 value: rtl? val*-1 : val,
3540 min: rtl? max*-1 : min,
3541 max: rtl? min*-1 : max,
3542 step: step,
3543 slide: function(event, ui) {
3544 tp_inst.control.value(tp_inst, $(this), unit, rtl? ui.value*-1:ui.value);
3545 tp_inst._onTimeChange();
3546 },
3547 stop: function(event, ui) {
3548 tp_inst._onSelectHandler();
3549 }
3550 });
3551 },
3552 options: function(tp_inst, obj, unit, opts, val){
3553 if(tp_inst._defaults.isRTL){
3554 if(typeof(opts) == 'string'){
3555 if(opts == 'min' || opts == 'max'){
3556 if(val !== undefined)
3557 return obj.slider(opts, val*-1);
3558 return Math.abs(obj.slider(opts));
3559 }
3560 return obj.slider(opts);
3561 }
3562 var min = opts.min,
3563 max = opts.max;
3564 opts.min = opts.max = null;
3565 if(min !== undefined)
3566 opts.max = min * -1;
3567 if(max !== undefined)
3568 opts.min = max * -1;
3569 return obj.slider(opts);
3570 }
3571 if(typeof(opts) == 'string' && val !== undefined)
3572 return obj.slider(opts, val);
3573 return obj.slider(opts);
3574 },
3575 value: function(tp_inst, obj, unit, val){
3576 if(tp_inst._defaults.isRTL){
3577 if(val !== undefined)
3578 return obj.slider('value', val*-1);
3579 return Math.abs(obj.slider('value'));
3580 }
3581 if(val !== undefined)
3582 return obj.slider('value', val);
3583 return obj.slider('value');
3584 }
3585 },
3586 // select methods
3587 select: {
3588 create: function(tp_inst, obj, unit, val, min, max, step){
3589 var sel = '<select class="ui-timepicker-select" data-unit="'+ unit +'" data-min="'+ min +'" data-max="'+ max +'" data-step="'+ step +'">',
3590 ul = tp_inst._defaults.timeFormat.indexOf('t') !== -1? 'toLowerCase':'toUpperCase',
3591 m = 0;
3592
3593 for(var i=min; i<=max; i+=step){
3594 sel += '<option value="'+ i +'"'+ (i==val? ' selected':'') +'>';
3595 if(unit == 'hour' && useAmpm(tp_inst._defaults.pickerTimeFormat || tp_inst._defaults.timeFormat))
3596 sel += $.datepicker.formatTime("hh TT", {hour:i}, tp_inst._defaults);
3597 else if(unit == 'millisec' || i >= 10) sel += i;
3598 else sel += '0'+ i.toString();
3599 sel += '</option>';
3600 }
3601 sel += '</select>';
3602
3603 obj.children('select').remove();
3604
3605 $(sel).appendTo(obj).change(function(e){
3606 tp_inst._onTimeChange();
3607 tp_inst._onSelectHandler();
3608 });
3609
3610 return obj;
3611 },
3612 options: function(tp_inst, obj, unit, opts, val){
3613 var o = {},
3614 $t = obj.children('select');
3615 if(typeof(opts) == 'string'){
3616 if(val === undefined)
3617 return $t.data(opts);
3618 o[opts] = val;
3619 }
3620 else o = opts;
3621 return tp_inst.control.create(tp_inst, obj, $t.data('unit'), $t.val(), o.min || $t.data('min'), o.max || $t.data('max'), o.step || $t.data('step'));
3622 },
3623 value: function(tp_inst, obj, unit, val){
3624 var $t = obj.children('select');
3625 if(val !== undefined)
3626 return $t.val(val);
3627 return $t.val();
3628 }
3629 }
3630 } // end _controls
3631
3632 });
3633
3634 $.fn.extend({
3635 /*
3636 * shorthand just to use timepicker..
3637 */
3638 timepicker: function(o) {
3639 o = o || {};
3640 var tmp_args = Array.prototype.slice.call(arguments);
3641
3642 if (typeof o == 'object') {
3643 tmp_args[0] = $.extend(o, {
3644 timeOnly: true
3645 });
3646 }
3647
3648 return $(this).each(function() {
3649 $.fn.datetimepicker.apply($(this), tmp_args);
3650 });
3651 },
3652
3653 /*
3654 * extend timepicker to datepicker
3655 */
3656 datetimepicker: function(o) {
3657 o = o || {};
3658 var tmp_args = arguments;
3659
3660 if (typeof(o) == 'string') {
3661 if (o == 'getDate') {
3662 return $.fn.datepicker.apply($(this[0]), tmp_args);
3663 } else {
3664 return this.each(function() {
3665 var $t = $(this);
3666 $t.datepicker.apply($t, tmp_args);
3667 });
3668 }
3669 } else {
3670 return this.each(function() {
3671 var $t = $(this);
3672 $t.datepicker($.timepicker._newInst($t, o)._defaults);
3673 });
3674 }
3675 }
3676 });
3677
3678 /*
3679 * Public Utility to parse date and time
3680 */
3681 $.datepicker.parseDateTime = function(dateFormat, timeFormat, dateTimeString, dateSettings, timeSettings) {
3682 var parseRes = parseDateTimeInternal(dateFormat, timeFormat, dateTimeString, dateSettings, timeSettings);
3683 if (parseRes.timeObj) {
3684 var t = parseRes.timeObj;
3685 parseRes.date.setHours(t.hour, t.minute, t.second, t.millisec);
3686 }
3687
3688 return parseRes.date;
3689 };
3690
3691 /*
3692 * Public utility to parse time
3693 */
3694 $.datepicker.parseTime = function(timeFormat, timeString, options) {
3695 var o = extendRemove(extendRemove({}, $.timepicker._defaults), options || {});
3696
3697 // Strict parse requires the timeString to match the timeFormat exactly
3698 var strictParse = function(f, s, o){
3699
3700 // pattern for standard and localized AM/PM markers
3701 var getPatternAmpm = function(amNames, pmNames) {
3702 var markers = [];
3703 if (amNames) {
3704 $.merge(markers, amNames);
3705 }
3706 if (pmNames) {
3707 $.merge(markers, pmNames);
3708 }
3709 markers = $.map(markers, function(val) {
3710 return val.replace(/[.*+?|()\[\]{}\\]/g, '\\$&');
3711 });
3712 return '(' + markers.join('|') + ')?';
3713 };
3714
3715 // figure out position of time elements.. cause js cant do named captures
3716 var getFormatPositions = function(timeFormat) {
3717 var finds = timeFormat.toLowerCase().match(/(h{1,2}|m{1,2}|s{1,2}|l{1}|t{1,2}|z|'.*?')/g),
3718 orders = {
3719 h: -1,
3720 m: -1,
3721 s: -1,
3722 l: -1,
3723 t: -1,
3724 z: -1
3725 };
3726
3727 if (finds) {
3728 for (var i = 0; i < finds.length; i++) {
3729 if (orders[finds[i].toString().charAt(0)] == -1) {
3730 orders[finds[i].toString().charAt(0)] = i + 1;
3731 }
3732 }
3733 }
3734 return orders;
3735 };
3736
3737 var regstr = '^' + f.toString()
3738 .replace(/([hH]{1,2}|mm?|ss?|[tT]{1,2}|[lz]|'.*?')/g, function (match) {
3739 var ml = match.length;
3740 switch (match.charAt(0).toLowerCase()) {
3741 case 'h': return ml === 1? '(\\d?\\d)':'(\\d{'+ml+'})';
3742 case 'm': return ml === 1? '(\\d?\\d)':'(\\d{'+ml+'})';
3743 case 's': return ml === 1? '(\\d?\\d)':'(\\d{'+ml+'})';
3744 case 'l': return '(\\d?\\d?\\d)';
3745 case 'z': return '(z|[-+]\\d\\d:?\\d\\d|\\S+)?';
3746 case 't': return getPatternAmpm(o.amNames, o.pmNames);
3747 default: // literal escaped in quotes
3748 return '(' + match.replace(/\'/g, "").replace(/(\.|\$|\^|\\|\/|\(|\)|\[|\]|\?|\+|\*)/g, function (m) { return "\\" + m; }) + ')?';
3749 }
3750 })
3751 .replace(/\s/g, '\\s?') +
3752 o.timeSuffix + '$',
3753 order = getFormatPositions(f),
3754 ampm = '',
3755 treg;
3756
3757 treg = s.match(new RegExp(regstr, 'i'));
3758
3759 var resTime = {
3760 hour: 0,
3761 minute: 0,
3762 second: 0,
3763 millisec: 0
3764 };
3765
3766 if (treg) {
3767 if (order.t !== -1) {
3768 if (treg[order.t] === undefined || treg[order.t].length === 0) {
3769 ampm = '';
3770 resTime.ampm = '';
3771 } else {
3772 ampm = $.inArray(treg[order.t].toUpperCase(), o.amNames) !== -1 ? 'AM' : 'PM';
3773 resTime.ampm = o[ampm == 'AM' ? 'amNames' : 'pmNames'][0];
3774 }
3775 }
3776
3777 if (order.h !== -1) {
3778 if (ampm == 'AM' && treg[order.h] == '12') {
3779 resTime.hour = 0; // 12am = 0 hour
3780 } else {
3781 if (ampm == 'PM' && treg[order.h] != '12') {
3782 resTime.hour = parseInt(treg[order.h], 10) + 12; // 12pm = 12 hour, any other pm = hour + 12
3783 } else {
3784 resTime.hour = Number(treg[order.h]);
3785 }
3786 }
3787 }
3788
3789 if (order.m !== -1) {
3790 resTime.minute = Number(treg[order.m]);
3791 }
3792 if (order.s !== -1) {
3793 resTime.second = Number(treg[order.s]);
3794 }
3795 if (order.l !== -1) {
3796 resTime.millisec = Number(treg[order.l]);
3797 }
3798 if (order.z !== -1 && treg[order.z] !== undefined) {
3799 var tz = treg[order.z].toUpperCase();
3800 switch (tz.length) {
3801 case 1:
3802 // Z
3803 tz = o.timezoneIso8601 ? 'Z' : '+0000';
3804 break;
3805 case 5:
3806 // +hhmm
3807 if (o.timezoneIso8601) {
3808 tz = tz.substring(1) == '0000' ? 'Z' : tz.substring(0, 3) + ':' + tz.substring(3);
3809 }
3810 break;
3811 case 6:
3812 // +hh:mm
3813 if (!o.timezoneIso8601) {
3814 tz = tz == 'Z' || tz.substring(1) == '00:00' ? '+0000' : tz.replace(/:/, '');
3815 } else {
3816 if (tz.substring(1) == '00:00') {
3817 tz = 'Z';
3818 }
3819 }
3820 break;
3821 }
3822 resTime.timezone = tz;
3823 }
3824
3825
3826 return resTime;
3827 }
3828 return false;
3829 };// end strictParse
3830
3831 // First try JS Date, if that fails, use strictParse
3832 var looseParse = function(f,s,o){
3833 try{
3834 var d = new Date('2012-01-01 '+ s);
3835 if(isNaN(d.getTime())){
3836 d = new Date('2012-01-01T'+ s);
3837 if(isNaN(d.getTime())){
3838 d = new Date('01/01/2012 '+ s);
3839 if(isNaN(d.getTime())){
3840 throw "Unable to parse time with native Date: "+ s;
3841 }
3842 }
3843 }
3844
3845 return {
3846 hour: d.getHours(),
3847 minute: d.getMinutes(),
3848 second: d.getSeconds(),
3849 millisec: d.getMilliseconds(),
3850 timezone: $.timepicker.timeZoneOffsetString(d)
3851 };
3852 }
3853 catch(err){
3854 try{
3855 return strictParse(f,s,o);
3856 }
3857 catch(err2){
3858 $.timepicker.log("Unable to parse \ntimeString: "+ s +"\ntimeFormat: "+ f);
3859 }
3860 }
3861 return false;
3862 }; // end looseParse
3863
3864 if(typeof o.parse === "function"){
3865 return o.parse(timeFormat, timeString, o)
3866 }
3867 if(o.parse === 'loose'){
3868 return looseParse(timeFormat, timeString, o);
3869 }
3870 return strictParse(timeFormat, timeString, o);
3871 };
3872
3873 /*
3874 * Public utility to format the time
3875 * format = string format of the time
3876 * time = a {}, not a Date() for timezones
3877 * options = essentially the regional[].. amNames, pmNames, ampm
3878 */
3879 $.datepicker.formatTime = function(format, time, options) {
3880 options = options || {};
3881 options = $.extend({}, $.timepicker._defaults, options);
3882 time = $.extend({
3883 hour: 0,
3884 minute: 0,
3885 second: 0,
3886 millisec: 0,
3887 timezone: '+0000'
3888 }, time);
3889
3890 var tmptime = format,
3891 ampmName = options.amNames[0],
3892 hour = parseInt(time.hour, 10);
3893
3894 if (hour > 11) {
3895 ampmName = options.pmNames[0];
3896 }
3897
3898 tmptime = tmptime.replace(/(?:HH?|hh?|mm?|ss?|[tT]{1,2}|[lz]|('.*?'|".*?"))/g, function(match) {
3899 switch (match) {
3900 case 'HH':
3901 return ('0' + hour).slice(-2);
3902 case 'H':
3903 return hour;
3904 case 'hh':
3905 return ('0' + convert24to12(hour)).slice(-2);
3906 case 'h':
3907 return convert24to12(hour);
3908 case 'mm':
3909 return ('0' + time.minute).slice(-2);
3910 case 'm':
3911 return time.minute;
3912 case 'ss':
3913 return ('0' + time.second).slice(-2);
3914 case 's':
3915 return time.second;
3916 case 'l':
3917 return ('00' + time.millisec).slice(-3);
3918 case 'z':
3919 return time.timezone === null? options.defaultTimezone : time.timezone;
3920 case 'T':
3921 return ampmName.charAt(0).toUpperCase();
3922 case 'TT':
3923 return ampmName.toUpperCase();
3924 case 't':
3925 return ampmName.charAt(0).toLowerCase();
3926 case 'tt':
3927 return ampmName.toLowerCase();
3928 default:
3929 return match.replace(/\'/g, "") || "'";
3930 }
3931 });
3932
3933 tmptime = $.trim(tmptime);
3934 return tmptime;
3935 };
3936
3937 /*
3938 * the bad hack :/ override datepicker so it doesnt close on select
3939 // inspired: http://stackoverflow.com/questions/1252512/jquery-datepicker-prevent-closing-picker-when-clicking-a-date/1762378#1762378
3940 */
3941 $.datepicker._base_selectDate = $.datepicker._selectDate;
3942 $.datepicker._selectDate = function(id, dateStr) {
3943 var inst = this._getInst($(id)[0]),
3944 tp_inst = this._get(inst, 'timepicker');
3945
3946 if (tp_inst) {
3947 tp_inst._limitMinMaxDateTime(inst, true);
3948 inst.inline = inst.stay_open = true;
3949 //This way the onSelect handler called from calendarpicker get the full dateTime
3950 this._base_selectDate(id, dateStr);
3951 inst.inline = inst.stay_open = false;
3952 this._notifyChange(inst);
3953 this._updateDatepicker(inst);
3954 } else {
3955 this._base_selectDate(id, dateStr);
3956 }
3957 };
3958
3959 /*
3960 * second bad hack :/ override datepicker so it triggers an event when changing the input field
3961 * and does not redraw the datepicker on every selectDate event
3962 */
3963 $.datepicker._base_updateDatepicker = $.datepicker._updateDatepicker;
3964 $.datepicker._updateDatepicker = function(inst) {
3965
3966 // don't popup the datepicker if there is another instance already opened
3967 var input = inst.input[0];
3968 if ($.datepicker._curInst && $.datepicker._curInst != inst && $.datepicker._datepickerShowing && $.datepicker._lastInput != input) {
3969 return;
3970 }
3971
3972 if (typeof(inst.stay_open) !== 'boolean' || inst.stay_open === false) {
3973
3974 this._base_updateDatepicker(inst);
3975
3976 // Reload the time control when changing something in the input text field.
3977 var tp_inst = this._get(inst, 'timepicker');
3978 if (tp_inst) {
3979 tp_inst._addTimePicker(inst);
3980
3981 // if (tp_inst._defaults.useLocalTimezone) { //checks daylight saving with the new date.
3982 // var date = new Date(inst.selectedYear, inst.selectedMonth, inst.selectedDay, 12);
3983 // selectLocalTimeZone(tp_inst, date);
3984 // tp_inst._onTimeChange();
3985 // }
3986 }
3987 }
3988 };
3989
3990 /*
3991 * third bad hack :/ override datepicker so it allows spaces and colon in the input field
3992 */
3993 $.datepicker._base_doKeyPress = $.datepicker._doKeyPress;
3994 $.datepicker._doKeyPress = function(event) {
3995 var inst = $.datepicker._getInst(event.target),
3996 tp_inst = $.datepicker._get(inst, 'timepicker');
3997
3998 if (tp_inst) {
3999 if ($.datepicker._get(inst, 'constrainInput')) {
4000 var ampm = useAmpm(tp_inst._defaults.timeFormat),
4001 dateChars = $.datepicker._possibleChars($.datepicker._get(inst, 'dateFormat')),
4002 datetimeChars = tp_inst._defaults.timeFormat.toString()
4003 .replace(/[hms]/g, '')
4004 .replace(/TT/g, ampm ? 'APM' : '')
4005 .replace(/Tt/g, ampm ? 'AaPpMm' : '')
4006 .replace(/tT/g, ampm ? 'AaPpMm' : '')
4007 .replace(/T/g, ampm ? 'AP' : '')
4008 .replace(/tt/g, ampm ? 'apm' : '')
4009 .replace(/t/g, ampm ? 'ap' : '') +
4010 " " + tp_inst._defaults.separator +
4011 tp_inst._defaults.timeSuffix +
4012 (tp_inst._defaults.showTimezone ? tp_inst._defaults.timezoneList.join('') : '') +
4013 (tp_inst._defaults.amNames.join('')) + (tp_inst._defaults.pmNames.join('')) +
4014 dateChars,
4015 chr = String.fromCharCode(event.charCode === undefined ? event.keyCode : event.charCode);
4016 return event.ctrlKey || (chr < ' ' || !dateChars || datetimeChars.indexOf(chr) > -1);
4017 }
4018 }
4019
4020 return $.datepicker._base_doKeyPress(event);
4021 };
4022
4023 /*
4024 * Fourth bad hack :/ override _updateAlternate function used in inline mode to init altField
4025 */
4026 $.datepicker._base_updateAlternate = $.datepicker._updateAlternate;
4027 /* Update any alternate field to synchronise with the main field. */
4028 $.datepicker._updateAlternate = function(inst) {
4029 var tp_inst = this._get(inst, 'timepicker');
4030 if(tp_inst){
4031 var altField = tp_inst._defaults.altField;
4032 if (altField) { // update alternate field too
4033 var altFormat = tp_inst._defaults.altFormat || tp_inst._defaults.dateFormat,
4034 date = this._getDate(inst),
4035 formatCfg = $.datepicker._getFormatConfig(inst),
4036 altFormattedDateTime = '',
4037 altSeparator = tp_inst._defaults.altSeparator ? tp_inst._defaults.altSeparator : tp_inst._defaults.separator,
4038 altTimeSuffix = tp_inst._defaults.altTimeSuffix ? tp_inst._defaults.altTimeSuffix : tp_inst._defaults.timeSuffix,
4039 altTimeFormat = tp_inst._defaults.altTimeFormat !== null ? tp_inst._defaults.altTimeFormat : tp_inst._defaults.timeFormat;
4040
4041 altFormattedDateTime += $.datepicker.formatTime(altTimeFormat, tp_inst, tp_inst._defaults) + altTimeSuffix;
4042 if(!tp_inst._defaults.timeOnly && !tp_inst._defaults.altFieldTimeOnly && date !== null){
4043 if(tp_inst._defaults.altFormat)
4044 altFormattedDateTime = $.datepicker.formatDate(tp_inst._defaults.altFormat, date, formatCfg) + altSeparator + altFormattedDateTime;
4045 else altFormattedDateTime = tp_inst.formattedDate + altSeparator + altFormattedDateTime;
4046 }
4047 $(altField).val(altFormattedDateTime);
4048 }
4049 }
4050 else{
4051 $.datepicker._base_updateAlternate(inst);
4052 }
4053 };
4054
4055 /*
4056 * Override key up event to sync manual input changes.
4057 */
4058 $.datepicker._base_doKeyUp = $.datepicker._doKeyUp;
4059 $.datepicker._doKeyUp = function(event) {
4060 var inst = $.datepicker._getInst(event.target),
4061 tp_inst = $.datepicker._get(inst, 'timepicker');
4062
4063 if (tp_inst) {
4064 if (tp_inst._defaults.timeOnly && (inst.input.val() != inst.lastVal)) {
4065 try {
4066 $.datepicker._updateDatepicker(inst);
4067 } catch (err) {
4068 $.timepicker.log(err);
4069 }
4070 }
4071 }
4072
4073 return $.datepicker._base_doKeyUp(event);
4074 };
4075
4076 /*
4077 * override "Today" button to also grab the time.
4078 */
4079 $.datepicker._base_gotoToday = $.datepicker._gotoToday;
4080 $.datepicker._gotoToday = function(id) {
4081 var inst = this._getInst($(id)[0]),
4082 $dp = inst.dpDiv;
4083 this._base_gotoToday(id);
4084 var tp_inst = this._get(inst, 'timepicker');
4085 selectLocalTimeZone(tp_inst);
4086 var now = new Date();
4087 this._setTime(inst, now);
4088 $('.ui-datepicker-today', $dp).click();
4089 };
4090
4091 /*
4092 * Disable & enable the Time in the datetimepicker
4093 */
4094 $.datepicker._disableTimepickerDatepicker = function(target) {
4095 var inst = this._getInst(target);
4096 if (!inst) {
4097 return;
4098 }
4099
4100 var tp_inst = this._get(inst, 'timepicker');
4101 $(target).datepicker('getDate'); // Init selected[Year|Month|Day]
4102 if (tp_inst) {
4103 tp_inst._defaults.showTimepicker = false;
4104 tp_inst._updateDateTime(inst);
4105 }
4106 };
4107
4108 $.datepicker._enableTimepickerDatepicker = function(target) {
4109 var inst = this._getInst(target);
4110 if (!inst) {
4111 return;
4112 }
4113
4114 var tp_inst = this._get(inst, 'timepicker');
4115 $(target).datepicker('getDate'); // Init selected[Year|Month|Day]
4116 if (tp_inst) {
4117 tp_inst._defaults.showTimepicker = true;
4118 tp_inst._addTimePicker(inst); // Could be disabled on page load
4119 tp_inst._updateDateTime(inst);
4120 }
4121 };
4122
4123 /*
4124 * Create our own set time function
4125 */
4126 $.datepicker._setTime = function(inst, date) {
4127 var tp_inst = this._get(inst, 'timepicker');
4128 if (tp_inst) {
4129 var defaults = tp_inst._defaults;
4130
4131 // calling _setTime with no date sets time to defaults
4132 tp_inst.hour = date ? date.getHours() : defaults.hour;
4133 tp_inst.minute = date ? date.getMinutes() : defaults.minute;
4134 tp_inst.second = date ? date.getSeconds() : defaults.second;
4135 tp_inst.millisec = date ? date.getMilliseconds() : defaults.millisec;
4136
4137 //check if within min/max times..
4138 tp_inst._limitMinMaxDateTime(inst, true);
4139
4140 tp_inst._onTimeChange();
4141 tp_inst._updateDateTime(inst);
4142 }
4143 };
4144
4145 /*
4146 * Create new public method to set only time, callable as $().datepicker('setTime', date)
4147 */
4148 $.datepicker._setTimeDatepicker = function(target, date, withDate) {
4149 var inst = this._getInst(target);
4150 if (!inst) {
4151 return;
4152 }
4153
4154 var tp_inst = this._get(inst, 'timepicker');
4155
4156 if (tp_inst) {
4157 this._setDateFromField(inst);
4158 var tp_date;
4159 if (date) {
4160 if (typeof date == "string") {
4161 tp_inst._parseTime(date, withDate);
4162 tp_date = new Date();
4163 tp_date.setHours(tp_inst.hour, tp_inst.minute, tp_inst.second, tp_inst.millisec);
4164 } else {
4165 tp_date = new Date(date.getTime());
4166 }
4167 if (tp_date.toString() == 'Invalid Date') {
4168 tp_date = undefined;
4169 }
4170 this._setTime(inst, tp_date);
4171 }
4172 }
4173
4174 };
4175
4176 /*
4177 * override setDate() to allow setting time too within Date object
4178 */
4179 $.datepicker._base_setDateDatepicker = $.datepicker._setDateDatepicker;
4180 $.datepicker._setDateDatepicker = function(target, date) {
4181 var inst = this._getInst(target);
4182 if (!inst) {
4183 return;
4184 }
4185
4186 var tp_date = (date instanceof Date) ? new Date(date.getTime()) : date;
4187
4188 this._updateDatepicker(inst);
4189 this._base_setDateDatepicker.apply(this, arguments);
4190 this._setTimeDatepicker(target, tp_date, true);
4191 };
4192
4193 /*
4194 * override getDate() to allow getting time too within Date object
4195 */
4196 $.datepicker._base_getDateDatepicker = $.datepicker._getDateDatepicker;
4197 $.datepicker._getDateDatepicker = function(target, noDefault) {
4198 var inst = this._getInst(target);
4199 if (!inst) {
4200 return;
4201 }
4202
4203 var tp_inst = this._get(inst, 'timepicker');
4204
4205 if (tp_inst) {
4206 // if it hasn't yet been defined, grab from field
4207 if(inst.lastVal === undefined){
4208 this._setDateFromField(inst, noDefault);
4209 }
4210
4211 var date = this._getDate(inst);
4212 if (date && tp_inst._parseTime($(target).val(), tp_inst.timeOnly)) {
4213 date.setHours(tp_inst.hour, tp_inst.minute, tp_inst.second, tp_inst.millisec);
4214 }
4215 return date;
4216 }
4217 return this._base_getDateDatepicker(target, noDefault);
4218 };
4219
4220 /*
4221 * override parseDate() because UI 1.8.14 throws an error about "Extra characters"
4222 * An option in datapicker to ignore extra format characters would be nicer.
4223 */
4224 $.datepicker._base_parseDate = $.datepicker.parseDate;
4225 $.datepicker.parseDate = function(format, value, settings) {
4226 var date;
4227 try {
4228 date = this._base_parseDate(format, value, settings);
4229 } catch (err) {
4230 // Hack! The error message ends with a colon, a space, and
4231 // the "extra" characters. We rely on that instead of
4232 // attempting to perfectly reproduce the parsing algorithm.
4233 date = this._base_parseDate(format, value.substring(0,value.length-(err.length-err.indexOf(':')-2)), settings);
4234 $.timepicker.log("Error parsing the date string: " + err + "\ndate string = " + value + "\ndate format = " + format);
4235 }
4236 return date;
4237 };
4238
4239 /*
4240 * override formatDate to set date with time to the input
4241 */
4242 $.datepicker._base_formatDate = $.datepicker._formatDate;
4243 $.datepicker._formatDate = function(inst, day, month, year) {
4244 var tp_inst = this._get(inst, 'timepicker');
4245 if (tp_inst) {
4246 tp_inst._updateDateTime(inst);
4247 return tp_inst.$input.val();
4248 }
4249 return this._base_formatDate(inst);
4250 };
4251
4252 /*
4253 * override options setter to add time to maxDate(Time) and minDate(Time). MaxDate
4254 */
4255 $.datepicker._base_optionDatepicker = $.datepicker._optionDatepicker;
4256 $.datepicker._optionDatepicker = function(target, name, value) {
4257 var inst = this._getInst(target),
4258 name_clone;
4259 if (!inst) {
4260 return null;
4261 }
4262
4263 var tp_inst = this._get(inst, 'timepicker');
4264 if (tp_inst) {
4265 var min = null,
4266 max = null,
4267 onselect = null,
4268 overrides = tp_inst._defaults.evnts,
4269 fns = {},
4270 prop;
4271 if (typeof name == 'string') { // if min/max was set with the string
4272 if (name === 'minDate' || name === 'minDateTime') {
4273 min = value;
4274 } else if (name === 'maxDate' || name === 'maxDateTime') {
4275 max = value;
4276 } else if (name === 'onSelect') {
4277 onselect = value;
4278 } else if (overrides.hasOwnProperty(name)) {
4279 if (typeof (value) === 'undefined') {
4280 return overrides[name];
4281 }
4282 fns[name] = value;
4283 name_clone = {}; //empty results in exiting function after overrides updated
4284 }
4285 } else if (typeof name == 'object') { //if min/max was set with the JSON
4286 if (name.minDate) {
4287 min = name.minDate;
4288 } else if (name.minDateTime) {
4289 min = name.minDateTime;
4290 } else if (name.maxDate) {
4291 max = name.maxDate;
4292 } else if (name.maxDateTime) {
4293 max = name.maxDateTime;
4294 }
4295 for (prop in overrides) {
4296 if (overrides.hasOwnProperty(prop) && name[prop]) {
4297 fns[prop] = name[prop];
4298 }
4299 }
4300 }
4301 for (prop in fns) {
4302 if (fns.hasOwnProperty(prop)) {
4303 overrides[prop] = fns[prop];
4304 if (!name_clone) { name_clone = $.extend({}, name);}
4305 delete name_clone[prop];
4306 }
4307 }
4308 if (name_clone && isEmptyObject(name_clone)) { return; }
4309 if (min) { //if min was set
4310 if (min === 0) {
4311 min = new Date();
4312 } else {
4313 min = new Date(min);
4314 }
4315 tp_inst._defaults.minDate = min;
4316 tp_inst._defaults.minDateTime = min;
4317 } else if (max) { //if max was set
4318 if (max === 0) {
4319 max = new Date();
4320 } else {
4321 max = new Date(max);
4322 }
4323 tp_inst._defaults.maxDate = max;
4324 tp_inst._defaults.maxDateTime = max;
4325 } else if (onselect) {
4326 tp_inst._defaults.onSelect = onselect;
4327 }
4328 }
4329 if (value === undefined) {
4330 return this._base_optionDatepicker.call($.datepicker, target, name);
4331 }
4332 return this._base_optionDatepicker.call($.datepicker, target, name_clone || name, value);
4333 };
4334 /*
4335 * jQuery isEmptyObject does not check hasOwnProperty - if someone has added to the object prototype,
4336 * it will return false for all objects
4337 */
4338 var isEmptyObject = function(obj) {
4339 var prop;
4340 for (prop in obj) {
4341 if (obj.hasOwnProperty(obj)) {
4342 return false;
4343 }
4344 }
4345 return true;
4346 };
4347
4348 /*
4349 * jQuery extend now ignores nulls!
4350 */
4351 var extendRemove = function(target, props) {
4352 $.extend(target, props);
4353 for (var name in props) {
4354 if (props[name] === null || props[name] === undefined) {
4355 target[name] = props[name];
4356 }
4357 }
4358 return target;
4359 };
4360
4361 /*
4362 * Determine by the time format if should use ampm
4363 * Returns true if should use ampm, false if not
4364 */
4365 var useAmpm = function(timeFormat){
4366 return (timeFormat.indexOf('t') !== -1 && timeFormat.indexOf('h') !== -1);
4367 };
4368
4369 /*
4370 * Converts 24 hour format into 12 hour
4371 * Returns 12 hour without leading 0
4372 */
4373 var convert24to12 = function(hour) {
4374 if (hour > 12) {
4375 hour = hour - 12;
4376 }
4377
4378 if (hour == 0) {
4379 hour = 12;
4380 }
4381
4382 return String(hour);
4383 };
4384
4385 /*
4386 * Splits datetime string into date ans time substrings.
4387 * Throws exception when date can't be parsed
4388 * Returns [dateString, timeString]
4389 */
4390 var splitDateTime = function(dateFormat, dateTimeString, dateSettings, timeSettings) {
4391 try {
4392 // The idea is to get the number separator occurances in datetime and the time format requested (since time has
4393 // fewer unknowns, mostly numbers and am/pm). We will use the time pattern to split.
4394 var separator = timeSettings && timeSettings.separator ? timeSettings.separator : $.timepicker._defaults.separator,
4395 format = timeSettings && timeSettings.timeFormat ? timeSettings.timeFormat : $.timepicker._defaults.timeFormat,
4396 timeParts = format.split(separator), // how many occurances of separator may be in our format?
4397 timePartsLen = timeParts.length,
4398 allParts = dateTimeString.split(separator),
4399 allPartsLen = allParts.length;
4400
4401 if (allPartsLen > 1) {
4402 return [
4403 allParts.splice(0,allPartsLen-timePartsLen).join(separator),
4404 allParts.splice(0,timePartsLen).join(separator)
4405 ];
4406 }
4407
4408 } catch (err) {
4409 $.timepicker.log('Could not split the date from the time. Please check the following datetimepicker options' +
4410 "\nthrown error: " + err +
4411 "\ndateTimeString" + dateTimeString +
4412 "\ndateFormat = " + dateFormat +
4413 "\nseparator = " + timeSettings.separator +
4414 "\ntimeFormat = " + timeSettings.timeFormat);
4415
4416 if (err.indexOf(":") >= 0) {
4417 // Hack! The error message ends with a colon, a space, and
4418 // the "extra" characters. We rely on that instead of
4419 // attempting to perfectly reproduce the parsing algorithm.
4420 var dateStringLength = dateTimeString.length - (err.length - err.indexOf(':') - 2),
4421 timeString = dateTimeString.substring(dateStringLength);
4422
4423 return [$.trim(dateTimeString.substring(0, dateStringLength)), $.trim(dateTimeString.substring(dateStringLength))];
4424
4425 } else {
4426 throw err;
4427 }
4428 }
4429 return [dateTimeString, ''];
4430 };
4431
4432 /*
4433 * Internal function to parse datetime interval
4434 * Returns: {date: Date, timeObj: Object}, where
4435 * date - parsed date without time (type Date)
4436 * timeObj = {hour: , minute: , second: , millisec: } - parsed time. Optional
4437 */
4438 var parseDateTimeInternal = function(dateFormat, timeFormat, dateTimeString, dateSettings, timeSettings) {
4439 var date;
4440 var splitRes = splitDateTime(dateFormat, dateTimeString, dateSettings, timeSettings);
4441 date = $.datepicker._base_parseDate(dateFormat, splitRes[0], dateSettings);
4442 if (splitRes[1] !== '') {
4443 var timeString = splitRes[1],
4444 parsedTime = $.datepicker.parseTime(timeFormat, timeString, timeSettings);
4445
4446 if (parsedTime === null) {
4447 throw 'Wrong time format';
4448 }
4449 return {
4450 date: date,
4451 timeObj: parsedTime
4452 };
4453 } else {
4454 return {
4455 date: date
4456 };
4457 }
4458 };
4459
4460 /*
4461 * Internal function to set timezone_select to the local timezone
4462 */
4463 var selectLocalTimeZone = function(tp_inst, date) {
4464 if (tp_inst && tp_inst.timezone_select) {
4465 tp_inst._defaults.useLocalTimezone = true;
4466 var now = typeof date !== 'undefined' ? date : new Date();
4467 var tzoffset = $.timepicker.timeZoneOffsetString(now);
4468 if (tp_inst._defaults.timezoneIso8601) {
4469 tzoffset = tzoffset.substring(0, 3) + ':' + tzoffset.substring(3);
4470 }
4471 tp_inst.timezone_select.val(tzoffset);
4472 }
4473 };
4474
4475 /*
4476 * Create a Singleton Insance
4477 */
4478 $.timepicker = new Timepicker();
4479
4480 /**
4481 * Get the timezone offset as string from a date object (eg '+0530' for UTC+5.5)
4482 * @param date
4483 * @return string
4484 */
4485 $.timepicker.timeZoneOffsetString = function(date) {
4486 var off = date.getTimezoneOffset() * -1,
4487 minutes = off % 60,
4488 hours = (off - minutes) / 60;
4489 return (off >= 0 ? '+' : '-') + ('0' + (hours * 101).toString()).slice(-2) + ('0' + (minutes * 101).toString()).slice(-2);
4490 };
4491
4492 /**
4493 * Calls `timepicker()` on the `startTime` and `endTime` elements, and configures them to
4494 * enforce date range limits.
4495 * n.b. The input value must be correctly formatted (reformatting is not supported)
4496 * @param Element startTime
4497 * @param Element endTime
4498 * @param obj options Options for the timepicker() call
4499 * @return jQuery
4500 */
4501 $.timepicker.timeRange = function(startTime, endTime, options) {
4502 return $.timepicker.handleRange('timepicker', startTime, endTime, options);
4503 };
4504
4505 /**
4506 * Calls `datetimepicker` on the `startTime` and `endTime` elements, and configures them to
4507 * enforce date range limits.
4508 * @param Element startTime
4509 * @param Element endTime
4510 * @param obj options Options for the `timepicker()` call. Also supports `reformat`,
4511 * a boolean value that can be used to reformat the input values to the `dateFormat`.
4512 * @param string method Can be used to specify the type of picker to be added
4513 * @return jQuery
4514 */
4515 $.timepicker.dateTimeRange = function(startTime, endTime, options) {
4516 $.timepicker.dateRange(startTime, endTime, options, 'datetimepicker');
4517 };
4518
4519 /**
4520 * Calls `method` on the `startTime` and `endTime` elements, and configures them to
4521 * enforce date range limits.
4522 * @param Element startTime
4523 * @param Element endTime
4524 * @param obj options Options for the `timepicker()` call. Also supports `reformat`,
4525 * a boolean value that can be used to reformat the input values to the `dateFormat`.
4526 * @param string method Can be used to specify the type of picker to be added
4527 * @return jQuery
4528 */
4529 $.timepicker.dateRange = function(startTime, endTime, options, method) {
4530 method = method || 'datepicker';
4531 $.timepicker.handleRange(method, startTime, endTime, options);
4532 };
4533
4534 /**
4535 * Calls `method` on the `startTime` and `endTime` elements, and configures them to
4536 * enforce date range limits.
4537 * @param string method Can be used to specify the type of picker to be added
4538 * @param Element startTime
4539 * @param Element endTime
4540 * @param obj options Options for the `timepicker()` call. Also supports `reformat`,
4541 * a boolean value that can be used to reformat the input values to the `dateFormat`.
4542 * @return jQuery
4543 */
4544 $.timepicker.handleRange = function(method, startTime, endTime, options) {
4545 $.fn[method].call(startTime, $.extend({
4546 onClose: function(dateText, inst) {
4547 checkDates(this, endTime, dateText);
4548 },
4549 onSelect: function(selectedDateTime) {
4550 selected(this, endTime, 'minDate');
4551 }
4552 }, options, options.start));
4553 $.fn[method].call(endTime, $.extend({
4554 onClose: function(dateText, inst) {
4555 checkDates(this, startTime, dateText);
4556 },
4557 onSelect: function(selectedDateTime) {
4558 selected(this, startTime, 'maxDate');
4559 }
4560 }, options, options.end));
4561 // timepicker doesn't provide access to its 'timeFormat' option,
4562 // nor could I get datepicker.formatTime() to behave with times, so I
4563 // have disabled reformatting for timepicker
4564 if (method != 'timepicker' && options.reformat) {
4565 $([startTime, endTime]).each(function() {
4566 var format = $(this)[method].call($(this), 'option', 'dateFormat'),
4567 date = new Date($(this).val());
4568 if ($(this).val() && date) {
4569 $(this).val($.datepicker.formatDate(format, date));
4570 }
4571 });
4572 }
4573 checkDates(startTime, endTime, startTime.val());
4574
4575 function checkDates(changed, other, dateText) {
4576 if (other.val() && (new Date(startTime.val()) > new Date(endTime.val()))) {
4577 other.val(dateText);
4578 }
4579 }
4580 selected(startTime, endTime, 'minDate');
4581 selected(endTime, startTime, 'maxDate');
4582
4583 function selected(changed, other, option) {
4584 if (!$(changed).val()) {
4585 return;
4586 }
4587 var date = $(changed)[method].call($(changed), 'getDate');
4588 // timepicker doesn't implement 'getDate' and returns a jQuery
4589 if (date.getTime) {
4590 $(other)[method].call($(other), 'option', option, date);
4591 }
4592 }
4593 return $([startTime.get(0), endTime.get(0)]);
4594 };
4595
4596 /**
4597 * Log error or data to the console during error or debugging
4598 * @param Object err pass any type object to log to the console during error or debugging
4599 * @return void
4600 */
4601 $.timepicker.log = function(err){
4602 if(window.console)
4603 console.log(err);
4604 };
4605
4606 /*
4607 * Keep up with the version
4608 */
4609 $.timepicker.version = "1.2";
4610
4611 })(jQuery);
4612
4613 /* assets/wpuf/js/upload.js */
4614 ;(function($) {
4615
4616 /**
4617 * Upload handler helper
4618 *
4619 * @param string {browse_button} browse_button ID of the pickfile
4620 * @param string {container} container ID of the wrapper
4621 * @param int {max} maximum number of file uplaods
4622 * @param string {type}
4623 */
4624 window.WPUF_Uploader = function (browse_button, container, max, type, allowed_type, max_file_size) {
4625 this.removed_files = [];
4626 this.container = container;
4627 this.browse_button = browse_button;
4628 this.max = max || 1;
4629 this.count = $('#' + container).find('.wpuf-attachment-list > li').length; //count how many items are there
4630 this.perFileCount = 0; //file count on each upload
4631 this.UploadedFiles = 0; //file count on each upload
4632
4633 //if no element found on the page, bail out
4634 if( !$('#'+browse_button).length ) {
4635 return;
4636 }
4637
4638 // enable drag option for ordering
4639 $( "ul.wpuf-attachment-list" ).sortable({
4640 placeholder: "highlight"
4641 });
4642 $( "ul.wpuf-attachment-list" ).disableSelection();
4643
4644 //instantiate the uploader
4645 this.uploader = new plupload.Uploader({
4646 runtimes: 'html5,html4',
4647 browse_button: browse_button,
4648 container: container,
4649 multipart: true,
4650 multipart_params: {
4651 action: 'wpuf_upload_file',
4652 form_id: $( '#' + browse_button ).data('form_id')
4653 },
4654 max_file_count : 2,
4655 multiple_queues: false,
4656 multi_selection: ( ( browse_button == 'wpuf-avatar-pickfiles' || browse_button == 'wpuf-featured_image-pickfiles' ) ? false : true ),
4657 urlstream_upload: true,
4658 file_data_name: 'wpuf_file',
4659 max_file_size: max_file_size + 'kb',
4660 url: wpuf_frontend_upload.plupload.url + '&type=' + type,
4661 flash_swf_url: wpuf_frontend_upload.flash_swf_url,
4662 filters: [{
4663 title: 'Allowed Files',
4664 extensions: allowed_type
4665 }]
4666 });
4667
4668 //attach event handlers
4669 this.uploader.bind('Init', $.proxy(this, 'init'));
4670 this.uploader.bind('FilesAdded', $.proxy(this, 'added'));
4671 this.uploader.bind('QueueChanged', $.proxy(this, 'upload'));
4672 this.uploader.bind('UploadProgress', $.proxy(this, 'progress'));
4673 this.uploader.bind('Error', $.proxy(this, 'error'));
4674 this.uploader.bind('FileUploaded', $.proxy(this, 'uploaded'));
4675
4676 this.uploader.init();
4677
4678 $('#' + container).on('click', 'a.attachment-delete', $.proxy(this.removeAttachment, this));
4679
4680 return this.uploader;
4681 };
4682
4683 WPUF_Uploader.prototype = {
4684
4685 init: function (up, params) {
4686 this.showHide();
4687 $('#' + this.container).prepend('<div class="wpuf-file-warning"></div>');
4688 },
4689
4690 showHide: function () {
4691
4692 if ( this.count >= this.max) {
4693
4694 if ( this.count > this.max ) {
4695 $('#' + this.container + ' .wpuf-file-warning').html( wpuf_frontend_upload.warning );
4696 } else {
4697 $('#' + this.container + ' .wpuf-file-warning').html( wpuf_frontend_upload.warning );
4698 }
4699
4700 $('#' + this.container).find('.file-selector').hide();
4701
4702 return;
4703 };
4704 $('#' + this.container + ' .wpuf-file-warning').html( '' );
4705 $('#' + this.container).find('.file-selector').show();
4706 },
4707
4708 added: function (up, files) {
4709 var $container = $('#' + this.container).find('.wpuf-attachment-upload-filelist');
4710
4711 this.showHide();
4712
4713 $.each(files, function(i, file) {
4714 $(".wpuf-submit-button").attr("disabled", "disabled");
4715
4716 $container.append(
4717 '<div class="upload-item" id="' + file.id + '"><div class="progress progress-striped active"><div class="bar"></div></div><div class="filename original">' +
4718 file.name + ' (' + plupload.formatSize(file.size) + ') <b></b>' +
4719 '</div></div>');
4720 });
4721
4722 up.refresh(); // Reposition Flash/Silverlight
4723 up.start();
4724 },
4725
4726 upload: function (uploader) {
4727 this.count = uploader.files.length - this.removed_files.length ;
4728 this.showHide();
4729 },
4730
4731 progress: function (up, file) {
4732 var item = $('#' + file.id);
4733
4734 $('.bar', item).css({ width: file.percent + '%' });
4735 $('.percent', item).html( file.percent + '%' );
4736 },
4737
4738 error: function (up, error) {
4739 $('#' + this.container).find('#' + error.file.id).remove();
4740
4741 var msg = '';
4742 switch (error.code) {
4743 case -600:
4744 msg = wpuf_frontend_upload.plupload.size_error;
4745 break;
4746
4747 case -601:
4748 msg = wpuf_frontend_upload.plupload.type_error;
4749 break;
4750
4751 default:
4752 msg = 'Error #' + error.code + ': ' + error.message;
4753 break;
4754 }
4755
4756 alert(msg);
4757
4758 this.count -= 1;
4759 this.showHide();
4760 this.uploader.refresh();
4761 },
4762
4763 uploaded: function (up, file, response) {
4764 // var res = $.parseJSON(response.response);
4765 var self = this;
4766
4767 $('#' + file.id + " b").html("100%");
4768 $('#' + file.id).remove();
4769
4770 if(response.response !== 'error') {
4771
4772 this.perFileCount++;
4773 this.UploadedFiles++;
4774 var $container = $('#' + this.container).find('.wpuf-attachment-list');
4775 $container.append(response.response);
4776
4777 if ( this.perFileCount > this.max ) {
4778 var attach_id = $('.wpuf-image-wrap:last a.attachment-delete',$container).data('attach_id');
4779 self.removeExtraAttachment(attach_id);
4780 $('.wpuf-image-wrap',$container).last().remove();
4781 this.perFileCount--;
4782 }
4783
4784 } else {
4785 alert(response.error);
4786
4787 this.count -= 1;
4788 this.showHide();
4789 }
4790
4791 var uploaded = this.UploadedFiles,
4792 FileProgress = up.files.length,
4793 imageCount = $('ul.wpuf-attachment-list > li').length;
4794
4795 if ( imageCount >= this.max ) {
4796 $('#' + this.container).find('.file-selector').hide();
4797 }
4798
4799 if ( FileProgress === uploaded ) {
4800 if ( typeof grecaptcha !== 'undefined' && !grecaptcha.getResponse().length ) {
4801 return;
4802 }
4803 $(".wpuf-submit-button").removeAttr("disabled");
4804 }
4805 },
4806
4807 removeAttachment: function(e) {
4808 e.preventDefault();
4809
4810 var self = this,
4811 el = $(e.currentTarget);
4812
4813 swal({
4814 text: wpuf_frontend_upload.confirmMsg,
4815 type: 'warning',
4816 showCancelButton: true,
4817 confirmButtonColor: '#d54e21',
4818 confirmButtonText: wpuf_frontend_upload.delete_it,
4819 cancelButtonText: wpuf_frontend_upload.cancel_it,
4820 confirmButtonClass: 'btn btn-success',
4821 cancelButtonClass: 'btn btn-danger',
4822 }).then(function () {
4823 var data = {
4824 'attach_id' : el.data('attach_id'),
4825 'nonce' : wpuf_frontend_upload.nonce,
4826 'action' : 'wpuf_file_del'
4827 };
4828 self.removed_files.push(data);
4829 jQuery('#del_attach').val(el.data('attach_id'));
4830 jQuery.post(wpuf_frontend_upload.ajaxurl, data, function() {
4831 self.perFileCount--;
4832 el.parent().parent().remove();
4833
4834 self.count -= 1;
4835 self.showHide();
4836 self.uploader.refresh();
4837 });
4838 });
4839 },
4840
4841 removeExtraAttachment : function( attach_id ) {
4842
4843
4844 var self = this;
4845
4846 var data = {
4847 'attach_id' : attach_id,
4848 'nonce' : wpuf_frontend_upload.nonce,
4849 'action' : 'wpuf_file_del'
4850 };
4851 this.removed_files.push(data);
4852 jQuery.post(wpuf_frontend_upload.ajaxurl, data, function() {
4853 self.count -= 1;
4854 self.showHide();
4855 self.uploader.refresh();
4856 });
4857 }
4858
4859 };
4860 })(jQuery);
4861