PluginProbe
weForms – Easy Drag & Drop Contact Form Builder For WordPress / 1.6.8
weForms – Easy Drag & Drop Contact Form Builder For WordPress v1.6.8
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.8, at assets/js/weforms.js

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