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

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