Contact Form by WPForms – Drag & Drop Form Builder for WordPress - Version 1.3.0

Version Description

[1.3.0] - 2016-10-07

Added

  • Added: Email field confirmantion
  • Added: Support for Visual Composer
  • Added: Field class to force elements to full-width on mobile devices, wpforms-mobile-full
  • Changed: Placeholders are added/updated in real-time for Dropdown fields in the form builder
  • Changed: Add empty value to select element placeholders when displaying form for better markup validation
  • Fixed: Multiple instances of reCAPTCHA on a page not correctly loading
  • Fixed: Field choice defaults not restoring in form builder
  • Fixed: Field alignment issues in the form builder when dragging field more than once
  • Fixed: PHP fatal erroring if form notification email address provided is not valid upon sending
  • Fixed: Compatibility issuses when network activated on a Multisite install
Download this release

Release Info

Developer jaredatch
Plugin Icon 128x128 Contact Form by WPForms – Drag & Drop Form Builder for WordPress
Version 1.3.0
Comparing to
See all releases

Code changes from version 1.2.9 to 1.3.0

assets/css/admin-builder-fields.css CHANGED
@@ -449,6 +449,7 @@
449
  margin-right: 2%;
450
  }
451
 
 
452
  #wpforms-panel-fields .wpforms-field-option-date-time .interval {
453
  float: left;
454
  width: 44%;
@@ -458,7 +459,8 @@
458
 
459
  #wpforms-panel-fields .wpforms-field-option-address .default select,
460
  #wpforms-panel-fields .wpforms-field-option-date-time .format select,
461
- #wpforms-panel-fields .wpforms-field-option-date-time .interval select {
 
462
  display: block;
463
  width: 100%;
464
  }
@@ -480,7 +482,17 @@
480
  #wpforms-panel-fields .wpforms-field-option-name .format-selected-simple .wpforms-field-option-row-last,
481
  #wpforms-panel-fields .wpforms-field-option-name .format-selected-first-last .wpforms-field-option-row-simple,
482
  #wpforms-panel-fields .wpforms-field-option-name .format-selected-first-last .wpforms-field-option-row-middle,
483
- #wpforms-panel-fields .wpforms-field-option-name .format-selected-first-middle-last .wpforms-field-option-row-simple {
 
 
 
 
 
 
 
 
 
 
484
  display: none;
485
  }
486
 
@@ -497,6 +509,13 @@
497
  display: inline-block;
498
  }
499
 
 
 
 
 
 
 
 
500
 
501
  /* Preview (right column)
502
  -------------------------------------------------------------- */
@@ -762,6 +781,7 @@
762
 
763
  #wpforms-panel-fields .wpforms-field .wpforms-sub-label {
764
  font-size: 12px;
 
765
  }
766
 
767
  #wpforms-panel-fields .wpforms-field.sublabel_hide .wpforms-sub-label {
@@ -896,10 +916,31 @@
896
  }
897
 
898
  #wpforms-panel-fields .wpforms-field-date-time .format-selected-date .wpforms-time,
899
- #wpforms-panel-fields .wpforms-field-date-time .format-selected-time .wpforms-date {
 
 
 
 
 
 
 
 
 
 
 
900
  display: none;
901
  }
902
 
 
 
 
 
 
 
 
 
 
 
903
  /* Page break field */
904
  #wpforms-panel-fields .wpforms-field-pagebreak .wpforms-pagebreak-buttons {
905
  text-align: center;
@@ -1144,8 +1185,46 @@
1144
  display: none;
1145
  }
1146
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1147
 
1148
  /* Choice input layouts */
 
1149
  #wpforms-panel-fields ul.primary-input {
1150
  margin-bottom: 0;
1151
  }
449
  margin-right: 2%;
450
  }
451
 
452
+ #wpforms-panel-fields .wpforms-field-option-date-time .type,
453
  #wpforms-panel-fields .wpforms-field-option-date-time .interval {
454
  float: left;
455
  width: 44%;
459
 
460
  #wpforms-panel-fields .wpforms-field-option-address .default select,
461
  #wpforms-panel-fields .wpforms-field-option-date-time .format select,
462
+ #wpforms-panel-fields .wpforms-field-option-date-time .interval select,
463
+ #wpforms-panel-fields .wpforms-field-option-date-time .type select {
464
  display: block;
465
  width: 100%;
466
  }
482
  #wpforms-panel-fields .wpforms-field-option-name .format-selected-simple .wpforms-field-option-row-last,
483
  #wpforms-panel-fields .wpforms-field-option-name .format-selected-first-last .wpforms-field-option-row-simple,
484
  #wpforms-panel-fields .wpforms-field-option-name .format-selected-first-last .wpforms-field-option-row-middle,
485
+ #wpforms-panel-fields .wpforms-field-option-name .format-selected-first-middle-last .wpforms-field-option-row-simple,
486
+ #wpforms-panel-fields .wpforms-field-option-date-time .format-selected-time .wpforms-field-option-row-date,
487
+ #wpforms-panel-fields .wpforms-field-option-date-time .format-selected-date .wpforms-field-option-row-time {
488
+ display: none;
489
+ }
490
+
491
+ #wpforms-panel-fields .wpforms-field-option-date-time.wpforms-date-type-dropdown option.datepicker-only {
492
+ display: none;
493
+ }
494
+
495
+ #wpforms-panel-fields .wpforms-field-option-date-time.wpforms-date-type-dropdown .wpforms-field-option-row-date .placeholder {
496
  display: none;
497
  }
498
 
509
  display: inline-block;
510
  }
511
 
512
+ /* Email/Password Confirmation */
513
+
514
+ #wpforms-panel-fields .wpforms-field-option.wpforms-confirm-disabled .wpforms-field-option-row-confirmation_placeholder,
515
+ #wpforms-panel-fields .wpforms-field-option.wpforms-confirm-disabled .wpforms-field-option-row-sublabel_hide {
516
+ display: none;
517
+ }
518
+
519
 
520
  /* Preview (right column)
521
  -------------------------------------------------------------- */
781
 
782
  #wpforms-panel-fields .wpforms-field .wpforms-sub-label {
783
  font-size: 12px;
784
+ display: block;
785
  }
786
 
787
  #wpforms-panel-fields .wpforms-field.sublabel_hide .wpforms-sub-label {
916
  }
917
 
918
  #wpforms-panel-fields .wpforms-field-date-time .format-selected-date .wpforms-time,
919
+ #wpforms-panel-fields .wpforms-field-date-time .format-selected-time .wpforms-date,
920
+ #wpforms-panel-fields .wpforms-field-date-time .format-selected-time .wpforms-sub-label,
921
+ #wpforms-panel-fields .wpforms-field-date-time .format-selected-date .wpforms-sub-label {
922
+ display: none;
923
+ }
924
+
925
+ #wpforms-panel-fields .wpforms-field-date-time .wpforms-date-dropdown select {
926
+ display: inline-block;
927
+ }
928
+
929
+ #wpforms-panel-fields .wpforms-field-date-time .wpforms-date-dropdown,
930
+ #wpforms-panel-fields .wpforms-field-date-time .wpforms-date-type-dropdown .wpforms-date-datepicker {
931
  display: none;
932
  }
933
 
934
+ #wpforms-panel-fields .wpforms-field-date-time .wpforms-date-type-dropdown .wpforms-date-dropdown,
935
+ #wpforms-panel-fields .wpforms-field-date-time .wpforms-date-type-datepicker .wpforms-date-datepicker {
936
+ display: block;
937
+ }
938
+
939
+ #wpforms-panel-fields .wpforms-field-date-time .wpforms-date-dropdown span {
940
+ display: inline-block;
941
+ padding:0 5px;
942
+ }
943
+
944
  /* Page break field */
945
  #wpforms-panel-fields .wpforms-field-pagebreak .wpforms-pagebreak-buttons {
946
  text-align: center;
1185
  display: none;
1186
  }
1187
 
1188
+ /* Email/Password confirmation */
1189
+
1190
+ #wpforms-panel-fields .wpforms-field .wpforms-confirm input[type=email],
1191
+ #wpforms-panel-fields .wpforms-field .wpforms-confirm input[type=email],
1192
+ #wpforms-panel-fields .wpforms-field .wpforms-confirm input[type=password],
1193
+ #wpforms-panel-fields .wpforms-field .wpforms-confirm input[type=password] {
1194
+ width: 100%;
1195
+ }
1196
+
1197
+ #wpforms-panel-fields .wpforms-field.size-large .wpforms-confirm {
1198
+ width: 100%;
1199
+ }
1200
+
1201
+ #wpforms-panel-fields .wpforms-field .wpforms-confirm,
1202
+ #wpforms-panel-fields .wpforms-field.size-medium .wpforms-confirm {
1203
+ width: 65%;
1204
+ }
1205
+
1206
+ #wpforms-panel-fields .wpforms-field.size-small .wpforms-confirm {
1207
+ width: 25%;
1208
+ }
1209
+
1210
+ #wpforms-panel-fields .wpforms-confirm-disabled .wpforms-confirm-confirmation,
1211
+ #wpforms-panel-fields .wpforms-confirm-disabled .wpforms-confirm-primary .wpforms-sub-label {
1212
+ display: none;
1213
+ }
1214
+
1215
+ #wpforms-panel-fields .wpforms-confirm-enabled .wpforms-confirm-primary {
1216
+ float: left;
1217
+ width: 48%;
1218
+ }
1219
+
1220
+ #wpforms-panel-fields .wpforms-confirm-enabled .wpforms-confirm-confirmation {
1221
+ float: right;
1222
+ width: 48%;
1223
+ }
1224
+
1225
 
1226
  /* Choice input layouts */
1227
+
1228
  #wpforms-panel-fields ul.primary-input {
1229
  margin-bottom: 0;
1230
  }
assets/css/admin-builder.css CHANGED
@@ -19,6 +19,7 @@ body {
19
  height: 100%;
20
  min-width: 0;
21
  cursor: default;
 
22
  }
23
 
24
  #wpforms-builder * {
19
  height: 100%;
20
  min-width: 0;
21
  cursor: default;
22
+ margin: 0 !important;
23
  }
24
 
25
  #wpforms-builder * {
assets/css/flatpickr.min.css ADDED
@@ -0,0 +1 @@
 
1
+ .flatpickr-input{cursor:pointer;z-index:1}.flatpickr-mobileInput{opacity:0;visibility:hidden;position:absolute;width:0;height:0;box-sizing:border-box;padding:0}.flatpickr-calendar{background:#fff;display:none;text-align:center;padding:0;border:1px solid #e6e6e6;font-size:14px;border-radius:3px;position:absolute;max-width:247px;min-width:200px}.flatpickr-calendar.open{opacity:1;z-index:99999;display:inline-block}.flatpickr-calendar.inline{display:table;margin-top:2px;position:relative}.flatpickr-calendar.static{position:relative}.flatpickr-calendar.static.open{display:block}.flatpickr-calendar.hasWeeks{max-width:300px}.flatpickr-calendar:after,.flatpickr-calendar:before{position:absolute;display:block;pointer-events:none;border:solid transparent;content:'';height:0;width:0;left:22px}.flatpickr-month,.flatpickr-next-month i,.flatpickr-prev-month i{position:relative}.flatpickr-calendar:before{border-width:5px;margin:0 -5px}.flatpickr-calendar:after{border-width:4px;margin:0 -4px}.flatpickr-calendar.arrowTop:after,.flatpickr-calendar.arrowTop:before{bottom:100%}.flatpickr-calendar.arrowTop:before{border-bottom-color:#e6e6e6}.flatpickr-calendar.arrowTop:after{border-bottom-color:#fff}.flatpickr-calendar.arrowBottom:after,.flatpickr-calendar.arrowBottom:before{top:100%}.flatpickr-calendar.arrowBottom:before{border-top-color:#e6e6e6}.flatpickr-calendar.arrowBottom:after{border-top-color:#fff}.flatpickr-month{background:0 0;color:rgba(0,0,0,.9);fill:rgba(0,0,0,.9);padding:4px 0 0;padding:0\9;text-align:center}.flatpickr-next-month,.flatpickr-prev-month{text-decoration:none;cursor:pointer}.flatpickr-next-month svg,.flatpickr-prev-month svg{width:14px;position:absolute;top:9px;top:0\9}.flatpickr-next-month svg path,.flatpickr-prev-month svg path{fill:inherit}.flatpickr-next-month svg:hover,.flatpickr-prev-month svg:hover{fill:#f99595}.flatpickr-next-month:hover,.flatpickr-prev-month:hover{color:#f99595}.flatpickr-prev-month svg{left:5px}.flatpickr-next-month svg{right:5px}.flatpickr-current-month{font-size:135%;font-weight:300;color:inherit;position:relative;display:inline-block;line-height:1}.flatpickr-current-month .cur-month{font-weight:700;color:inherit}.flatpickr-current-month .cur-year{background:0 0;box-sizing:border-box;color:inherit;cursor:default;padding:0;margin:0;width:3.2em;display:inline;font-size:inherit;font-weight:300;line-height:inherit;height:initial;border:0;border-radius:0;vertical-align:initial}.flatpickr-current-month .cur-year:hover{background:rgba(0,0,0,.05)}.flatpickr-weekdays{background:0 0;text-align:center;overflow:hidden}.flatpickr-days{padding-top:1px;outline:0;text-align:left}.flatpickr-day{background:0 0;border:1px solid transparent;border-radius:150px;box-sizing:border-box;color:#393939;cursor:pointer;display:inline-block;position:relative;font-weight:300;width:35px;height:35px;line-height:35px;margin:0;text-align:center;transition:50ms all ease-out}.flatpickr-day.inRange,.flatpickr-day.nextMonthDay.inRange,.flatpickr-day.nextMonthDay:focus,.flatpickr-day.nextMonthDay:hover,.flatpickr-day.prevMonthDay.inRange,.flatpickr-day.prevMonthDay:focus,.flatpickr-day.prevMonthDay:hover,.flatpickr-day:focus,.flatpickr-day:hover{cursor:pointer;outline:0;background:#e6e6e6;border-color:#e6e6e6}.flatpickr-day.today{border-color:#f99595}.flatpickr-day.today:focus,.flatpickr-day.today:hover{border-color:#f99595;background:#f99595;color:#fff}.flatpickr-day.selected,.flatpickr-day.selected:focus,.flatpickr-day.selected:hover{background:#446cb3;color:#fff;border-color:#446cb3}.flatpickr-day.disabled,.flatpickr-day.disabled:hover,.flatpickr-day.nextMonthDay,.flatpickr-day.notAllowed,.flatpickr-day.notAllowed.nextMonthDay,.flatpickr-day.notAllowed.prevMonthDay,.flatpickr-day.prevMonthDay{color:rgba(57,57,57,.3);background:0 0;border-color:transparent;cursor:default}span.flatpickr-weekday{cursor:default;font-size:90%;color:rgba(0,0,0,.54);height:24px;line-height:24px;margin:0;background:0 0;text-align:center;display:block;float:left;width:14.28%;font-weight:700}.flatpickr-weekwrapper{display:inline-block;float:left}.flatpickr-weekwrapper .flatpickr-weeks{padding:0 .25rem;border-right:1px solid #e6e6e6}.flatpickr-weekwrapper .flatpickr-weekday{float:none;width:100%}.flatpickr-weekwrapper span.flatpickr-day{display:block;width:100%}.flatpickr-rContainer{display:inline-block;max-width:247px}.flatpickr-time{overflow:auto;text-align:center;border-top:0;outline:0;display:block;display:flex}.flatpickr-am-pm,.flatpickr-time input,.flatpickr-time-separator{height:38px;display:inline-block;line-height:38px;color:#393939}.flatpickr-time input{-moz-appearance:textfield;background:0 0;box-shadow:none;border:0;border-radius:0;flex:1;width:33%;min-width:33%;text-align:center;margin:0;padding:0;cursor:pointer;font-weight:700}.flatpickr-time input.flatpickr-minute{width:26%;font-weight:300}.flatpickr-time input.flatpickr-second{font-weight:300}.flatpickr-time input:focus{outline:0;border:0}.flatpickr-time input:focus,.flatpickr-time input:hover{-moz-appearance:number-input;background:#e6e6e6}.flatpickr-time.has-seconds input[type=number]{width:25%;min-width:25%}.hasTime .flatpickr-days,.hasWeeks .flatpickr-days{border-bottom:0;border-bottom-right-radius:0;border-bottom-left-radius:0}.hasWeeks .flatpickr-days{border-left:0}.flatpickr-rContainer+.flatpickr-time{border-top:1px solid #e6e6e6}.flatpickr-am-pm{outline:0;width:21%;padding:0 2%;cursor:pointer;text-align:left;font-weight:300}.flatpickr-am-pm:focus,.flatpickr-am-pm:hover{background:#f0f0f0}@media all and (-ms-high-contrast:none){.flatpickr-month{padding:0}.flatpickr-month svg{top:0!important}}
assets/css/jquery.timepicker.css ADDED
@@ -0,0 +1,71 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ .ui-timepicker-wrapper {
2
+ overflow-y: auto;
3
+ height: 142px;
4
+ width: 6.5em;
5
+ background: #fff;
6
+ border: 1px solid #e6e6e6;
7
+ border-radius: 3px;
8
+ outline: none;
9
+ z-index: 10001;
10
+ margin: 0;
11
+ }
12
+
13
+ .ui-timepicker-wrapper.ui-timepicker-with-duration {
14
+ width: 13em;
15
+ }
16
+
17
+ .ui-timepicker-wrapper.ui-timepicker-with-duration.ui-timepicker-step-30,
18
+ .ui-timepicker-wrapper.ui-timepicker-with-duration.ui-timepicker-step-60 {
19
+ width: 11em;
20
+ }
21
+
22
+ .ui-timepicker-list {
23
+ margin: 0;
24
+ padding: 0;
25
+ list-style: none;
26
+ }
27
+
28
+ .ui-timepicker-duration {
29
+ margin-left: 5px; color: #888;
30
+ }
31
+
32
+ .ui-timepicker-list:hover .ui-timepicker-duration {
33
+ color: #888;
34
+ }
35
+
36
+ .ui-timepicker-list li {
37
+ padding: 3px 0 3px 5px;
38
+ cursor: pointer;
39
+ white-space: nowrap;
40
+ color: #393939;
41
+ list-style: none;
42
+ margin: 0;
43
+ font-size: 14px;
44
+ }
45
+
46
+ .ui-timepicker-list:hover .ui-timepicker-selected {
47
+ background: #fff; color: #393939;
48
+ }
49
+
50
+ li.ui-timepicker-selected,
51
+ .ui-timepicker-list li:hover,
52
+ .ui-timepicker-list .ui-timepicker-selected:hover {
53
+ background: #446cb3; color: #fff;
54
+ }
55
+
56
+ li.ui-timepicker-selected .ui-timepicker-duration,
57
+ .ui-timepicker-list li:hover .ui-timepicker-duration {
58
+ color: #ccc;
59
+ }
60
+
61
+ .ui-timepicker-list li.ui-timepicker-disabled,
62
+ .ui-timepicker-list li.ui-timepicker-disabled:hover,
63
+ .ui-timepicker-list li.ui-timepicker-selected.ui-timepicker-disabled {
64
+ color: #888;
65
+ cursor: default;
66
+ }
67
+
68
+ .ui-timepicker-list li.ui-timepicker-disabled:hover,
69
+ .ui-timepicker-list li.ui-timepicker-selected.ui-timepicker-disabled {
70
+ background: #f2f2f2;
71
+ }
assets/css/pickadate.classic.css DELETED
@@ -1,99 +0,0 @@
1
- /* ==========================================================================
2
- $BASE-PICKER
3
- ========================================================================== */
4
- /**
5
- * Note: the root picker element should *NOT* be styled more than what’s here.
6
- */
7
- div.wpforms-container .wpforms-form .picker {
8
- font-size: 16px;
9
- text-align: left;
10
- line-height: 1.2;
11
- color: #000000;
12
- position: absolute;
13
- z-index: 10000;
14
- -webkit-user-select: none;
15
- -moz-user-select: none;
16
- -ms-user-select: none;
17
- user-select: none;
18
- }
19
- /**
20
- * The picker input element.
21
- */
22
- div.wpforms-container .wpforms-form .picker__input {
23
- cursor: default;
24
- }
25
- /**
26
- * When the picker is opened, the input element is “activated”.
27
- */
28
- div.wpforms-container .wpforms-form .picker__input.picker__input--active {
29
- border-color: #0089ec;
30
- }
31
- /**
32
- * The holder is the only “scrollable” top-level container element.
33
- */
34
- div.wpforms-container .wpforms-form .picker__holder {
35
- width: 100%;
36
- overflow-y: auto;
37
- -webkit-overflow-scrolling: touch;
38
- }
39
-
40
- /*!
41
- * Classic picker styling for pickadate.js
42
- * Demo: http://amsul.github.io/pickadate.js
43
- */
44
- /**
45
- * Note: the root picker element should *NOT* be styled more than what’s here.
46
- */
47
- div.wpforms-container .wpforms-form .picker {
48
- width: 100%;
49
- }
50
- /**
51
- * The holder is the base of the picker.
52
- */
53
- div.wpforms-container .wpforms-form .picker__holder {
54
- position: absolute;
55
- background: #ffffff;
56
- border: 1px solid #aaaaaa;
57
- border-top-width: 0;
58
- border-bottom-width: 0;
59
- border-radius: 0 0 5px 5px;
60
- box-sizing: border-box;
61
- min-width: 176px;
62
- max-width: 466px;
63
- max-height: 0;
64
- -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=0)";
65
- filter: alpha(opacity=0);
66
- -moz-opacity: 0;
67
- opacity: 0;
68
- -webkit-transform: translateY(-1em) perspective(600px) rotateX(10deg);
69
- transform: translateY(-1em) perspective(600px) rotateX(10deg);
70
- transition: -webkit-transform 0.15s ease-out, opacity 0.15s ease-out, max-height 0s 0.15s, border-width 0s 0.15s;
71
- transition: transform 0.15s ease-out, opacity 0.15s ease-out, max-height 0s 0.15s, border-width 0s 0.15s;
72
- }
73
- /**
74
- * The frame and wrap work together to ensure that
75
- * clicks within the picker don’t reach the holder.
76
- */
77
- div.wpforms-container .wpforms-form .picker__frame {
78
- padding: 1px;
79
- }
80
- div.wpforms-container .wpforms-form .picker__wrap {
81
- margin: -1px;
82
- }
83
- /**
84
- * When the picker opens...
85
- */
86
- div.wpforms-container .wpforms-form .picker--opened .picker__holder {
87
- max-height: 25em;
88
- -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=100)";
89
- filter: alpha(opacity=100);
90
- -moz-opacity: 1;
91
- opacity: 1;
92
- border-top-width: 1px;
93
- border-bottom-width: 1px;
94
- -webkit-transform: translateY(0) perspective(600px) rotateX(0);
95
- transform: translateY(0) perspective(600px) rotateX(0);
96
- transition: -webkit-transform 0.15s ease-out, opacity 0.15s ease-out, max-height 0s, border-width 0s;
97
- transition: transform 0.15s ease-out, opacity 0.15s ease-out, max-height 0s, border-width 0s;
98
- box-shadow: 0 6px 18px 1px rgba(0, 0, 0, 0.12);
99
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
assets/css/pickadate.classic.date.css DELETED
@@ -1,302 +0,0 @@
1
- /* ==========================================================================
2
- $BASE-DATE-PICKER
3
- ========================================================================== */
4
- /**
5
- * The picker box.
6
- */
7
- div.wpforms-container .wpforms-form .picker__box {
8
- padding: 0 1em;
9
- }
10
- /**
11
- * The header containing the month and year stuff.
12
- */
13
- div.wpforms-container .wpforms-form .picker__header {
14
- text-align: center;
15
- position: relative;
16
- margin-top: .75em;
17
- }
18
- /**
19
- * The month and year labels.
20
- */
21
- div.wpforms-container .wpforms-form .picker__month,
22
- div.wpforms-container .wpforms-form .picker__year {
23
- font-weight: 500;
24
- display: inline-block;
25
- margin-left: .25em;
26
- margin-right: .25em;
27
- }
28
- div.wpforms-container .wpforms-form .picker__year {
29
- color: #999999;
30
- font-size: .8em;
31
- font-style: italic;
32
- }
33
- /**
34
- * The month and year selectors.
35
- */
36
- div.wpforms-container .wpforms-form select.picker__select--month,
37
- div.wpforms-container .wpforms-form select.picker__select--year {
38
- border: 1px solid #b7b7b7;
39
- height: 2em;
40
- padding: .5em;
41
- margin-left: .25em;
42
- margin-right: .25em;
43
- display: inline-block;
44
- }
45
- @media (min-width: 24.5em) {
46
- div.wpforms-container .wpforms-form select.picker__select--month,
47
- div.wpforms-container .wpforms-form select.picker__select--year {
48
- margin-top: -0.5em;
49
- }
50
- }
51
- div.wpforms-container .wpforms-form select.picker__select--month {
52
- width: 35%;
53
- }
54
- div.wpforms-container .wpforms-form select.picker__select--year {
55
- width: 22.5%;
56
- }
57
- div.wpforms-container .wpforms-form select.picker__select--month:focus,
58
- div.wpforms-container .wpforms-form select.picker__select--year:focus {
59
- border-color: #0089ec;
60
- }
61
- /**
62
- * The month navigation buttons.
63
- */
64
- div.wpforms-container .wpforms-form .picker__nav--prev,
65
- div.wpforms-container .wpforms-form .picker__nav--next {
66
- position: absolute;
67
- padding: .5em 1.25em;
68
- width: 1em;
69
- height: 1em;
70
- box-sizing: content-box;
71
- top: -0.25em;
72
- }
73
- @media (min-width: 24.5em) {
74
- div.wpforms-container .wpforms-form .picker__nav--prev,
75
- div.wpforms-container .wpforms-form .picker__nav--next {
76
- top: -0.33em;
77
- }
78
- }
79
- div.wpforms-container .wpforms-form .picker__nav--prev {
80
- left: -1em;
81
- padding-right: 1.25em;
82
- }
83
- @media (min-width: 24.5em) {
84
- div.wpforms-container .wpforms-form .picker__nav--prev {
85
- padding-right: 1.5em;
86
- }
87
- }
88
- div.wpforms-container .wpforms-form .picker__nav--next {
89
- right: -1em;
90
- padding-left: 1.25em;
91
- }
92
- @media (min-width: 24.5em) {
93
- div.wpforms-container .wpforms-form .picker__nav--next {
94
- padding-left: 1.5em;
95
- }
96
- }
97
- div.wpforms-container .wpforms-form .picker__nav--prev:before,
98
- div.wpforms-container .wpforms-form .picker__nav--next:before {
99
- content: " ";
100
- border-top: .5em solid transparent;
101
- border-bottom: .5em solid transparent;
102
- border-right: 0.75em solid #000000;
103
- width: 0;
104
- height: 0;
105
- display: block;
106
- margin: 0 auto;
107
- }
108
- div.wpforms-container .wpforms-form .picker__nav--next:before {
109
- border-right: 0;
110
- border-left: 0.75em solid #000000;
111
- }
112
- div.wpforms-container .wpforms-form .picker__nav--prev:hover,
113
- div.wpforms-container .wpforms-form .picker__nav--next:hover {
114
- cursor: pointer;
115
- color: #000000;
116
- background: #b1dcfb;
117
- }
118
- div.wpforms-container .wpforms-form .picker__nav--disabled,
119
- div.wpforms-container .wpforms-form .picker__nav--disabled:hover,
120
- div.wpforms-container .wpforms-form .picker__nav--disabled:before,
121
- div.wpforms-container .wpforms-form .picker__nav--disabled:before:hover {
122
- cursor: default;
123
- background: none;
124
- border-right-color: #f5f5f5;
125
- border-left-color: #f5f5f5;
126
- }
127
- /**
128
- * The calendar table of dates
129
- */
130
- div.wpforms-container .wpforms-form .picker__table {
131
- text-align: center;
132
- border-collapse: collapse;
133
- border-spacing: 0;
134
- table-layout: fixed;
135
- font-size: inherit;
136
- width: 100%;
137
- margin-top: .75em;
138
- margin-bottom: .5em;
139
- }
140
- @media (min-height: 33.875em) {
141
- div.wpforms-container .wpforms-form .picker__table {
142
- margin-bottom: .75em;
143
- }
144
- }
145
- div.wpforms-container .wpforms-form .picker__table td {
146
- margin: 0;
147
- padding: 0;
148
- }
149
- /**
150
- * The weekday labels
151
- */
152
- div.wpforms-container .wpforms-form .picker__weekday {
153
- width: 14.285714286%;
154
- font-size: .75em;
155
- padding-bottom: .25em;
156
- color: #999999;
157
- font-weight: 500;
158
- /* Increase the spacing a tad */
159
- }
160
- @media (min-height: 33.875em) {
161
- div.wpforms-container .wpforms-form .picker__weekday {
162
- padding-bottom: .5em;
163
- }
164
- }
165
- /**
166
- * The days on the calendar
167
- */
168
- div.wpforms-container .wpforms-form .picker__day {
169
- padding: .3125em 0;
170
- font-weight: 200;
171
- border: 1px solid transparent;
172
- }
173
- div.wpforms-container .wpforms-form .picker__day--today {
174
- position: relative;
175
- }
176
- div.wpforms-container .wpforms-form .picker__day--today:before {
177
- content: " ";
178
- position: absolute;
179
- top: 2px;
180
- right: 2px;
181
- width: 0;
182
- height: 0;
183
- border-top: 0.5em solid #0059bc;
184
- border-left: .5em solid transparent;
185
- }
186
- div.wpforms-container .wpforms-form .picker__day--disabled:before {
187
- border-top-color: #aaaaaa;
188
- }
189
- div.wpforms-container .wpforms-form .picker__day--outfocus {
190
- color: #dddddd;
191
- }
192
- div.wpforms-container .wpforms-form .picker__day--infocus:hover,
193
- div.wpforms-container .wpforms-form .picker__day--outfocus:hover {
194
- cursor: pointer;
195
- color: #000000;
196
- background: #b1dcfb;
197
- }
198
- div.wpforms-container .wpforms-form .picker__day--highlighted {
199
- border-color: #0089ec;
200
- }
201
- div.wpforms-container .wpforms-form .picker__day--highlighted:hover,
202
- div.wpforms-container .wpforms-form .picker--focused .picker__day--highlighted {
203
- cursor: pointer;
204
- color: #000000;
205
- background: #b1dcfb;
206
- }
207
- div.wpforms-container .wpforms-form .picker__day--selected,
208
- div.wpforms-container .wpforms-form .picker__day--selected:hover,
209
- div.wpforms-container .wpforms-form .picker--focused .picker__day--selected {
210
- background: #0089ec;
211
- color: #ffffff;
212
- }
213
- div.wpforms-container .wpforms-form .picker__day--disabled,
214
- div.wpforms-container .wpforms-form .picker__day--disabled:hover,
215
- div.wpforms-container .wpforms-form .picker--focused .picker__day--disabled {
216
- background: #f5f5f5;
217
- border-color: #f5f5f5;
218
- color: #dddddd;
219
- cursor: default;
220
- }
221
- div.wpforms-container .wpforms-form .picker__day--highlighted.picker__day--disabled,
222
- div.wpforms-container .wpforms-form .picker__day--highlighted.picker__day--disabled:hover {
223
- background: #bbbbbb;
224
- }
225
- /**
226
- * The footer containing the "today", "clear", and "close" buttons.
227
- */
228
- div.wpforms-container .wpforms-form .picker__footer {
229
- text-align: center;
230
- }
231
- div.wpforms-container .wpforms-form .picker__button--today,
232
- div.wpforms-container .wpforms-form .picker__button--clear,
233
- div.wpforms-container .wpforms-form .picker__button--close {
234
- border: 1px solid #ffffff;
235
- background: #ffffff;
236
- font-size: .8em;
237
- padding: .66em 0;
238
- font-weight: bold;
239
- width: 33%;
240
- display: inline-block;
241
- vertical-align: bottom;
242
- }
243
- div.wpforms-container .wpforms-form .picker__button--today:hover,
244
- div.wpforms-container .wpforms-form .picker__button--clear:hover,
245
- div.wpforms-container .wpforms-form .picker__button--close:hover {
246
- cursor: pointer;
247
- color: #000000;
248
- background: #b1dcfb;
249
- border-bottom-color: #b1dcfb;
250
- }
251
- div.wpforms-container .wpforms-form .picker__button--today:focus,
252
- div.wpforms-container .wpforms-form .picker__button--clear:focus,
253
- div.wpforms-container .wpforms-form .picker__button--close:focus {
254
- background: #b1dcfb;
255
- border-color: #0089ec;
256
- outline: none;
257
- }
258
- div.wpforms-container .wpforms-form .picker__button--today:before,
259
- div.wpforms-container .wpforms-form .picker__button--clear:before,
260
- div.wpforms-container .wpforms-form .picker__button--close:before {
261
- position: relative;
262
- display: inline-block;
263
- height: 0;
264
- }
265
- div.wpforms-container .wpforms-form .picker__button--today:before,
266
- div.wpforms-container .wpforms-form .picker__button--clear:before {
267
- content: " ";
268
- margin-right: .45em;
269
- }
270
- div.wpforms-container .wpforms-form .picker__button--today:before {
271
- top: -0.05em;
272
- width: 0;
273
- border-top: 0.66em solid #0059bc;
274
- border-left: .66em solid transparent;
275
- }
276
- div.wpforms-container .wpforms-form .picker__button--clear:before {
277
- top: -0.25em;
278
- width: .66em;
279
- border-top: 3px solid #ee2200;
280
- }
281
- div.wpforms-container .wpforms-form .picker__button--close:before {
282
- content: "\D7";
283
- top: -0.1em;
284
- vertical-align: top;
285
- font-size: 1.1em;
286
- margin-right: .35em;
287
- color: #777777;
288
- }
289
- div.wpforms-container .wpforms-form .picker__button--today[disabled],
290
- div.wpforms-container .wpforms-form .picker__button--today[disabled]:hover {
291
- background: #f5f5f5;
292
- border-color: #f5f5f5;
293
- color: #dddddd;
294
- cursor: default;
295
- }
296
- div.wpforms-container .wpforms-form .picker__button--today[disabled]:before {
297
- border-top-color: #aaaaaa;
298
- }
299
-
300
- /* ==========================================================================
301
- $CLASSIC-DATE-PICKER
302
- ========================================================================== */
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
assets/css/pickadate.classic.time.css DELETED
@@ -1,132 +0,0 @@
1
- /* ==========================================================================
2
- $BASE-TIME-PICKER
3
- ========================================================================== */
4
- /**
5
- * The list of times.
6
- */
7
- div.wpforms-container .wpforms-form .picker__list {
8
- list-style: none;
9
- padding: 0.75em 0 4.2em;
10
- margin: 0;
11
- }
12
- /**
13
- * The times on the clock.
14
- */
15
- div.wpforms-container .wpforms-form .picker__list-item {
16
- border-bottom: 1px solid #dddddd;
17
- border-top: 1px solid #dddddd;
18
- margin-bottom: -1px;
19
- position: relative;
20
- background: #ffffff;
21
- padding: .75em 1.25em;
22
- }
23
- @media (min-height: 46.75em) {
24
- div.wpforms-container .wpforms-form .picker__list-item {
25
- padding: .5em 1em;
26
- }
27
- }
28
- /* Hovered time */
29
- div.wpforms-container .wpforms-form .picker__list-item:hover {
30
- cursor: pointer;
31
- color: #000000;
32
- background: #b1dcfb;
33
- border-color: #0089ec;
34
- z-index: 10;
35
- }
36
- /* Highlighted and hovered/focused time */
37
- div.wpforms-container .wpforms-form .picker__list-item--highlighted {
38
- border-color: #0089ec;
39
- z-index: 10;
40
- }
41
- div.wpforms-container .wpforms-form .picker__list-item--highlighted:hover,
42
- div.wpforms-container .wpforms-form .picker--focused .picker__list-item--highlighted {
43
- cursor: pointer;
44
- color: #000000;
45
- background: #b1dcfb;
46
- }
47
- /* Selected and hovered/focused time */
48
- div.wpforms-container .wpforms-form .picker__list-item--selected,
49
- div.wpforms-container .wpforms-form .picker__list-item--selected:hover,
50
- div.wpforms-container .wpforms-form .picker--focused .picker__list-item--selected {
51
- background: #0089ec;
52
- color: #ffffff;
53
- z-index: 10;
54
- }
55
- /* Disabled time */
56
- div.wpforms-container .wpforms-form .picker__list-item--disabled,
57
- div.wpforms-container .wpforms-form .picker__list-item--disabled:hover,
58
- div.wpforms-container .wpforms-form .picker--focused .picker__list-item--disabled {
59
- background: #f5f5f5;
60
- border-color: #f5f5f5;
61
- color: #dddddd;
62
- cursor: default;
63
- border-color: #dddddd;
64
- z-index: auto;
65
- }
66
- /**
67
- * The clear button
68
- */
69
- div.wpforms-container .wpforms-form .picker--time .picker__button--clear {
70
- display: block;
71
- width: 80%;
72
- margin: 1em auto 0;
73
- padding: 1em 1.25em;
74
- background: none;
75
- border: 0;
76
- font-weight: 500;
77
- font-size: .67em;
78
- text-align: center;
79
- text-transform: uppercase;
80
- color: #666;
81
- }
82
- div.wpforms-container .wpforms-form .picker--time .picker__button--clear:hover,
83
- div.wpforms-container .wpforms-form .picker--time .picker__button--clear:focus {
84
- color: #000000;
85
- background: #b1dcfb;
86
- background: #ee2200;
87
- border-color: #ee2200;
88
- cursor: pointer;
89
- color: #ffffff;
90
- outline: none;
91
- }
92
- div.wpforms-container .wpforms-form .picker--time .picker__button--clear:before {
93
- top: -0.25em;
94
- color: #666;
95
- font-size: 1.25em;
96
- font-weight: bold;
97
- }
98
- div.wpforms-container .wpforms-form .picker--time .picker__button--clear:hover:before,
99
- div.wpforms-container .wpforms-form .picker--time .picker__button--clear:focus:before {
100
- color: #ffffff;
101
- border-color: #ffffff;
102
- }
103
-
104
- /* ==========================================================================
105
- $CLASSIC-TIME-PICKER
106
- ========================================================================== */
107
- /**
108
- * Note: the root picker element should __NOT__ be styled
109
- * more than what’s here. Style the `.picker__holder` instead.
110
- */
111
- div.wpforms-container .wpforms-form .picker--time {
112
- min-width: 256px;
113
- max-width: 320px;
114
- }
115
- /**
116
- * The holder is the base of the picker.
117
- */
118
- div.wpforms-container .wpforms-form .picker--time .picker__holder {
119
- background: #f2f2f2;
120
- }
121
- @media (min-height: 40.125em) {
122
- div.wpforms-container .wpforms-form .picker--time .picker__holder {
123
- font-size: .875em;
124
- }
125
- }
126
- /**
127
- * The box contains the list of times.
128
- */
129
- div.wpforms-container .wpforms-form .picker--time .picker__box {
130
- padding: 0;
131
- position: relative;
132
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
assets/css/wpforms-base.css CHANGED
@@ -376,8 +376,16 @@
376
  /* Date/time field
377
  ----------------------------------------------------------------------------- */
378
 
379
- .wpforms-container .wpforms-form .wpforms-datepicker-wrap {
380
- position: relative;
 
 
 
 
 
 
 
 
381
  }
382
 
383
 
@@ -503,6 +511,13 @@
503
  /* Small devices */
504
  @media only screen and (max-width: 600px) {
505
 
 
 
 
 
 
 
 
506
  /* Full width for all sizes */
507
  .wpforms-container input.wpforms-field-medium,
508
  .wpforms-container select.wpforms-field-medium,
376
  /* Date/time field
377
  ----------------------------------------------------------------------------- */
378
 
379
+ .wpforms-container .wpforms-field-date-time-date-sep {
380
+ display:inline-block;
381
+ padding:0 5px;
382
+ }
383
+
384
+ .wpforms-container .wpforms-field-date-time-date-year,
385
+ .wpforms-container .wpforms-field-date-time-date-day,
386
+ .wpforms-container .wpforms-field-date-time-date-month {
387
+ display:inline-block;
388
+ width:auto;
389
  }
390
 
391
 
511
  /* Small devices */
512
  @media only screen and (max-width: 600px) {
513
 
514
+ /* Mobile width override */
515
+ .wpforms-container .wpforms-mobile-full {
516
+ width: 100%;
517
+ margin-left: 0;
518
+ float: none;
519
+ }
520
+
521
  /* Full width for all sizes */
522
  .wpforms-container input.wpforms-field-medium,
523
  .wpforms-container select.wpforms-field-medium,
assets/css/wpforms-full.css CHANGED
@@ -600,8 +600,16 @@ div.wpforms-container-full .wpforms-form .wpforms-field-credit-card-expiration s
600
  /* Date/time field
601
  ----------------------------------------------------------------------------- */
602
 
603
- div.wpforms-container-full .wpforms-form .wpforms-datepicker-wrap {
604
- position: relative;
 
 
 
 
 
 
 
 
605
  }
606
 
607
 
@@ -751,6 +759,13 @@ div.wpforms-container-full .wpforms-form .wpforms-field-hidden {
751
  /* Small devices */
752
  @media only screen and (max-width: 600px) {
753
 
 
 
 
 
 
 
 
754
  /* Full width for all sizes */
755
  div.wpforms-container-full .wpforms-form input.wpforms-field-medium,
756
  div.wpforms-container-full .wpforms-form select.wpforms-field-medium,
600
  /* Date/time field
601
  ----------------------------------------------------------------------------- */
602
 
603
+ div.wpforms-container-full .wpforms-field-date-time-date-sep {
604
+ display:inline-block;
605
+ padding:0 5px;
606
+ }
607
+
608
+ div.wpforms-container-full .wpforms-form .wpforms-field-date-time-date-year,
609
+ div.wpforms-container-full .wpforms-form .wpforms-field-date-time-date-day,
610
+ div.wpforms-container-full .wpforms-form .wpforms-field-date-time-date-month {
611
+ display:inline-block;
612
+ width:auto;
613
  }
614
 
615
 
759
  /* Small devices */
760
  @media only screen and (max-width: 600px) {
761
 
762
+ /* Mobile width override */
763
+ div.wpforms-container-full .wpforms-form .wpforms-mobile-full {
764
+ width: 100%;
765
+ margin-left: 0;
766
+ float: none;
767
+ }
768
+
769
  /* Full width for all sizes */
770
  div.wpforms-container-full .wpforms-form input.wpforms-field-medium,
771
  div.wpforms-container-full .wpforms-form select.wpforms-field-medium,
assets/images/sullie-vc.png ADDED
Binary file
assets/js/admin-builder.js CHANGED
@@ -652,6 +652,13 @@
652
  $('#wpforms-field-'+id).toggleClass('required');
653
  });
654
 
 
 
 
 
 
 
 
655
  // Real-time updates for "Size" field option
656
  $(document).on('change', '.wpforms-field-option-row-size select', function(e) {
657
  var $this = $(this),
@@ -662,10 +669,32 @@
662
 
663
  // Real-time updates for "Placeholder" field option
664
  $(document).on('input', '.wpforms-field-option-row-placeholder input', function(e) {
665
- var $this = $(this),
666
- value = $this.val(),
667
- id = $this.parent().data('field-id');
668
- $('#wpforms-field-'+id).find('.primary-input').attr('placeholder', value);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
669
  });
670
 
671
  // Real-time updates for "Hide Label" field option
@@ -713,6 +742,29 @@
713
  $('#wpforms-field-'+id).find('.wpforms-'+ subfield+' input' ).attr('placeholder', value);
714
  });
715
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
716
  // Consider the field active when a disabled nav button is clicked
717
  $(document).on('click', '.wpforms-pagebreak-button', function(e) {
718
  e.preventDefault();
@@ -1171,9 +1223,14 @@
1171
  if ( !fieldReceived ) {
1172
  var width = $el.attr('data-original-width');
1173
  if ( $el.hasClass('wpforms-field-drag')){
1174
- $el.addClass('wpforms-field-drag-out').removeClass('wpforms-field-drag-over').css('width', width);
1175
  }
1176
  }
 
 
 
 
 
1177
  },
1178
  receive: function(e, ui) {
1179
  fieldReceived = true;
652
  $('#wpforms-field-'+id).toggleClass('required');
653
  });
654
 
655
+ // Real-time updates for "Confirmation" field option
656
+ $(document).on('change', '.wpforms-field-option-row-confirmation input', function(e) {
657
+ var id = $(this).parent().data('field-id');
658
+ $('#wpforms-field-'+id).find('.wpforms-confirm').toggleClass('wpforms-confirm-enabled wpforms-confirm-disabled');
659
+ $('#wpforms-field-option-'+id).toggleClass('wpforms-confirm-enabled wpforms-confirm-disabled');
660
+ });
661
+
662
  // Real-time updates for "Size" field option
663
  $(document).on('change', '.wpforms-field-option-row-size select', function(e) {
664
  var $this = $(this),
669
 
670
  // Real-time updates for "Placeholder" field option
671
  $(document).on('input', '.wpforms-field-option-row-placeholder input', function(e) {
672
+ var $this = $(this),
673
+ value = $this.val(),
674
+ id = $this.parent().data('field-id'),
675
+ $primary = $('#wpforms-field-'+id).find('.primary-input');
676
+
677
+ if ($primary.is('select')) {
678
+ if (!value.length) {
679
+ $primary.find('.placeholder').remove();
680
+ } else {
681
+ if ($primary.find('.placeholder').length) {
682
+ $primary.find('.placeholder').text(value);
683
+ } else {
684
+ $primary.prepend('<option class="placeholder" selected>'+value+'</option>')
685
+ }
686
+ }
687
+ } else {
688
+ $primary.attr('placeholder', value);
689
+ }
690
+ });
691
+
692
+ // Real-time updates for "Confirmation Placeholder" field option
693
+ $(document).on('input', '.wpforms-field-option-row-confirmation_placeholder input', function(e) {
694
+ var $this = $(this),
695
+ value = $this.val(),
696
+ id = $this.parent().data('field-id');
697
+ $('#wpforms-field-'+id).find('.secondary-input').attr('placeholder', value);
698
  });
699
 
700
  // Real-time updates for "Hide Label" field option
742
  $('#wpforms-field-'+id).find('.wpforms-'+ subfield+' input' ).attr('placeholder', value);
743
  });
744
 
745
+ // Real-time updates for Date/Time date type
746
+ $(document).on('change', '.wpforms-field-option-row-date .type select', function(e) {
747
+ var $this = $(this),
748
+ value = $this.val(),
749
+ id = $(this).parent().parent().data('field-id');
750
+ $('#wpforms-field-'+id).find('.wpforms-date').toggleClass('wpforms-date-type-datepicker wpforms-date-type-dropdown');
751
+ $('#wpforms-field-option-'+id).toggleClass('wpforms-date-type-datepicker wpforms-date-type-dropdown');
752
+ });
753
+
754
+ // Real-time updates for Date/Time date select format
755
+ $(document).on('change', '.wpforms-field-option-row-date .format select', function(e) {
756
+ var $this = $(this),
757
+ value = $this.val(),
758
+ id = $(this).parent().parent().data('field-id');
759
+ if ( value === 'm/d/Y' ) {
760
+ $('#wpforms-field-'+id).find('.wpforms-date-dropdown .first option').text(wpforms_builder.date_select_month);
761
+ $('#wpforms-field-'+id).find('.wpforms-date-dropdown .second option').text(wpforms_builder.date_select_day);
762
+ } else if ( value == 'd/m/Y' ) {
763
+ $('#wpforms-field-'+id).find('.wpforms-date-dropdown .first option').text(wpforms_builder.date_select_day);
764
+ $('#wpforms-field-'+id).find('.wpforms-date-dropdown .second option').text(wpforms_builder.date_select_month);
765
+ }
766
+ });
767
+
768
  // Consider the field active when a disabled nav button is clicked
769
  $(document).on('click', '.wpforms-pagebreak-button', function(e) {
770
  e.preventDefault();
1223
  if ( !fieldReceived ) {
1224
  var width = $el.attr('data-original-width');
1225
  if ( $el.hasClass('wpforms-field-drag')){
1226
+ $el.addClass('wpforms-field-drag-out').removeClass('wpforms-field-drag-over').css('width', width).css('left', '').css('top', '');
1227
  }
1228
  }
1229
+ $el.css({
1230
+ 'top': '',
1231
+ 'left': '',
1232
+ 'z-index': ''
1233
+ });
1234
  },
1235
  receive: function(e, ui) {
1236
  fieldReceived = true;
assets/js/flatpickr.min.js ADDED
@@ -0,0 +1,2 @@
 
 
1
+ /*! flatpickr v2.0, @license MIT */
2
+ function Flatpickr(e,t){function n(){$.element=e,$.instanceConfig=t||{},O(),x(),R(),S(),A(),$.isOpen=$.config.inline,$.changeMonth=p,$.clear=f,$.close=m,$.destroy=g,$.formatDate=v,$.jumpToDate=i,$.open=M,$.parseDate=I,$.redraw=L,$.set=F,$.setDate=N,$.toggle=_,$.isMobile=!$.config.disableMobile&&"single"===$.config.mode&&!$.config.disable.length&&!$.config.enable.length&&/Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent),$.isMobile||o(),r(),$.selectedDates.length&&z(),j("Ready")}function a(e){$.config.noCalendar&&!$.selectedDates.length&&($.selectedDates=[$.now]),Q(e),z()}function r(){return $.config.wrap&&["open","close","toggle","clear"].forEach(function(e){try{$.element.querySelector("[data-"+e+"]").addEventListener("click",$[e])}catch(e){}}),"createEvent"in document&&($.changeEvent=document.createEvent("HTMLEvents"),$.changeEvent.initEvent("change",!1,!0)),$.isMobile?H():($.debouncedResize=q(C,100),$.triggerChange=function(){return j("Change")},$.debouncedChange=q($.triggerChange,1e3),"range"===$.config.mode&&$.days.addEventListener("mouseover",w),document.addEventListener("keydown",b),window.addEventListener("resize",$.debouncedResize),document.addEventListener("click",h),document.addEventListener("blur",h),$.config.clickOpens&&($.altInput||$.input).addEventListener("focus",M),$.config.noCalendar||($.prevMonthNav.addEventListener("click",function(){return p(-1)}),$.nextMonthNav.addEventListener("click",function(){return p(1)}),$.currentYearElement.addEventListener("wheel",J),$.currentYearElement.addEventListener("focus",function(){$.currentYearElement.select()}),$.currentYearElement.addEventListener("input",function(e){4===e.target.value.length&&$.currentYearElement.blur(),$.currentYear=parseInt(e.target.value,10)||$.currentYear,$.redraw()}),$.days.addEventListener("click",Y)),void($.config.enableTime&&($.timeContainer.addEventListener("wheel",a),$.timeContainer.addEventListener("input",a),$.timeContainer.addEventListener("wheel",$.debouncedChange),$.timeContainer.addEventListener("input",$.triggerChange),$.hourElement.addEventListener("focus",function(){$.hourElement.select()}),$.minuteElement.addEventListener("focus",function(){$.minuteElement.select()}),$.secondElement&&$.secondElement.addEventListener("focus",function(){$.secondElement.select()}),$.amPM&&$.amPM.addEventListener("click",a))))}function i(e){e=e?I(e):P()||$.config.minDate||$.now;try{$.currentYear=e.getFullYear(),$.currentMonth=e.getMonth()}catch(t){console.error(t.stack),console.warn("Invalid date supplied: "+e)}$.redraw()}function o(){var e=document.createDocumentFragment();$.calendarContainer=K("div","flatpickr-calendar"),$.numInputType=navigator.userAgent.indexOf("MSIE 9.0")>0?"text":"number",$.config.noCalendar||(e.appendChild(c()),$.config.weekNumbers&&e.appendChild(d()),$.rContainer=K("div","flatpickr-rContainer"),$.rContainer.appendChild(u()),$.rContainer.appendChild(l()),e.appendChild($.rContainer)),$.config.enableTime&&e.appendChild(s()),$.calendarContainer.appendChild(e),$.config.inline||$.config.static?($.calendarContainer.classList.add($.config.inline?"inline":"static"),T(),$.element.parentNode.insertBefore($.calendarContainer,($.altInput||$.input).nextSibling)):document.body.appendChild($.calendarContainer)}function l(){$.days||($.days=K("div","flatpickr-days"),$.days.tabIndex=-1),$.firstOfMonth=(new Date($.currentYear,$.currentMonth,1).getDay()-Flatpickr.l10n.firstDayOfWeek+7)%7,$.prevMonthDays=$.utils.getDaysinMonth(($.currentMonth-1+12)%12);var e=$.utils.getDaysinMonth(),t=document.createDocumentFragment(),n=$.prevMonthDays+1-$.firstOfMonth,a=void 0,r=void 0;if($.config.weekNumbers&&($.weekNumbers.innerHTML=""),"range"===$.config.mode){var i=$.config.enable.length||$.config.disable.length||$.config.mixDate||$.config.maxDate;i&&$.minRangeDate&&$.maxRangeDate||($.minRangeDate=new Date($.currentYear,$.currentMonth-1,n),$.maxRangeDate=new Date($.currentYear,$.currentMonth+1,(42-$.firstOfMonth)%e))}$.days.innerHTML="";for(var o=0;n<=$.prevMonthDays;o++,n++){var l=new Date($.currentYear,$.currentMonth-1,n,0,0,0,0,0),c=y(l),s=K("span","flatpickr-day prevMonthDay"+(c?"":" disabled")+(W(l)?" inRange":"")+(1===$.selectedDates.length&&(l<$.minRangeDate||l>$.maxRangeDate)?" notAllowed":"")+(U(l)!==!1?" selected":""),n);c?s.tabIndex=0:$.selectedDates[0]&&l>$.minRangeDate&&l<$.selectedDates[0]?$.minRangeDate=l:$.selectedDates[0]&&l<$.maxRangeDate&&l>$.selectedDates[0]&&($.maxRangeDate=l),j("DayCreate",s),t.appendChild(s)}for(n=1;n<=e;n++){a=new Date($.currentYear,$.currentMonth,n,0,0,0,0,0),$.config.weekNumbers&&n%7===1&&$.weekNumbers.insertAdjacentHTML("beforeend","<span class='disabled flatpickr-day'>"+$.getWeek(a)+"</span>"),r=!y(a);var u=K("span",r?"flatpickr-day disabled":"flatpickr-day"+(W(a)?" inRange":"")+(1===$.selectedDates.length&&(a<$.minRangeDate||a>$.maxRangeDate)?" notAllowed":""),n);r?$.selectedDates[0]&&a>$.minRangeDate&&a<$.selectedDates[0]?$.minRangeDate=a:$.selectedDates[0]&&a<$.maxRangeDate&&a>$.selectedDates[0]&&($.maxRangeDate=a):(u.tabIndex=0,V(a,$.now)&&u.classList.add("today"),U(a)&&(u.classList.add("selected"),$.selectedDateElem=u,"range"===$.config.mode&&(u.className+=V(a,$.selectedDates[0])?" startRange":$.selectedDates.length>1?" endRange":""))),j("DayCreate",u),t.appendChild(u)}for(var d=e+1;d<=42-$.firstOfMonth;d++){var p=new Date($.currentYear,$.currentMonth+1,d%e,0,0,0,0,0),f=y(p),m=K("span","flatpickr-day nextMonthDay"+(f?"":" disabled")+(W(p)?" inRange":"")+(1===$.selectedDates.length&&(p<$.minRangeDate||p>$.maxRangeDate)?" notAllowed":"")+(U(p)!==!1?" selected":""),d%e);$.config.weekNumbers&&d%7===1&&$.weekNumbers.insertAdjacentHTML("beforeend","<span class='disabled flatpickr-day'>"+$.getWeek(p)+"</span>"),f?m.tabIndex=0:$.selectedDates[0]&&p>$.minRangeDate&&p<$.selectedDates[0]?$.minRangeDate=p:$.selectedDates[0]&&p<$.maxRangeDate&&p>$.selectedDates[0]&&($.maxRangeDate=p),j("DayCreate",m),t.appendChild(m)}return $.days.appendChild(t),$.days}function c(){var e=document.createDocumentFragment();return $.monthNav=K("div","flatpickr-month"),$.prevMonthNav=K("span","flatpickr-prev-month"),$.prevMonthNav.innerHTML=$.config.prevArrow,$.currentMonthElement=K("span","cur-month"),$.currentYearElement=K("input","cur-year"),$.currentYearElement.type=$.numInputType,$.currentYearElement.title=Flatpickr.l10n.scrollTitle,$.config.minDate&&($.currentYearElement.min=$.config.minDate.getFullYear()),$.config.maxDate&&($.currentYearElement.max=$.config.maxDate.getFullYear()),$.nextMonthNav=K("span","flatpickr-next-month"),$.nextMonthNav.innerHTML=$.config.nextArrow,$.navigationCurrentMonth=K("span","flatpickr-current-month"),$.navigationCurrentMonth.appendChild($.currentMonthElement),$.navigationCurrentMonth.appendChild($.currentYearElement),e.appendChild($.prevMonthNav),e.appendChild($.navigationCurrentMonth),e.appendChild($.nextMonthNav),$.monthNav.appendChild(e),B(),$.monthNav}function s(){$.calendarContainer.classList.add("hasTime"),$.timeContainer=K("div","flatpickr-time"),$.timeContainer.tabIndex=-1;var e=K("span","flatpickr-time-separator",":");return $.hourElement=K("input","flatpickr-hour"),$.minuteElement=K("input","flatpickr-minute"),$.hourElement.tabIndex=$.minuteElement.tabIndex=0,$.hourElement.type=$.minuteElement.type=$.numInputType,$.hourElement.value=E(P()?P().getHours():$.config.defaultHour),$.minuteElement.value=E(P()?P().getMinutes():$.config.defaultMinute),$.hourElement.step=$.config.hourIncrement,$.minuteElement.step=$.config.minuteIncrement,$.hourElement.min=-($.config.time_24hr?1:0),$.hourElement.max=$.config.time_24hr?24:13,$.minuteElement.min=-$.minuteElement.step,$.minuteElement.max=60,$.hourElement.title=$.minuteElement.title=Flatpickr.l10n.scrollTitle,$.timeContainer.appendChild($.hourElement),$.timeContainer.appendChild(e),$.timeContainer.appendChild($.minuteElement),$.config.enableSeconds&&($.timeContainer.classList.add("has-seconds"),$.secondElement=K("input","flatpickr-second"),$.secondElement.type=$.numInputType,$.secondElement.value=P()?E(P().getSeconds()):"00",$.secondElement.step=$.minuteElement.step,$.secondElement.min=$.minuteElement.min,$.secondElement.max=$.minuteElement.max,$.timeContainer.appendChild(K("span","flatpickr-time-separator",":")),$.timeContainer.appendChild($.secondElement)),$.config.time_24hr||($.amPM=K("span","flatpickr-am-pm",["AM","PM"][$.hourElement.value>11|0]),$.amPM.title=Flatpickr.l10n.toggleTitle,$.amPM.tabIndex=0,$.timeContainer.appendChild($.amPM)),$.timeContainer}function u(){$.weekdayContainer||($.weekdayContainer=K("div","flatpickr-weekdays"));var e=Flatpickr.l10n.firstDayOfWeek,t=Flatpickr.l10n.weekdays.shorthand.slice();return e>0&&e<t.length&&(t=[].concat(t.splice(e,t.length),t.splice(0,e))),$.weekdayContainer.innerHTML="\n\t\t<span class=flatpickr-weekday>\n\t\t\t"+t.join("</span><span class=flatpickr-weekday>")+"\n\t\t</span>\n\t\t",$.weekdayContainer}function d(){return $.calendarContainer.classList.add("hasWeeks"),$.weekWrapper=K("div","flatpickr-weekwrapper"),$.weekWrapper.appendChild(K("span","flatpickr-weekday",Flatpickr.l10n.weekAbbreviation)),$.weekNumbers=K("div","flatpickr-weeks"),$.weekWrapper.appendChild($.weekNumbers),$.weekWrapper}function p(e,t){$.currentMonth="undefined"==typeof t||t?($.currentMonth+e+12)%12:e,D(),B(),l(),$.config.noCalendar||$.days.focus()}function f(){$.input.value="",$.altInput&&($.altInput.value=""),$.mobileInput&&($.mobileInput.value=""),$.selectedDates=[],j("Change"),i($.now)}function m(){$.isOpen=!1,$.calendarContainer.classList.remove("open"),($.altInput||$.input).classList.remove("active"),j("Close")}function g(){$.clear(),$.calendarContainer.parentNode.removeChild($.calendarContainer),$.altInput&&($.input.type="text",$.altInput.parentNode.removeChild($.altInput)),$.input.classList.remove("flatpickr-input"),$.input.removeEventListener("focus",M),$.input.removeAttribute("readonly"),document.removeEventListener("keydown",b),window.removeEventListener("resize",$.debouncedResize),document.removeEventListener("click",h),document.removeEventListener("blur",h),delete $.input._flatpickr,delete $.input}function h(e){var t=$.calendarContainer.contains(e.target),n=$.element.contains(e.target)||e.target===$.altInput;!$.isOpen||t||n||($.close(),"range"===$.config.mode&&1===$.selectedDates.length&&($.clear(),$.redraw()))}function v(e,t){var n=e.split("");return n.map(function(e,a){return $.formats[e]&&"\\"!==n[a-1]?$.formats[e](t):"\\"!==e?e:""}).join("")}function D(){($.currentMonth<0||$.currentMonth>11)&&($.currentYear+=$.currentMonth%11,$.currentMonth=($.currentMonth+12)%12)}function y(e){if($.config.minDate&&e<$.config.minDate||$.config.maxDate&&e>$.config.maxDate)return!1;if(!$.config.enable.length&&!$.config.disable.length)return!0;e=I(e,!0);for(var t,n=$.config.enable.length>0,a=n?$.config.enable:$.config.disable,r=0;r<a.length;r++){if(t=a[r],t instanceof Function&&t(e))return n;if((t instanceof Date||"string"==typeof t)&&I(t,!0).getTime()===e.getTime())return n;if("object"===("undefined"==typeof t?"undefined":_typeof(t))&&t.from&&t.to&&e>=I(t.from)&&e<=I(t.to))return n}return!n}function b(e){if($.isOpen)switch(e.which){case 13:$.timeContainer&&$.timeContainer.contains(e.target)?z():Y(e);break;case 27:$.clear(),$.close();break;case 37:e.target!==$.input&e.target!==$.altInput&&p(-1);break;case 38:e.preventDefault(),$.timeContainer&&$.timeContainer.contains(e.target)?a(e):($.currentYear++,$.redraw());break;case 39:e.target!==$.input&e.target!==$.altInput&&p(1);break;case 40:e.preventDefault(),$.timeContainer&&$.timeContainer.contains(e.target)?a(e):($.currentYear--,$.redraw())}}function k(e){return new Date($.currentYear,$.currentMonth+e.classList.contains("nextMonthDay")-e.classList.contains("prevMonthDay"),e.textContent)}function w(e){if(1===$.selectedDates.length&&e.target.classList.contains("flatpickr-day")){for(var t=k(e.target),n=Math.min(t.getTime(),$.selectedDates[0].getTime()),a=Math.max(t.getTime(),$.selectedDates[0].getTime()),r=!1,i=n;i<a;i+=$.utils.duration.DAY)if(!y(new Date(i))){r=!0;break}for(var o=k($.days.childNodes[0]).getTime(),l=0;l<42;l++,o+=$.utils.duration.DAY)o<$.minRangeDate.getTime()||o>$.maxRangeDate.getTime()?($.days.childNodes[l].classList.add("notAllowed"),$.days.childNodes[l].classList.remove("inRange")):!r&&o>Math.max($.minRangeDate.getTime(),n)&&o<Math.min($.maxRangeDate.getTime(),a)?$.days.childNodes[l].classList.add("inRange"):$.days.childNodes[l].classList.remove("inRange")}}function C(){!$.isOpen||$.config.inline||$.config.static||T()}function M(e){return $.isMobile?(e.preventDefault(),e.target.blur(),setTimeout(function(){$.mobileInput.click()},0),void j("Open")):void($.isOpen||($.altInput||$.input).disabled||$.config.inline||($.calendarContainer.classList.add("open"),$.config.static||T(),$.isOpen=!0,$.config.allowInput||(($.altInput||$.input).blur(),($.config.noCalendar?$.timeContainer:$.selectedDateElem?$.selectedDateElem:$.days).focus()),($.altInput||$.input).classList.add("active"),j("Open")))}function E(e){return("0"+e).slice(-2)}function x(){var e=["utc","wrap","weekNumbers","allowInput","clickOpens","time_24hr","enableTime","noCalendar","altInput","shorthandCurrentMonth","inline","static","enableSeconds","disableMobile"];$.config=Object.create(Flatpickr.defaultConfig);var t=_extends({},$.instanceConfig,$.element.dataset||{});Object.defineProperty($.config,"minDate",{get:function(){return this._minDate},set:function(e){this._minDate=I(e,!0),$.days&&L()}}),Object.defineProperty($.config,"maxDate",{get:function(){return this._maxDate},set:function(e){this._maxDate=I(e,!0),$.days&&L()}}),_extends($.config,t);for(var n=0;n<e.length;n++)$.config[e[n]]=$.config[e[n]]===!0||"true"===$.config[e[n]];!t.dateFormat&&t.enableTime&&($.config.dateFormat=$.config.noCalendar?"H:i"+($.config.enableSeconds?":S":""):Flatpickr.defaultConfig.dateFormat+" H:i"+($.config.enableSeconds?":S":"")),t.altInput&&t.enableTime&&!t.altFormat&&($.config.altFormat=$.config.noCalendar?"h:i"+($.config.enableSeconds?":S K":" K"):Flatpickr.defaultConfig.altFormat+(" h:i"+($.config.enableSeconds?":S":"")+" K"))}function I(e){var t=arguments.length>1&&void 0!==arguments[1]&&arguments[1];if(!e)return null;var n=/(\d+)/g,a=/^(\d{1,2})[:\s](\d\d)?[:\s](\d\d)?\s?(a|p)?/i,r=e;if("string"==typeof e)if(e=e.trim(),"today"===e)e=new Date,t=!0;else if($.config.parseDate)e=$.config.parseDate(e);else if(a.test(e)){var i=e.match(a),o=i[4]?i[1]%12+("p"===i[4].toLowerCase()?12:0):i[1];e=new Date,e.setHours(o,i[2]||0,i[3]||0)}else if(/Z$/.test(e)||/GMT$/.test(e))e=new Date(e);else if(n.test(e)&&/^[0-9]/.test(e)){var l=e.match(n);e=new Date(l[0]+"/"+(l[1]||1)+"/"+(l[2]||1)+" "+(l[3]||0)+":"+(l[4]||0)+":"+(l[5]||0))}else e=new Date(e);return e instanceof Date?($.config.utc&&!e.fp_isUTC&&(e=e.fp_toUTC()),t&&e.setHours(0,0,0,0),e):(console.warn("flatpickr: invalid date "+r),console.info($.element),null)}function T(){var e=$.calendarContainer.offsetHeight,t=$.altInput||$.input,n=t.getBoundingClientRect(),a=window.innerHeight-n.bottom+t.offsetHeight,r=void 0,i=window.pageXOffset+n.left;a<e?(r=window.pageYOffset-e+n.top-2,$.calendarContainer.classList.remove("arrowTop"),$.calendarContainer.classList.add("arrowBottom")):(r=window.pageYOffset+t.offsetHeight+n.top+2,$.calendarContainer.classList.remove("arrowBottom"),$.calendarContainer.classList.add("arrowTop")),$.config.inline||$.config.static||($.calendarContainer.style.top=r+"px",$.calendarContainer.style.left=i+"px")}function L(){$.config.noCalendar||$.isMobile||(u(),B(),l())}function Y(e){if(e.preventDefault(),e.stopPropagation(),$.config.allowInput&&13===e.which&&(e.target===$.altInput||$.input))return $.setDate(($.altInput||$.input).value),e.target.blur();if(e.target.classList.contains("flatpickr-day")&&!e.target.classList.contains("disabled")&&!e.target.classList.contains("notAllowed")){var t=k(e.target);if($.selectedDateElem=e.target,"single"===$.config.mode)$.selectedDates=[t],$.config.enableTime||$.close();else if("multiple"===$.config.mode){var n=U(t);n?$.selectedDates.splice(n,1):$.selectedDates.push(t)}else"range"===$.config.mode&&(2===$.selectedDates.length&&$.clear(),$.selectedDates.push(t),$.selectedDates.sort(function(e,t){return e.getTime()-t.getTime()}));t.getMonth()!==$.currentMonth&&p(t.getMonth(),!1),z(),l(),j("Change"),"range"===$.config.mode&&1===$.selectedDates.length&&w(e)}}function F(e,t){$.config[e]=t,$.redraw(),i()}function N(e,t){return e?($.selectedDates=(Array.isArray(e)?e.map(I):[I(e)]).filter(function(e){return e instanceof Date}),$.redraw(),i(),z(!1),void(t&&j("Change"))):$.clear()}function S(){$.selectedDates=[],$.now=new Date;var e=$.config.defaultDate||$.input.value;if(Array.isArray(e))$.selectedDates=e.map(I);else if(e){switch($.config.mode){case"single":$.selectedDates=[I(e)];break;case"multiple":$.selectedDates=e.split("; ").map(I);break;case"range":$.selectedDates=e.split(" to ").map(I)}$.selectedDates=$.selectedDates.filter(function(e){return e instanceof Date})}var t=$.selectedDates.length?$.selectedDates[0]:$.config.minDate||$.now;$.currentYear=t.getFullYear(),$.currentMonth=t.getMonth()}function O(){$.formats={D:function(e){return Flatpickr.l10n.weekdays.shorthand[$.formats.w(e)]},F:function(e){return $.utils.monthToStr($.formats.n(e)-1,!1)},H:function(e){return E(e.getHours())},J:function(e){return e.getDate()+Flatpickr.l10n.ordinal(e.getDate())},K:function(e){return e.getHours()>11?"PM":"AM"},M:function(e){return $.utils.monthToStr(e.getMonth(),!0)},S:function(e){return E(e.getSeconds())},U:function(e){return e.getTime()/1e3},Y:function(e){return e.getFullYear()},d:function(e){return E($.formats.j(e))},h:function(e){return e.getHours()%12?e.getHours()%12:12},i:function(e){return E(e.getMinutes())},j:function(e){return e.getDate()},l:function(e){return Flatpickr.l10n.weekdays.longhand[$.formats.w(e)]},m:function(e){return E($.formats.n(e))},n:function(e){return e.getMonth()+1},s:function(e){return e.getSeconds()},w:function(e){return e.getDay()},y:function(e){return String($.formats.Y(e)).substring(2)}}}function A(){$.utils={duration:{DAY:864e5},getDaysinMonth:function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:$.currentMonth,t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:$.currentYear;return 1===e&&t%4===0&&t%100!==0||t%400===0?29:Flatpickr.l10n.daysInMonth[e]},monthToStr:function(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:$.config.shorthandCurrentMonth;return Flatpickr.l10n.months[(t?"short":"long")+"hand"][e]}}}function R(){$.input=$.config.wrap?$.element.querySelector("[data-input]"):$.element,$.input.classList.add("flatpickr-input"),$.config.altInput&&($.altInput=K($.input.nodeName,"flatpickr-input "+$.config.altInputClass),$.altInput.placeholder=$.input.placeholder,$.altInput.type="text",$.input.type="hidden",$.input.parentNode.insertBefore($.altInput,$.input.nextSibling)),$.config.allowInput||($.altInput||$.input).setAttribute("readonly","readonly")}function H(){var e=$.config.enableTime?$.config.noCalendar?"time":"datetime-local":"date";$.mobileInput=K("input","flatpickr-input flatpickr-mobile"),$.mobileInput.step="any",$.mobileInput.tabIndex=-1,$.mobileInput.type=e,$.mobileFormatStr="datetime-local"===e?"Y-m-d\\TH:i:S":"date"===e?"Y-m-d":"H:i:S",$.selectedDates.length&&($.mobileInput.defaultValue=$.mobileInput.value=v($.mobileFormatStr,$.selectedDates[0])),$.config.minDate&&($.mobileInput.min=v("Y-m-d",$.config.minDate)),$.config.maxDate&&($.mobileInput.max=v("Y-m-d",$.config.maxDate)),$.input.type="hidden",$.config.altInput&&($.altInput.type="hidden");try{$.input.parentNode.insertBefore($.mobileInput,$.input.nextSibling)}catch(e){}$.mobileInput.addEventListener("change",function(e){$.setDate(e.target.value),j("Change"),j("Close")})}function _(){$.isOpen?$.close():$.open()}function j(e,t){if($.config["on"+e])for(var n=Array.isArray($.config["on"+e])?$.config["on"+e]:[$.config["on"+e]],a=0;a<n.length;a++)n[a]($.selectedDates,$.input.value,$,t);if("Change"===e)try{$.input.dispatchEvent(new Event("change",{bubbles:!0}))}catch(e){if("createEvent"in document)return $.input.dispatchEvent($.changeEvent);$.input.fireEvent("onchange")}}function P(){return $.selectedDates.length?$.selectedDates[$.selectedDates.length-1]:null}function U(e){if($.selectedDates.length)for(var t=0;t<$.selectedDates.length;t++)if(V($.selectedDates[t],e))return""+t;return!1}function W(e){return!("range"!==$.config.mode||$.selectedDates.length<2)&&(e>$.selectedDates[0]&&e<$.selectedDates[1])}function B(){if(!$.config.noCalendar&&!$.isMobile&&$.monthNav){if($.currentMonthElement.textContent=$.utils.monthToStr($.currentMonth)+" ",$.currentYearElement.value=$.currentYear,$.config.minDate){$.currentYearElement.min=$.config.minDate.getFullYear();var e=$.currentYear===$.config.minDate.getFullYear()?($.currentMonth+11)%12<$.config.minDate.getMonth():$.currentYear<$.config.minDate.getFullYear();$.prevMonthNav.style.display=e?"none":"block"}else $.currentYearElement.removeAttribute("min"),$.prevMonthNav.style.display="block";if($.config.maxDate){var t=$.currentYear===$.config.maxDate.getFullYear()?$.currentMonth+1>$.config.maxDate.getMonth():$.currentYear>$.config.maxDate.getFullYear();$.nextMonthNav.style.display=t?"none":"block",$.currentYearElement.max=$.config.maxDate.getFullYear()}else $.currentYearElement.removeAttribute("max"),$.nextMonthNav.style.display="block"}}function z(){var e=!(arguments.length>0&&void 0!==arguments[0])||arguments[0];if(!$.selectedDates.length)return $.clear();if($.config.enableTime&&!$.isMobile){var t=void 0,n=void 0,a=void 0;e?(t=parseInt($.hourElement.value,10)||0,n=(60+(parseInt($.minuteElement.value,10)||0))%60,$.config.enableSeconds&&(a=(60+parseInt($.secondElement.value,10)||0)%60),$.config.time_24hr||(t=t%12+12*("PM"===$.amPM.innerHTML)),$.selectedDates[$.selectedDates.length-1].setHours(t,n,a||0,0)):(t=P().getHours(),n=P().getMinutes(),a=P().getSeconds()),$.hourElement.value=E($.config.time_24hr?t:(12+t)%12+12*(t%12===0)),$.minuteElement.value=E(n),$.config.time_24hr||($.amPM.textContent=t>=12?"PM":"AM"),$.config.enableSeconds&&($.secondElement.value=E(a))}switch($.isMobile&&($.mobileInput.value=$.selectedDates.length?v($.mobileFormatStr,P()):""),$.config.mode){case"single":$.input.value=v($.config.dateFormat,P()),$.altInput&&($.altInput.value=v($.config.altFormat,P()));break;case"multiple":$.input.value=$.selectedDates.map(function(e){return v($.config.dateFormat,e)}).join("; "),$.altInput&&($.altInput.value=$.selectedDates.map(function(e){return v($.config.altFormat,e)}).join("; "));break;case"range":2===$.selectedDates.length?($.altInput||$.input).value=$.selectedDates.map(function(e){return v($.config.dateFormat,e)}).join(" to "):($.altInput||$.input).value=v($.config.dateFormat,P())}j("ValueUpdate")}function J(e){e.preventDefault();var t=Math.max(-1,Math.min(1,e.wheelDelta||-e.deltaY));$.currentYear=e.target.value=parseInt(e.target.value,10)+t,$.redraw()}function K(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:"",n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:"",a=document.createElement(e);return a.className=t,n&&(a.textContent=n),a}function q(e,t,n){var a=void 0;return function(){for(var r=arguments.length,i=Array(r),o=0;o<r;o++)i[o]=arguments[o];var l=this,c=function(){a=null,n||e.apply(l,i)};clearTimeout(a),a=setTimeout(c,t),n&&!a&&e.apply(l,i)}}function V(e,t){return e instanceof Date&&t instanceof Date&&(e.getDate()===t.getDate()&&e.getMonth()===t.getMonth()&&e.getFullYear()===t.getFullYear())}function Q(e){if(e.preventDefault(),e&&((e.target.value||e.target.textContent).length>=2||"keydown"!==e.type&&"input"!==e.type)&&e.target.blur(),"flatpickr-am-pm"===e.target.className)return e.target.textContent=["AM","PM"]["AM"===e.target.textContent|0],void e.stopPropagation();var t=parseInt(e.target.min,10),n=parseInt(e.target.max,10),a=parseInt(e.target.step,10),r=parseInt(e.target.value,10),i=r;"wheel"===e.type?i=r+a*Math.max(-1,Math.min(1,e.wheelDelta||-e.deltaY)):"keydown"===e.type&&(i=r+a*(38===e.which?1:-1)),i<=t?i=n-a:i>=n&&(i=t+a),e.target.value=E(i)}var $=this;return n(),$}function _flatpickr(e,t){for(var n=[],a=0;a<e.length;a++){e[a]._flatpickr&&e[a]._flatpickr.destroy();try{e[a]._flatpickr=new Flatpickr(e[a],t||{}),n.push(e[a]._flatpickr)}catch(e){console.warn(e,e.stack)}}return 1===n.length?n[0]:n}function flatpickr(e,t){return _flatpickr(document.querySelectorAll(e),t)}var _extends=Object.assign||function(e){for(var t=1;t<arguments.length;t++){var n=arguments[t];for(var a in n)Object.prototype.hasOwnProperty.call(n,a)&&(e[a]=n[a])}return e},_typeof="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol?"symbol":typeof e};Flatpickr.defaultConfig={mode:"single",utc:!1,wrap:!1,weekNumbers:!1,allowInput:!1,clickOpens:!0,time_24hr:!1,enableTime:!1,noCalendar:!1,dateFormat:"Y-m-d",altInput:!1,altInputClass:"",altFormat:"F j, Y",defaultDate:null,minDate:null,maxDate:null,parseDate:null,enable:[],disable:[],shorthandCurrentMonth:!1,inline:!1,static:!1,prevArrow:"<svg version='1.1' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink' viewBox='0 0 17 17'><g></g><path d='M5.207 8.471l7.146 7.147-0.707 0.707-7.853-7.854 7.854-7.853 0.707 0.707-7.147 7.146z' /></svg>",nextArrow:"<svg version='1.1' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink' viewBox='0 0 17 17'><g></g><path d='M13.207 8.472l-7.854 7.854-0.707-0.707 7.146-7.146-7.146-7.148 0.707-0.707 7.854 7.854z' /></svg>",enableSeconds:!1,hourIncrement:1,minuteIncrement:5,defaultHour:12,defaultMinute:0,disableMobile:!1,onChange:null,onOpen:null,onClose:null,onReady:null,onValueUpdate:null,onDayCreate:null},Flatpickr.l10n={weekdays:{shorthand:["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],longhand:["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"]},months:{shorthand:["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"],longhand:["January","February","March","April","May","June","July","August","September","October","November","December"]},daysInMonth:[31,28,31,30,31,30,31,31,30,31,30,31],firstDayOfWeek:0,ordinal:function(e){var t=e%100;if(t>3&&t<21)return"th";switch(t%10){case 1:return"st";case 2:return"nd";case 3:return"rd";default:return"th"}},weekAbbreviation:"Wk",scrollTitle:"Scroll to increment",toggleTitle:"Click to toggle"},Flatpickr.localize=function(e){Object.keys(e).forEach(function(t){return Flatpickr.l10n[t]=e[t]})},"undefined"!=typeof HTMLElement&&(HTMLCollection.prototype.flatpickr=NodeList.prototype.flatpickr=function(e){return _flatpickr(this,e)},HTMLElement.prototype.flatpickr=function(e){return _flatpickr([this],e)}),"undefined"!=typeof jQuery&&(jQuery.fn.flatpickr=function(e){return _flatpickr(this,e)}),Date.prototype.fp_incr=function(e){return new Date(this.getFullYear(),this.getMonth(),this.getDate()+parseInt(e,10))},Date.prototype.fp_isUTC=!1,Date.prototype.fp_toUTC=function(){var e=new Date(this.getUTCFullYear(),this.getUTCMonth(),this.getUTCDate(),this.getUTCHours(),this.getUTCMinutes(),this.getUTCSeconds());return e.fp_isUTC=!0,e},Flatpickr.prototype.getWeek=function(e){var t=new Date(e.getTime());t.setHours(0,0,0,0),t.setDate(t.getDate()+3-(t.getDay()+6)%7);var n=new Date(t.getFullYear(),0,4);return 1+Math.round(((t.getTime()-n.getTime())/864e5-3+(n.getDay()+6)%7)/7)},"classList"in document.documentElement||!Object.defineProperty||"undefined"==typeof HTMLElement||Object.defineProperty(HTMLElement.prototype,"classList",{get:function(){function e(e){return function(n){var a=t.className.split(/\s+/),r=a.indexOf(n);e(a,r,n),t.className=a.join(" ")}}var t=this,n={add:e(function(e,t,n){~t||e.push(n)}),remove:e(function(e,t){~t&&e.splice(t,1)}),toggle:e(function(e,t,n){~t?e.splice(t,1):e.push(n)}),contains:function(e){return!!~t.className.split(/\s+/).indexOf(e)},item:function(e){return t.className.split(/\s+/)[e]||null}};return Object.defineProperty(n,"length",{get:function(){return t.className.split(/\s+/).length}}),n}}),"undefined"!=typeof module&&(module.exports=Flatpickr);
assets/js/jquery.picker.date.js DELETED
@@ -1,1354 +0,0 @@
1
- /*!
2
- * Date picker for pickadate.js v3.5.6
3
- * http://amsul.github.io/pickadate.js/date.htm
4
- */
5
-
6
- (function ( factory ) {
7
-
8
- // AMD.
9
- if ( typeof define == 'function' && define.amd )
10
- define( ['picker', 'jquery'], factory )
11
-
12
- // Node.js/browserify.
13
- else if ( typeof exports == 'object' )
14
- module.exports = factory( require('./picker.js'), require('jquery') )
15
-
16
- // Browser globals.
17
- else factory( Picker, jQuery )
18
-
19
- }(function( Picker, $ ) {
20
-
21
-
22
- /**
23
- * Globals and constants
24
- */
25
- var DAYS_IN_WEEK = 7,
26
- WEEKS_IN_CALENDAR = 6,
27
- _ = Picker._
28
-
29
-
30
-
31
- /**
32
- * The date picker constructor
33
- */
34
- function DatePicker( picker, settings ) {
35
-
36
- var calendar = this,
37
- element = picker.$node[ 0 ],
38
- elementValue = element.value,
39
- elementDataValue = picker.$node.data( 'value' ),
40
- valueString = elementDataValue || elementValue,
41
- formatString = elementDataValue ? settings.formatSubmit : settings.format,
42
- isRTL = function() {
43
-
44
- return element.currentStyle ?
45
-
46
- // For IE.
47
- element.currentStyle.direction == 'rtl' :
48
-
49
- // For normal browsers.
50
- getComputedStyle( picker.$root[0] ).direction == 'rtl'
51
- }
52
-
53
- calendar.settings = settings
54
- calendar.$node = picker.$node
55
-
56
- // The queue of methods that will be used to build item objects.
57
- calendar.queue = {
58
- min: 'measure create',
59
- max: 'measure create',
60
- now: 'now create',
61
- select: 'parse create validate',
62
- highlight: 'parse navigate create validate',
63
- view: 'parse create validate viewset',
64
- disable: 'deactivate',
65
- enable: 'activate'
66
- }
67
-
68
- // The component's item object.
69
- calendar.item = {}
70
-
71
- calendar.item.clear = null
72
- calendar.item.disable = ( settings.disable || [] ).slice( 0 )
73
- calendar.item.enable = -(function( collectionDisabled ) {
74
- return collectionDisabled[ 0 ] === true ? collectionDisabled.shift() : -1
75
- })( calendar.item.disable )
76
-
77
- calendar.
78
- set( 'min', settings.min ).
79
- set( 'max', settings.max ).
80
- set( 'now' )
81
-
82
- // When there’s a value, set the `select`, which in turn
83
- // also sets the `highlight` and `view`.
84
- if ( valueString ) {
85
- calendar.set( 'select', valueString, {
86
- format: formatString,
87
- defaultValue: true
88
- })
89
- }
90
-
91
- // If there’s no value, default to highlighting “today”.
92
- else {
93
- calendar.
94
- set( 'select', null ).
95
- set( 'highlight', calendar.item.now )
96
- }
97
-
98
-
99
- // The keycode to movement mapping.
100
- calendar.key = {
101
- 40: 7, // Down
102
- 38: -7, // Up
103
- 39: function() { return isRTL() ? -1 : 1 }, // Right
104
- 37: function() { return isRTL() ? 1 : -1 }, // Left
105
- go: function( timeChange ) {
106
- var highlightedObject = calendar.item.highlight,
107
- targetDate = new Date( highlightedObject.year, highlightedObject.month, highlightedObject.date + timeChange )
108
- calendar.set(
109
- 'highlight',
110
- targetDate,
111
- { interval: timeChange }
112
- )
113
- this.render()
114
- }
115
- }
116
-
117
-
118
- // Bind some picker events.
119
- picker.
120
- on( 'render', function() {
121
- picker.$root.find( '.' + settings.klass.selectMonth ).on( 'change', function() {
122
- var value = this.value
123
- if ( value ) {
124
- picker.set( 'highlight', [ picker.get( 'view' ).year, value, picker.get( 'highlight' ).date ] )
125
- picker.$root.find( '.' + settings.klass.selectMonth ).trigger( 'focus' )
126
- }
127
- })
128
- picker.$root.find( '.' + settings.klass.selectYear ).on( 'change', function() {
129
- var value = this.value
130
- if ( value ) {
131
- picker.set( 'highlight', [ value, picker.get( 'view' ).month, picker.get( 'highlight' ).date ] )
132
- picker.$root.find( '.' + settings.klass.selectYear ).trigger( 'focus' )
133
- }
134
- })
135
- }, 1 ).
136
- on( 'open', function() {
137
- var includeToday = ''
138
- if ( calendar.disabled( calendar.get('now') ) ) {
139
- includeToday = ':not(.' + settings.klass.buttonToday + ')'
140
- }
141
- picker.$root.find( 'button' + includeToday + ', select' ).attr( 'disabled', false )
142
- }, 1 ).
143
- on( 'close', function() {
144
- picker.$root.find( 'button, select' ).attr( 'disabled', true )
145
- }, 1 )
146
-
147
- } //DatePicker
148
-
149
-
150
- /**
151
- * Set a datepicker item object.
152
- */
153
- DatePicker.prototype.set = function( type, value, options ) {
154
-
155
- var calendar = this,
156
- calendarItem = calendar.item
157
-
158
- // If the value is `null` just set it immediately.
159
- if ( value === null ) {
160
- if ( type == 'clear' ) type = 'select'
161
- calendarItem[ type ] = value
162
- return calendar
163
- }
164
-
165
- // Otherwise go through the queue of methods, and invoke the functions.
166
- // Update this as the time unit, and set the final value as this item.
167
- // * In the case of `enable`, keep the queue but set `disable` instead.
168
- // And in the case of `flip`, keep the queue but set `enable` instead.
169
- calendarItem[ ( type == 'enable' ? 'disable' : type == 'flip' ? 'enable' : type ) ] = calendar.queue[ type ].split( ' ' ).map( function( method ) {
170
- value = calendar[ method ]( type, value, options )
171
- return value
172
- }).pop()
173
-
174
- // Check if we need to cascade through more updates.
175
- if ( type == 'select' ) {
176
- calendar.set( 'highlight', calendarItem.select, options )
177
- }
178
- else if ( type == 'highlight' ) {
179
- calendar.set( 'view', calendarItem.highlight, options )
180
- }
181
- else if ( type.match( /^(flip|min|max|disable|enable)$/ ) ) {
182
- if ( calendarItem.select && calendar.disabled( calendarItem.select ) ) {
183
- calendar.set( 'select', calendarItem.select, options )
184
- }
185
- if ( calendarItem.highlight && calendar.disabled( calendarItem.highlight ) ) {
186
- calendar.set( 'highlight', calendarItem.highlight, options )
187
- }
188
- }
189
-
190
- return calendar
191
- } //DatePicker.prototype.set
192
-
193
-
194
- /**
195
- * Get a datepicker item object.
196
- */
197
- DatePicker.prototype.get = function( type ) {
198
- return this.item[ type ]
199
- } //DatePicker.prototype.get
200
-
201
-
202
- /**
203
- * Create a picker date object.
204
- */
205
- DatePicker.prototype.create = function( type, value, options ) {
206
-
207
- var isInfiniteValue,
208
- calendar = this
209
-
210
- // If there’s no value, use the type as the value.
211
- value = value === undefined ? type : value
212
-
213
-
214
- // If it’s infinity, update the value.
215
- if ( value == -Infinity || value == Infinity ) {
216
- isInfiniteValue = value
217
- }
218
-
219
- // If it’s an object, use the native date object.
220
- else if ( $.isPlainObject( value ) && _.isInteger( value.pick ) ) {
221
- value = value.obj
222
- }
223
-
224
- // If it’s an array, convert it into a date and make sure
225
- // that it’s a valid date – otherwise default to today.
226
- else if ( $.isArray( value ) ) {
227
- value = new Date( value[ 0 ], value[ 1 ], value[ 2 ] )
228
- value = _.isDate( value ) ? value : calendar.create().obj
229
- }
230
-
231
- // If it’s a number or date object, make a normalized date.
232
- else if ( _.isInteger( value ) || _.isDate( value ) ) {
233
- value = calendar.normalize( new Date( value ), options )
234
- }
235
-
236
- // If it’s a literal true or any other case, set it to now.
237
- else /*if ( value === true )*/ {
238
- value = calendar.now( type, value, options )
239
- }
240
-
241
- // Return the compiled object.
242
- return {
243
- year: isInfiniteValue || value.getFullYear(),
244
- month: isInfiniteValue || value.getMonth(),
245
- date: isInfiniteValue || value.getDate(),
246
- day: isInfiniteValue || value.getDay(),
247
- obj: isInfiniteValue || value,
248
- pick: isInfiniteValue || value.getTime()
249
- }
250
- } //DatePicker.prototype.create
251
-
252
-
253
- /**
254
- * Create a range limit object using an array, date object,
255
- * literal “true”, or integer relative to another time.
256
- */
257
- DatePicker.prototype.createRange = function( from, to ) {
258
-
259
- var calendar = this,
260
- createDate = function( date ) {
261
- if ( date === true || $.isArray( date ) || _.isDate( date ) ) {
262
- return calendar.create( date )
263
- }
264
- return date
265
- }
266
-
267
- // Create objects if possible.
268
- if ( !_.isInteger( from ) ) {
269
- from = createDate( from )
270
- }
271
- if ( !_.isInteger( to ) ) {
272
- to = createDate( to )
273
- }
274
-
275
- // Create relative dates.
276
- if ( _.isInteger( from ) && $.isPlainObject( to ) ) {
277
- from = [ to.year, to.month, to.date + from ];
278
- }
279
- else if ( _.isInteger( to ) && $.isPlainObject( from ) ) {
280
- to = [ from.year, from.month, from.date + to ];
281
- }
282
-
283
- return {
284
- from: createDate( from ),
285
- to: createDate( to )
286
- }
287
- } //DatePicker.prototype.createRange
288
-
289
-
290
- /**
291
- * Check if a date unit falls within a date range object.
292
- */
293
- DatePicker.prototype.withinRange = function( range, dateUnit ) {
294
- range = this.createRange(range.from, range.to)
295
- return dateUnit.pick >= range.from.pick && dateUnit.pick <= range.to.pick
296
- }
297
-
298
-
299
- /**
300
- * Check if two date range objects overlap.
301
- */
302
- DatePicker.prototype.overlapRanges = function( one, two ) {
303
-
304
- var calendar = this
305
-
306
- // Convert the ranges into comparable dates.
307
- one = calendar.createRange( one.from, one.to )
308
- two = calendar.createRange( two.from, two.to )
309
-
310
- return calendar.withinRange( one, two.from ) || calendar.withinRange( one, two.to ) ||
311
- calendar.withinRange( two, one.from ) || calendar.withinRange( two, one.to )
312
- }
313
-
314
-
315
- /**
316
- * Get the date today.
317
- */
318
- DatePicker.prototype.now = function( type, value, options ) {
319
- value = new Date()
320
- if ( options && options.rel ) {
321
- value.setDate( value.getDate() + options.rel )
322
- }
323
- return this.normalize( value, options )
324
- }
325
-
326
-
327
- /**
328
- * Navigate to next/prev month.
329
- */
330
- DatePicker.prototype.navigate = function( type, value, options ) {
331
-
332
- var targetDateObject,
333
- targetYear,
334
- targetMonth,
335
- targetDate,
336
- isTargetArray = $.isArray( value ),
337
- isTargetObject = $.isPlainObject( value ),
338
- viewsetObject = this.item.view/*,
339
- safety = 100*/
340
-
341
-
342
- if ( isTargetArray || isTargetObject ) {
343
-
344
- if ( isTargetObject ) {
345
- targetYear = value.year
346
- targetMonth = value.month
347
- targetDate = value.date
348
- }
349
- else {
350
- targetYear = +value[0]
351
- targetMonth = +value[1]
352
- targetDate = +value[2]
353
- }
354
-
355
- // If we’re navigating months but the view is in a different
356
- // month, navigate to the view’s year and month.
357
- if ( options && options.nav && viewsetObject && viewsetObject.month !== targetMonth ) {
358
- targetYear = viewsetObject.year
359
- targetMonth = viewsetObject.month
360
- }
361
-
362
- // Figure out the expected target year and month.
363
- targetDateObject = new Date( targetYear, targetMonth + ( options && options.nav ? options.nav : 0 ), 1 )
364
- targetYear = targetDateObject.getFullYear()
365
- targetMonth = targetDateObject.getMonth()
366
-
367
- // If the month we’re going to doesn’t have enough days,
368
- // keep decreasing the date until we reach the month’s last date.
369
- while ( /*safety &&*/ new Date( targetYear, targetMonth, targetDate ).getMonth() !== targetMonth ) {
370
- targetDate -= 1
371
- /*safety -= 1
372
- if ( !safety ) {
373
- throw 'Fell into an infinite loop while navigating to ' + new Date( targetYear, targetMonth, targetDate ) + '.'
374
- }*/
375
- }
376
-
377
- value = [ targetYear, targetMonth, targetDate ]
378
- }
379
-
380
- return value
381
- } //DatePicker.prototype.navigate
382
-
383
-
384
- /**
385
- * Normalize a date by setting the hours to midnight.
386
- */
387
- DatePicker.prototype.normalize = function( value/*, options*/ ) {
388
- value.setHours( 0, 0, 0, 0 )
389
- return value
390
- }
391
-
392
-
393
- /**
394
- * Measure the range of dates.
395
- */
396
- DatePicker.prototype.measure = function( type, value/*, options*/ ) {
397
-
398
- var calendar = this
399
-
400
- // If it’s anything false-y, remove the limits.
401
- if ( !value ) {
402
- value = type == 'min' ? -Infinity : Infinity
403
- }
404
-
405
- // If it’s a string, parse it.
406
- else if ( typeof value == 'string' ) {
407
- value = calendar.parse( type, value )
408
- }
409
-
410
- // If it's an integer, get a date relative to today.
411
- else if ( _.isInteger( value ) ) {
412
- value = calendar.now( type, value, { rel: value } )
413
- }
414
-
415
- return value
416
- } ///DatePicker.prototype.measure
417
-
418
-
419
- /**
420
- * Create a viewset object based on navigation.
421
- */
422
- DatePicker.prototype.viewset = function( type, dateObject/*, options*/ ) {
423
- return this.create([ dateObject.year, dateObject.month, 1 ])
424
- }
425
-
426
-
427
- /**
428
- * Validate a date as enabled and shift if needed.
429
- */
430
- DatePicker.prototype.validate = function( type, dateObject, options ) {
431
-
432
- var calendar = this,
433
-
434
- // Keep a reference to the original date.
435
- originalDateObject = dateObject,
436
-
437
- // Make sure we have an interval.
438
- interval = options && options.interval ? options.interval : 1,
439
-
440
- // Check if the calendar enabled dates are inverted.
441
- isFlippedBase = calendar.item.enable === -1,
442
-
443
- // Check if we have any enabled dates after/before now.
444
- hasEnabledBeforeTarget, hasEnabledAfterTarget,
445
-
446
- // The min & max limits.
447
- minLimitObject = calendar.item.min,
448
- maxLimitObject = calendar.item.max,
449
-
450
- // Check if we’ve reached the limit during shifting.
451
- reachedMin, reachedMax,
452
-
453
- // Check if the calendar is inverted and at least one weekday is enabled.
454
- hasEnabledWeekdays = isFlippedBase && calendar.item.disable.filter( function( value ) {
455
-
456
- // If there’s a date, check where it is relative to the target.
457
- if ( $.isArray( value ) ) {
458
- var dateTime = calendar.create( value ).pick
459
- if ( dateTime < dateObject.pick ) hasEnabledBeforeTarget = true
460
- else if ( dateTime > dateObject.pick ) hasEnabledAfterTarget = true
461
- }
462
-
463
- // Return only integers for enabled weekdays.
464
- return _.isInteger( value )
465
- }).length/*,
466
-
467
- safety = 100*/
468
-
469
-
470
-
471
- // Cases to validate for:
472
- // [1] Not inverted and date disabled.
473
- // [2] Inverted and some dates enabled.
474
- // [3] Not inverted and out of range.
475
- //
476
- // Cases to **not** validate for:
477
- // • Navigating months.
478
- // • Not inverted and date enabled.
479
- // • Inverted and all dates disabled.
480
- // • ..and anything else.
481
- if ( !options || (!options.nav && !options.defaultValue) ) if (
482
- /* 1 */ ( !isFlippedBase && calendar.disabled( dateObject ) ) ||
483
- /* 2 */ ( isFlippedBase && calendar.disabled( dateObject ) && ( hasEnabledWeekdays || hasEnabledBeforeTarget || hasEnabledAfterTarget ) ) ||
484
- /* 3 */ ( !isFlippedBase && (dateObject.pick <= minLimitObject.pick || dateObject.pick >= maxLimitObject.pick) )
485
- ) {
486
-
487
-
488
- // When inverted, flip the direction if there aren’t any enabled weekdays
489
- // and there are no enabled dates in the direction of the interval.
490
- if ( isFlippedBase && !hasEnabledWeekdays && ( ( !hasEnabledAfterTarget && interval > 0 ) || ( !hasEnabledBeforeTarget && interval < 0 ) ) ) {
491
- interval *= -1
492
- }
493
-
494
-
495
- // Keep looping until we reach an enabled date.
496
- while ( /*safety &&*/ calendar.disabled( dateObject ) ) {
497
-
498
- /*safety -= 1
499
- if ( !safety ) {
500
- throw 'Fell into an infinite loop while validating ' + dateObject.obj + '.'
501
- }*/
502
-
503
-
504
- // If we’ve looped into the next/prev month with a large interval, return to the original date and flatten the interval.
505
- if ( Math.abs( interval ) > 1 && ( dateObject.month < originalDateObject.month || dateObject.month > originalDateObject.month ) ) {
506
- dateObject = originalDateObject
507
- interval = interval > 0 ? 1 : -1
508
- }
509
-
510
-
511
- // If we’ve reached the min/max limit, reverse the direction, flatten the interval and set it to the limit.
512
- if ( dateObject.pick <= minLimitObject.pick ) {
513
- reachedMin = true
514
- interval = 1
515
- dateObject = calendar.create([
516
- minLimitObject.year,
517
- minLimitObject.month,
518
- minLimitObject.date + (dateObject.pick === minLimitObject.pick ? 0 : -1)
519
- ])
520
- }
521
- else if ( dateObject.pick >= maxLimitObject.pick ) {
522
- reachedMax = true
523
- interval = -1
524
- dateObject = calendar.create([
525
- maxLimitObject.year,
526
- maxLimitObject.month,
527
- maxLimitObject.date + (dateObject.pick === maxLimitObject.pick ? 0 : 1)
528
- ])
529
- }
530
-
531
-
532
- // If we’ve reached both limits, just break out of the loop.
533
- if ( reachedMin && reachedMax ) {
534
- break
535
- }
536
-
537
-
538
- // Finally, create the shifted date using the interval and keep looping.
539
- dateObject = calendar.create([ dateObject.year, dateObject.month, dateObject.date + interval ])
540
- }
541
-
542
- } //endif
543
-
544
-
545
- // Return the date object settled on.
546
- return dateObject
547
- } //DatePicker.prototype.validate
548
-
549
-
550
- /**
551
- * Check if a date is disabled.
552
- */
553
- DatePicker.prototype.disabled = function( dateToVerify ) {
554
-
555
- var
556
- calendar = this,
557
-
558
- // Filter through the disabled dates to check if this is one.
559
- isDisabledMatch = calendar.item.disable.filter( function( dateToDisable ) {
560
-
561
- // If the date is a number, match the weekday with 0index and `firstDay` check.
562
- if ( _.isInteger( dateToDisable ) ) {
563
- return dateToVerify.day === ( calendar.settings.firstDay ? dateToDisable : dateToDisable - 1 ) % 7
564
- }
565
-
566
- // If it’s an array or a native JS date, create and match the exact date.
567
- if ( $.isArray( dateToDisable ) || _.isDate( dateToDisable ) ) {
568
- return dateToVerify.pick === calendar.create( dateToDisable ).pick
569
- }
570
-
571
- // If it’s an object, match a date within the “from” and “to” range.
572
- if ( $.isPlainObject( dateToDisable ) ) {
573
- return calendar.withinRange( dateToDisable, dateToVerify )
574
- }
575
- })
576
-
577
- // If this date matches a disabled date, confirm it’s not inverted.
578
- isDisabledMatch = isDisabledMatch.length && !isDisabledMatch.filter(function( dateToDisable ) {
579
- return $.isArray( dateToDisable ) && dateToDisable[3] == 'inverted' ||
580
- $.isPlainObject( dateToDisable ) && dateToDisable.inverted
581
- }).length
582
-
583
- // Check the calendar “enabled” flag and respectively flip the
584
- // disabled state. Then also check if it’s beyond the min/max limits.
585
- return calendar.item.enable === -1 ? !isDisabledMatch : isDisabledMatch ||
586
- dateToVerify.pick < calendar.item.min.pick ||
587
- dateToVerify.pick > calendar.item.max.pick
588
-
589
- } //DatePicker.prototype.disabled
590
-
591
-
592
- /**
593
- * Parse a string into a usable type.
594
- */
595
- DatePicker.prototype.parse = function( type, value, options ) {
596
-
597
- var calendar = this,
598
- parsingObject = {}
599
-
600
- // If it’s already parsed, we’re good.
601
- if ( !value || typeof value != 'string' ) {
602
- return value
603
- }
604
-
605
- // We need a `.format` to parse the value with.
606
- if ( !( options && options.format ) ) {
607
- options = options || {}
608
- options.format = calendar.settings.format
609
- }
610
-
611
- // Convert the format into an array and then map through it.
612
- calendar.formats.toArray( options.format ).map( function( label ) {
613
-
614
- var
615
- // Grab the formatting label.
616
- formattingLabel = calendar.formats[ label ],
617
-
618
- // The format length is from the formatting label function or the
619
- // label length without the escaping exclamation (!) mark.
620
- formatLength = formattingLabel ? _.trigger( formattingLabel, calendar, [ value, parsingObject ] ) : label.replace( /^!/, '' ).length
621
-
622
- // If there's a format label, split the value up to the format length.
623
- // Then add it to the parsing object with appropriate label.
624
- if ( formattingLabel ) {
625
- parsingObject[ label ] = value.substr( 0, formatLength )
626
- }
627
-
628
- // Update the value as the substring from format length to end.
629
- value = value.substr( formatLength )
630
- })
631
-
632
- // Compensate for month 0index.
633
- return [
634
- parsingObject.yyyy || parsingObject.yy,
635
- +( parsingObject.mm || parsingObject.m ) - 1,
636
- parsingObject.dd || parsingObject.d
637
- ]
638
- } //DatePicker.prototype.parse
639
-
640
-
641
- /**
642
- * Various formats to display the object in.
643
- */
644
- DatePicker.prototype.formats = (function() {
645
-
646
- // Return the length of the first word in a collection.
647
- function getWordLengthFromCollection( string, collection, dateObject ) {
648
-
649
- // Grab the first word from the string.
650
- // Regex pattern from http://stackoverflow.com/q/150033
651
- var word = string.match( /[^\x00-\x7F]+|\w+/ )[ 0 ]
652
-
653
- // If there's no month index, add it to the date object
654
- if ( !dateObject.mm && !dateObject.m ) {
655
- dateObject.m = collection.indexOf( word ) + 1
656
- }
657
-
658
- // Return the length of the word.
659
- return word.length
660
- }
661
-
662
- // Get the length of the first word in a string.
663
- function getFirstWordLength( string ) {
664
- return string.match( /\w+/ )[ 0 ].length
665
- }
666
-
667
- return {
668
-
669
- d: function( string, dateObject ) {
670
-
671
- // If there's string, then get the digits length.
672
- // Otherwise return the selected date.
673
- return string ? _.digits( string ) : dateObject.date
674
- },
675
- dd: function( string, dateObject ) {
676
-
677
- // If there's a string, then the length is always 2.
678
- // Otherwise return the selected date with a leading zero.
679
- return string ? 2 : _.lead( dateObject.date )
680
- },
681
- ddd: function( string, dateObject ) {
682
-
683
- // If there's a string, then get the length of the first word.
684
- // Otherwise return the short selected weekday.
685
- return string ? getFirstWordLength( string ) : this.settings.weekdaysShort[ dateObject.day ]
686
- },
687
- dddd: function( string, dateObject ) {
688
-
689
- // If there's a string, then get the length of the first word.
690
- // Otherwise return the full selected weekday.
691
- return string ? getFirstWordLength( string ) : this.settings.weekdaysFull[ dateObject.day ]
692
- },
693
- m: function( string, dateObject ) {
694
-
695
- // If there's a string, then get the length of the digits
696
- // Otherwise return the selected month with 0index compensation.
697
- return string ? _.digits( string ) : dateObject.month + 1
698
- },
699
- mm: function( string, dateObject ) {
700
-
701
- // If there's a string, then the length is always 2.
702
- // Otherwise return the selected month with 0index and leading zero.
703
- return string ? 2 : _.lead( dateObject.month + 1 )
704
- },
705
- mmm: function( string, dateObject ) {
706
-
707
- var collection = this.settings.monthsShort
708
-
709
- // If there's a string, get length of the relevant month from the short
710
- // months collection. Otherwise return the selected month from that collection.
711
- return string ? getWordLengthFromCollection( string, collection, dateObject ) : collection[ dateObject.month ]
712
- },
713
- mmmm: function( string, dateObject ) {
714
-
715
- var collection = this.settings.monthsFull
716
-
717
- // If there's a string, get length of the relevant month from the full
718
- // months collection. Otherwise return the selected month from that collection.
719
- return string ? getWordLengthFromCollection( string, collection, dateObject ) : collection[ dateObject.month ]
720
- },
721
- yy: function( string, dateObject ) {
722
-
723
- // If there's a string, then the length is always 2.
724
- // Otherwise return the selected year by slicing out the first 2 digits.
725
- return string ? 2 : ( '' + dateObject.year ).slice( 2 )
726
- },
727
- yyyy: function( string, dateObject ) {
728
-
729
- // If there's a string, then the length is always 4.
730
- // Otherwise return the selected year.
731
- return string ? 4 : dateObject.year
732
- },
733
-
734
- // Create an array by splitting the formatting string passed.
735
- toArray: function( formatString ) { return formatString.split( /(d{1,4}|m{1,4}|y{4}|yy|!.)/g ) },
736
-
737
- // Format an object into a string using the formatting options.
738
- toString: function ( formatString, itemObject ) {
739
- var calendar = this
740
- return calendar.formats.toArray( formatString ).map( function( label ) {
741
- return _.trigger( calendar.formats[ label ], calendar, [ 0, itemObject ] ) || label.replace( /^!/, '' )
742
- }).join( '' )
743
- }
744
- }
745
- })() //DatePicker.prototype.formats
746
-
747
-
748
-
749
-
750
- /**
751
- * Check if two date units are the exact.
752
- */
753
- DatePicker.prototype.isDateExact = function( one, two ) {
754
-
755
- var calendar = this
756
-
757
- // When we’re working with weekdays, do a direct comparison.
758
- if (
759
- ( _.isInteger( one ) && _.isInteger( two ) ) ||
760
- ( typeof one == 'boolean' && typeof two == 'boolean' )
761
- ) {
762
- return one === two
763
- }
764
-
765
- // When we’re working with date representations, compare the “pick” value.
766
- if (
767
- ( _.isDate( one ) || $.isArray( one ) ) &&
768
- ( _.isDate( two ) || $.isArray( two ) )
769
- ) {
770
- return calendar.create( one ).pick === calendar.create( two ).pick
771
- }
772
-
773
- // When we’re working with range objects, compare the “from” and “to”.
774
- if ( $.isPlainObject( one ) && $.isPlainObject( two ) ) {
775
- return calendar.isDateExact( one.from, two.from ) && calendar.isDateExact( one.to, two.to )
776
- }
777
-
778
- return false
779
- }
780
-
781
-
782
- /**
783
- * Check if two date units overlap.
784
- */
785
- DatePicker.prototype.isDateOverlap = function( one, two ) {
786
-
787
- var calendar = this,
788
- firstDay = calendar.settings.firstDay ? 1 : 0
789
-
790
- // When we’re working with a weekday index, compare the days.
791
- if ( _.isInteger( one ) && ( _.isDate( two ) || $.isArray( two ) ) ) {
792
- one = one % 7 + firstDay
793
- return one === calendar.create( two ).day + 1
794
- }
795
- if ( _.isInteger( two ) && ( _.isDate( one ) || $.isArray( one ) ) ) {
796
- two = two % 7 + firstDay
797
- return two === calendar.create( one ).day + 1
798
- }
799
-
800
- // When we’re working with range objects, check if the ranges overlap.
801
- if ( $.isPlainObject( one ) && $.isPlainObject( two ) ) {
802
- return calendar.overlapRanges( one, two )
803
- }
804
-
805
- return false
806
- }
807
-
808
-
809
- /**
810
- * Flip the “enabled” state.
811
- */
812
- DatePicker.prototype.flipEnable = function(val) {
813
- var itemObject = this.item
814
- itemObject.enable = val || (itemObject.enable == -1 ? 1 : -1)
815
- }
816
-
817
-
818
- /**
819
- * Mark a collection of dates as “disabled”.
820
- */
821
- DatePicker.prototype.deactivate = function( type, datesToDisable ) {
822
-
823
- var calendar = this,
824
- disabledItems = calendar.item.disable.slice(0)
825
-
826
-
827
- // If we’re flipping, that’s all we need to do.
828
- if ( datesToDisable == 'flip' ) {
829
- calendar.flipEnable()
830
- }
831
-
832
- else if ( datesToDisable === false ) {
833
- calendar.flipEnable(1)
834
- disabledItems = []
835
- }
836
-
837
- else if ( datesToDisable === true ) {
838
- calendar.flipEnable(-1)
839
- disabledItems = []
840
- }
841
-
842
- // Otherwise go through the dates to disable.
843
- else {
844
-
845
- datesToDisable.map(function( unitToDisable ) {
846
-
847
- var matchFound
848
-
849
- // When we have disabled items, check for matches.
850
- // If something is matched, immediately break out.
851
- for ( var index = 0; index < disabledItems.length; index += 1 ) {
852
- if ( calendar.isDateExact( unitToDisable, disabledItems[index] ) ) {
853
- matchFound = true
854
- break
855
- }
856
- }
857
-
858
- // If nothing was found, add the validated unit to the collection.
859
- if ( !matchFound ) {
860
- if (
861
- _.isInteger( unitToDisable ) ||
862
- _.isDate( unitToDisable ) ||
863
- $.isArray( unitToDisable ) ||
864
- ( $.isPlainObject( unitToDisable ) && unitToDisable.from && unitToDisable.to )
865
- ) {
866
- disabledItems.push( unitToDisable )
867
- }
868
- }
869
- })
870
- }
871
-
872
- // Return the updated collection.
873
- return disabledItems
874
- } //DatePicker.prototype.deactivate
875
-
876
-
877
- /**
878
- * Mark a collection of dates as “enabled”.
879
- */
880
- DatePicker.prototype.activate = function( type, datesToEnable ) {
881
-
882
- var calendar = this,
883
- disabledItems = calendar.item.disable,
884
- disabledItemsCount = disabledItems.length
885
-
886
- // If we’re flipping, that’s all we need to do.
887
- if ( datesToEnable == 'flip' ) {
888
- calendar.flipEnable()
889
- }
890
-
891
- else if ( datesToEnable === true ) {
892
- calendar.flipEnable(1)
893
- disabledItems = []
894
- }
895
-
896
- else if ( datesToEnable === false ) {
897
- calendar.flipEnable(-1)
898
- disabledItems = []
899
- }
900
-
901
- // Otherwise go through the disabled dates.
902
- else {
903
-
904
- datesToEnable.map(function( unitToEnable ) {
905
-
906
- var matchFound,
907
- disabledUnit,
908
- index,
909
- isExactRange
910
-
911
- // Go through the disabled items and try to find a match.
912
- for ( index = 0; index < disabledItemsCount; index += 1 ) {
913
-
914
- disabledUnit = disabledItems[index]
915
-
916
- // When an exact match is found, remove it from the collection.
917
- if ( calendar.isDateExact( disabledUnit, unitToEnable ) ) {
918
- matchFound = disabledItems[index] = null
919
- isExactRange = true
920
- break
921
- }
922
-
923
- // When an overlapped match is found, add the “inverted” state to it.
924
- else if ( calendar.isDateOverlap( disabledUnit, unitToEnable ) ) {
925
- if ( $.isPlainObject( unitToEnable ) ) {
926
- unitToEnable.inverted = true
927
- matchFound = unitToEnable
928
- }
929
- else if ( $.isArray( unitToEnable ) ) {
930
- matchFound = unitToEnable
931
- if ( !matchFound[3] ) matchFound.push( 'inverted' )
932
- }
933
- else if ( _.isDate( unitToEnable ) ) {
934
- matchFound = [ unitToEnable.getFullYear(), unitToEnable.getMonth(), unitToEnable.getDate(), 'inverted' ]
935
- }
936
- break
937
- }
938
- }
939
-
940
- // If a match was found, remove a previous duplicate entry.
941
- if ( matchFound ) for ( index = 0; index < disabledItemsCount; index += 1 ) {
942
- if ( calendar.isDateExact( disabledItems[index], unitToEnable ) ) {
943
- disabledItems[index] = null
944
- break
945
- }
946
- }
947
-
948
- // In the event that we’re dealing with an exact range of dates,
949
- // make sure there are no “inverted” dates because of it.
950
- if ( isExactRange ) for ( index = 0; index < disabledItemsCount; index += 1 ) {
951
- if ( calendar.isDateOverlap( disabledItems[index], unitToEnable ) ) {
952
- disabledItems[index] = null
953
- break
954
- }
955
- }
956
-
957
- // If something is still matched, add it into the collection.
958
- if ( matchFound ) {
959
- disabledItems.push( matchFound )
960
- }
961
- })
962
- }
963
-
964
- // Return the updated collection.
965
- return disabledItems.filter(function( val ) { return val != null })
966
- } //DatePicker.prototype.activate
967
-
968
-
969
- /**
970
- * Create a string for the nodes in the picker.
971
- */
972
- DatePicker.prototype.nodes = function( isOpen ) {
973
-
974
- var
975
- calendar = this,
976
- settings = calendar.settings,
977
- calendarItem = calendar.item,
978
- nowObject = calendarItem.now,
979
- selectedObject = calendarItem.select,
980
- highlightedObject = calendarItem.highlight,
981
- viewsetObject = calendarItem.view,
982
- disabledCollection = calendarItem.disable,
983
- minLimitObject = calendarItem.min,
984
- maxLimitObject = calendarItem.max,
985
-
986
-
987
- // Create the calendar table head using a copy of weekday labels collection.
988
- // * We do a copy so we don't mutate the original array.
989
- tableHead = (function( collection, fullCollection ) {
990
-
991
- // If the first day should be Monday, move Sunday to the end.
992
- if ( settings.firstDay ) {
993
- collection.push( collection.shift() )
994
- fullCollection.push( fullCollection.shift() )
995
- }
996
-
997
- // Create and return the table head group.
998
- return _.node(
999
- 'thead',
1000
- _.node(
1001
- 'tr',
1002
- _.group({
1003
- min: 0,
1004
- max: DAYS_IN_WEEK - 1,
1005
- i: 1,
1006
- node: 'th',
1007
- item: function( counter ) {
1008
- return [
1009
- collection[ counter ],
1010
- settings.klass.weekdays,
1011
- 'scope=col title="' + fullCollection[ counter ] + '"'
1012
- ]
1013
- }
1014
- })
1015
- )
1016
- ) //endreturn
1017
- })( ( settings.showWeekdaysFull ? settings.weekdaysFull : settings.weekdaysShort ).slice( 0 ), settings.weekdaysFull.slice( 0 ) ), //tableHead
1018
-
1019
-
1020
- // Create the nav for next/prev month.
1021
- createMonthNav = function( next ) {
1022
-
1023
- // Otherwise, return the created month tag.
1024
- return _.node(
1025
- 'div',
1026
- ' ',
1027
- settings.klass[ 'nav' + ( next ? 'Next' : 'Prev' ) ] + (
1028
-
1029
- // If the focused month is outside the range, disabled the button.
1030
- ( next && viewsetObject.year >= maxLimitObject.year && viewsetObject.month >= maxLimitObject.month ) ||
1031
- ( !next && viewsetObject.year <= minLimitObject.year && viewsetObject.month <= minLimitObject.month ) ?
1032
- ' ' + settings.klass.navDisabled : ''
1033
- ),
1034
- 'data-nav=' + ( next || -1 ) + ' ' +
1035
- _.ariaAttr({
1036
- role: 'button',
1037
- controls: calendar.$node[0].id + '_table'
1038
- }) + ' ' +
1039
- 'title="' + (next ? settings.labelMonthNext : settings.labelMonthPrev ) + '"'
1040
- ) //endreturn
1041
- }, //createMonthNav
1042
-
1043
-
1044
- // Create the month label.
1045
- createMonthLabel = function() {
1046
-
1047
- var monthsCollection = settings.showMonthsShort ? settings.monthsShort : settings.monthsFull
1048
-
1049
- // If there are months to select, add a dropdown menu.
1050
- if ( settings.selectMonths ) {
1051
-
1052
- return _.node( 'select',
1053
- _.group({
1054
- min: 0,
1055
- max: 11,
1056
- i: 1,
1057
- node: 'option',
1058
- item: function( loopedMonth ) {
1059
-
1060
- return [
1061
-
1062
- // The looped month and no classes.
1063
- monthsCollection[ loopedMonth ], 0,
1064
-
1065
- // Set the value and selected index.
1066
- 'value=' + loopedMonth +
1067
- ( viewsetObject.month == loopedMonth ? ' selected' : '' ) +
1068
- (
1069
- (
1070
- ( viewsetObject.year == minLimitObject.year && loopedMonth < minLimitObject.month ) ||
1071
- ( viewsetObject.year == maxLimitObject.year && loopedMonth > maxLimitObject.month )
1072
- ) ?
1073
- ' disabled' : ''
1074
- )
1075
- ]
1076
- }
1077
- }),
1078
- settings.klass.selectMonth,
1079
- ( isOpen ? '' : 'disabled' ) + ' ' +
1080
- _.ariaAttr({ controls: calendar.$node[0].id + '_table' }) + ' ' +
1081
- 'title="' + settings.labelMonthSelect + '"'
1082
- )
1083
- }
1084
-
1085
- // If there's a need for a month selector
1086
- return _.node( 'div', monthsCollection[ viewsetObject.month ], settings.klass.month )
1087
- }, //createMonthLabel
1088
-
1089
-
1090
- // Create the year label.
1091
- createYearLabel = function() {
1092
-
1093
- var focusedYear = viewsetObject.year,
1094
-
1095
- // If years selector is set to a literal "true", set it to 5. Otherwise
1096
- // divide in half to get half before and half after focused year.
1097
- numberYears = settings.selectYears === true ? 5 : ~~( settings.selectYears / 2 )
1098
-
1099
- // If there are years to select, add a dropdown menu.
1100
- if ( numberYears ) {
1101
-
1102
- var
1103
- minYear = minLimitObject.year,
1104
- maxYear = maxLimitObject.year,
1105
- lowestYear = focusedYear - numberYears,
1106
- highestYear = focusedYear + numberYears
1107
-
1108
- // If the min year is greater than the lowest year, increase the highest year
1109
- // by the difference and set the lowest year to the min year.
1110
- if ( minYear > lowestYear ) {
1111
- highestYear += minYear - lowestYear
1112
- lowestYear = minYear
1113
- }
1114
-
1115
- // If the max year is less than the highest year, decrease the lowest year
1116
- // by the lower of the two: available and needed years. Then set the
1117
- // highest year to the max year.
1118
- if ( maxYear < highestYear ) {
1119
-
1120
- var availableYears = lowestYear - minYear,
1121
- neededYears = highestYear - maxYear
1122
-
1123
- lowestYear -= availableYears > neededYears ? neededYears : availableYears
1124
- highestYear = maxYear
1125
- }
1126
-
1127
- return _.node( 'select',
1128
- _.group({
1129
- min: lowestYear,
1130
- max: highestYear,
1131
- i: 1,
1132
- node: 'option',
1133
- item: function( loopedYear ) {
1134
- return [
1135
-
1136
- // The looped year and no classes.
1137
- loopedYear, 0,
1138
-
1139
- // Set the value and selected index.
1140
- 'value=' + loopedYear + ( focusedYear == loopedYear ? ' selected' : '' )
1141
- ]
1142
- }
1143
- }),
1144
- settings.klass.selectYear,
1145
- ( isOpen ? '' : 'disabled' ) + ' ' + _.ariaAttr({ controls: calendar.$node[0].id + '_table' }) + ' ' +
1146
- 'title="' + settings.labelYearSelect + '"'
1147
- )
1148
- }
1149
-
1150
- // Otherwise just return the year focused
1151
- return _.node( 'div', focusedYear, settings.klass.year )
1152
- } //createYearLabel
1153
-
1154
-
1155
- // Create and return the entire calendar.
1156
- return _.node(
1157
- 'div',
1158
- ( settings.selectYears ? createYearLabel() + createMonthLabel() : createMonthLabel() + createYearLabel() ) +
1159
- createMonthNav() + createMonthNav( 1 ),
1160
- settings.klass.header
1161
- ) + _.node(
1162
- 'table',
1163
- tableHead +
1164
- _.node(
1165
- 'tbody',
1166
- _.group({
1167
- min: 0,
1168
- max: WEEKS_IN_CALENDAR - 1,
1169
- i: 1,
1170
- node: 'tr',
1171
- item: function( rowCounter ) {
1172
-
1173
- // If Monday is the first day and the month starts on Sunday, shift the date back a week.
1174
- var shiftDateBy = settings.firstDay && calendar.create([ viewsetObject.year, viewsetObject.month, 1 ]).day === 0 ? -7 : 0
1175
-
1176
- return [
1177
- _.group({
1178
- min: DAYS_IN_WEEK * rowCounter - viewsetObject.day + shiftDateBy + 1, // Add 1 for weekday 0index
1179
- max: function() {
1180
- return this.min + DAYS_IN_WEEK - 1
1181
- },
1182
- i: 1,
1183
- node: 'td',
1184
- item: function( targetDate ) {
1185
-
1186
- // Convert the time date from a relative date to a target date.
1187
- targetDate = calendar.create([ viewsetObject.year, viewsetObject.month, targetDate + ( settings.firstDay ? 1 : 0 ) ])
1188
-
1189
- var isSelected = selectedObject && selectedObject.pick == targetDate.pick,
1190
- isHighlighted = highlightedObject && highlightedObject.pick == targetDate.pick,
1191
- isDisabled = disabledCollection && calendar.disabled( targetDate ) || targetDate.pick < minLimitObject.pick || targetDate.pick > maxLimitObject.pick,
1192
- formattedDate = _.trigger( calendar.formats.toString, calendar, [ settings.format, targetDate ] )
1193
-
1194
- return [
1195
- _.node(
1196
- 'div',
1197
- targetDate.date,
1198
- (function( klasses ) {
1199
-
1200
- // Add the `infocus` or `outfocus` classes based on month in view.
1201
- klasses.push( viewsetObject.month == targetDate.month ? settings.klass.infocus : settings.klass.outfocus )
1202
-
1203
- // Add the `today` class if needed.
1204
- if ( nowObject.pick == targetDate.pick ) {
1205
- klasses.push( settings.klass.now )
1206
- }
1207
-
1208
- // Add the `selected` class if something's selected and the time matches.
1209
- if ( isSelected ) {
1210
- klasses.push( settings.klass.selected )
1211
- }
1212
-
1213
- // Add the `highlighted` class if something's highlighted and the time matches.
1214
- if ( isHighlighted ) {
1215
- klasses.push( settings.klass.highlighted )
1216
- }
1217
-
1218
- // Add the `disabled` class if something's disabled and the object matches.
1219
- if ( isDisabled ) {
1220
- klasses.push( settings.klass.disabled )
1221
- }
1222
-
1223
- return klasses.join( ' ' )
1224
- })([ settings.klass.day ]),
1225
- 'data-pick=' + targetDate.pick + ' ' + _.ariaAttr({
1226
- role: 'gridcell',
1227
- label: formattedDate,
1228
- selected: isSelected && calendar.$node.val() === formattedDate ? true : null,
1229
- activedescendant: isHighlighted ? true : null,
1230
- disabled: isDisabled ? true : null
1231
- })
1232
- ),
1233
- '',
1234
- _.ariaAttr({ role: 'presentation' })
1235
- ] //endreturn
1236
- }
1237
- })
1238
- ] //endreturn
1239
- }
1240
- })
1241
- ),
1242
- settings.klass.table,
1243
- 'id="' + calendar.$node[0].id + '_table' + '" ' + _.ariaAttr({
1244
- role: 'grid',
1245
- controls: calendar.$node[0].id,
1246
- readonly: true
1247
- })
1248
- ) +
1249
-
1250
- // * For Firefox forms to submit, make sure to set the buttons’ `type` attributes as “button”.
1251
- _.node(
1252
- 'div',
1253
- _.node( 'button', settings.today, settings.klass.buttonToday,
1254
- 'type=button data-pick=' + nowObject.pick +
1255
- ( isOpen && !calendar.disabled(nowObject) ? '' : ' disabled' ) + ' ' +
1256
- _.ariaAttr({ controls: calendar.$node[0].id }) ) +
1257
- _.node( 'button', settings.clear, settings.klass.buttonClear,
1258
- 'type=button data-clear=1' +
1259
- ( isOpen ? '' : ' disabled' ) + ' ' +
1260
- _.ariaAttr({ controls: calendar.$node[0].id }) ) +
1261
- _.node('button', settings.close, settings.klass.buttonClose,
1262
- 'type=button data-close=true ' +
1263
- ( isOpen ? '' : ' disabled' ) + ' ' +
1264
- _.ariaAttr({ controls: calendar.$node[0].id }) ),
1265
- settings.klass.footer
1266
- ) //endreturn
1267
- } //DatePicker.prototype.nodes
1268
-
1269
-
1270
-
1271
-
1272
- /**
1273
- * The date picker defaults.
1274
- */
1275
- DatePicker.defaults = (function( prefix ) {
1276
-
1277
- return {
1278
-
1279
- // The title label to use for the month nav buttons
1280
- labelMonthNext: 'Next month',
1281
- labelMonthPrev: 'Previous month',
1282
-
1283
- // The title label to use for the dropdown selectors
1284
- labelMonthSelect: 'Select a month',
1285
- labelYearSelect: 'Select a year',
1286
-
1287
- // Months and weekdays
1288
- monthsFull: [ 'January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December' ],
1289
- monthsShort: [ 'Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec' ],
1290
- weekdaysFull: [ 'Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday' ],
1291
- weekdaysShort: [ 'Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat' ],
1292
-
1293
- // Today and clear
1294
- today: 'Today',
1295
- clear: 'Clear',
1296
- close: 'Close',
1297
-
1298
- // Picker close behavior
1299
- closeOnSelect: true,
1300
- closeOnClear: true,
1301
-
1302
- // The format to show on the `input` element
1303
- format: 'd mmmm, yyyy',
1304
-
1305
- // Classes
1306
- klass: {
1307
-
1308
- table: prefix + 'table',
1309
-
1310
- header: prefix + 'header',
1311
-
1312
- navPrev: prefix + 'nav--prev',
1313
- navNext: prefix + 'nav--next',
1314
- navDisabled: prefix + 'nav--disabled',
1315
-
1316
- month: prefix + 'month',
1317
- year: prefix + 'year',
1318
-
1319
- selectMonth: prefix + 'select--month',
1320
- selectYear: prefix + 'select--year',
1321
-
1322
- weekdays: prefix + 'weekday',
1323
-
1324
- day: prefix + 'day',
1325
- disabled: prefix + 'day--disabled',
1326
- selected: prefix + 'day--selected',
1327
- highlighted: prefix + 'day--highlighted',
1328
- now: prefix + 'day--today',
1329
- infocus: prefix + 'day--infocus',
1330
- outfocus: prefix + 'day--outfocus',
1331
-
1332
- footer: prefix + 'footer',
1333
-
1334
- buttonClear: prefix + 'button--clear',
1335
- buttonToday: prefix + 'button--today',
1336
- buttonClose: prefix + 'button--close'
1337
- }
1338
- }
1339
- })( Picker.klasses().picker + '__' )
1340
-
1341
-
1342
-
1343
-
1344
-
1345
- /**
1346
- * Extend the picker to add the date picker.
1347
- */
1348
- Picker.extend( 'pickadate', DatePicker )
1349
-
1350
-
1351
- }));
1352
-
1353
-
1354
-
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
assets/js/jquery.picker.js DELETED
@@ -1,1163 +0,0 @@
1
- /*!
2
- * pickadate.js v3.5.6, 2015/04/20
3
- * By Amsul, http://amsul.ca
4
- * Hosted on http://amsul.github.io/pickadate.js
5
- * Licensed under MIT
6
- */
7
-
8
- (function ( factory ) {
9
-
10
- // AMD.
11
- if ( typeof define == 'function' && define.amd )
12
- define( 'picker', ['jquery'], factory )
13
-
14
- // Node.js/browserify.
15
- else if ( typeof exports == 'object' )
16
- module.exports = factory( require('jquery') )
17
-
18
- // Browser globals.
19
- else this.Picker = factory( jQuery )
20
-
21
- }(function( $ ) {
22
-
23
- var $window = $( window )
24
- var $document = $( document )
25
- var $html = $( document.documentElement )
26
- var supportsTransitions = document.documentElement.style.transition != null
27
-
28
-
29
- /**
30
- * The picker constructor that creates a blank picker.
31
- */
32
- function PickerConstructor( ELEMENT, NAME, COMPONENT, OPTIONS ) {
33
-
34
- // If there’s no element, return the picker constructor.
35
- if ( !ELEMENT ) return PickerConstructor
36
-
37
-
38
- var
39
- IS_DEFAULT_THEME = false,
40
-
41
-
42
- // The state of the picker.
43
- STATE = {
44
- id: ELEMENT.id || 'P' + Math.abs( ~~(Math.random() * new Date()) )
45
- },
46
-
47
-
48
- // Merge the defaults and options passed.
49
- SETTINGS = COMPONENT ? $.extend( true, {}, COMPONENT.defaults, OPTIONS ) : OPTIONS || {},
50
-
51
-
52
- // Merge the default classes with the settings classes.
53
- CLASSES = $.extend( {}, PickerConstructor.klasses(), SETTINGS.klass ),
54
-
55
-
56
- // The element node wrapper into a jQuery object.
57
- $ELEMENT = $( ELEMENT ),
58
-
59
-
60
- // Pseudo picker constructor.
61
- PickerInstance = function() {
62
- return this.start()
63
- },
64
-
65
-
66
- // The picker prototype.
67
- P = PickerInstance.prototype = {
68
-
69
- constructor: PickerInstance,
70
-
71
- $node: $ELEMENT,
72
-
73
-
74
- /**
75
- * Initialize everything
76
- */
77
- start: function() {
78
-
79
- // If it’s already started, do nothing.
80
- if ( STATE && STATE.start ) return P
81
-
82
-
83
- // Update the picker states.
84
- STATE.methods = {}
85
- STATE.start = true
86
- STATE.open = false
87
- STATE.type = ELEMENT.type
88
-
89
-
90
- // Confirm focus state, convert into text input to remove UA stylings,
91
- // and set as readonly to prevent keyboard popup.
92
- ELEMENT.autofocus = ELEMENT == getActiveElement()
93
- ELEMENT.readOnly = !SETTINGS.editable
94
- ELEMENT.id = ELEMENT.id || STATE.id
95
- if ( ELEMENT.type != 'text' ) {
96
- ELEMENT.type = 'text'
97
- }
98
-
99
-
100
- // Create a new picker component with the settings.
101
- P.component = new COMPONENT(P, SETTINGS)
102
-
103
-
104
- // Create the picker root and then prepare it.
105
- P.$root = $( '<div class="' + CLASSES.picker + '" id="' + ELEMENT.id + '_root" />' )
106
- prepareElementRoot()
107
-
108
-
109
- // Create the picker holder and then prepare it.
110
- P.$holder = $( createWrappedComponent() ).appendTo( P.$root )
111
- prepareElementHolder()
112
-
113
-
114
- // If there’s a format for the hidden input element, create the element.
115
- if ( SETTINGS.formatSubmit ) {
116
- prepareElementHidden()
117
- }
118
-
119
-
120
- // Prepare the input element.
121
- prepareElement()
122
-
123
-
124
- // Insert the hidden input as specified in the settings.
125
- if ( SETTINGS.containerHidden ) $( SETTINGS.containerHidden ).append( P._hidden )
126
- else $ELEMENT.after( P._hidden )
127
-
128
-
129
- // Insert the root as specified in the settings.
130
- if ( SETTINGS.container ) $( SETTINGS.container ).append( P.$root )
131
- else $ELEMENT.after( P.$root )
132
-
133
-
134
- // Bind the default component and settings events.
135
- P.on({
136
- start: P.component.onStart,
137
- render: P.component.onRender,
138
- stop: P.component.onStop,
139
- open: P.component.onOpen,
140
- close: P.component.onClose,
141
- set: P.component.onSet
142
- }).on({
143
- start: SETTINGS.onStart,
144
- render: SETTINGS.onRender,
145
- stop: SETTINGS.onStop,
146
- open: SETTINGS.onOpen,
147
- close: SETTINGS.onClose,
148
- set: SETTINGS.onSet
149
- })
150
-
151
-
152
- // Once we’re all set, check the theme in use.
153
- IS_DEFAULT_THEME = isUsingDefaultTheme( P.$holder[0] )
154
-
155
-
156
- // If the element has autofocus, open the picker.
157
- if ( ELEMENT.autofocus ) {
158
- P.open()
159
- }
160
-
161
-
162
- // Trigger queued the “start” and “render” events.
163
- return P.trigger( 'start' ).trigger( 'render' )
164
- }, //start
165
-
166
-
167
- /**
168
- * Render a new picker
169
- */
170
- render: function( entireComponent ) {
171
-
172
- // Insert a new component holder in the root or box.
173
- if ( entireComponent ) {
174
- P.$holder = $( createWrappedComponent() )
175
- prepareElementHolder()
176
- P.$root.html( P.$holder )
177
- }
178
- else P.$root.find( '.' + CLASSES.box ).html( P.component.nodes( STATE.open ) )
179
-
180
- // Trigger the queued “render” events.
181
- return P.trigger( 'render' )
182
- }, //render
183
-
184
-
185
- /**
186
- * Destroy everything
187
- */
188
- stop: function() {
189
-
190
- // If it’s already stopped, do nothing.
191
- if ( !STATE.start ) return P
192
-
193
- // Then close the picker.
194
- P.close()
195
-
196
- // Remove the hidden field.
197
- if ( P._hidden ) {
198
- P._hidden.parentNode.removeChild( P._hidden )
199
- }
200
-
201
- // Remove the root.
202
- P.$root.remove()
203
-
204
- // Remove the input class, remove the stored data, and unbind
205
- // the events (after a tick for IE - see `P.close`).
206
- $ELEMENT.removeClass( CLASSES.input ).removeData( NAME )
207
- setTimeout( function() {
208
- $ELEMENT.off( '.' + STATE.id )
209
- }, 0)
210
-
211
- // Restore the element state
212
- ELEMENT.type = STATE.type
213
- ELEMENT.readOnly = false
214
-
215
- // Trigger the queued “stop” events.
216
- P.trigger( 'stop' )
217
-
218
- // Reset the picker states.
219
- STATE.methods = {}
220
- STATE.start = false
221
-
222
- return P
223
- }, //stop
224
-
225
-
226
- /**
227
- * Open up the picker
228
- */
229
- open: function( dontGiveFocus ) {
230
-
231
- // If it’s already open, do nothing.
232
- if ( STATE.open ) return P
233
-
234
- // Add the “active” class.
235
- $ELEMENT.addClass( CLASSES.active )
236
- aria( ELEMENT, 'expanded', true )
237
-
238
- // * A Firefox bug, when `html` has `overflow:hidden`, results in
239
- // killing transitions :(. So add the “opened” state on the next tick.
240
- // Bug: https://bugzilla.mozilla.org/show_bug.cgi?id=625289
241
- setTimeout( function() {
242
-
243
- // Add the “opened” class to the picker root.
244
- P.$root.addClass( CLASSES.opened )
245
- aria( P.$root[0], 'hidden', false )
246
-
247
- }, 0 )
248
-
249
- // If we have to give focus, bind the element and doc events.
250
- if ( dontGiveFocus !== false ) {
251
-
252
- // Set it as open.
253
- STATE.open = true
254
-
255
- // Prevent the page from scrolling.
256
- if ( IS_DEFAULT_THEME ) {
257
- $html.
258
- css( 'overflow', 'hidden' ).
259
- css( 'padding-right', '+=' + getScrollbarWidth() )
260
- }
261
-
262
- // Pass focus to the root element’s jQuery object.
263
- focusPickerOnceOpened()
264
-
265
- // Bind the document events.
266
- $document.on( 'click.' + STATE.id + ' focusin.' + STATE.id, function( event ) {
267
-
268
- var target = event.target
269
-
270
- // If the target of the event is not the element, close the picker picker.
271
- // * Don’t worry about clicks or focusins on the root because those don’t bubble up.
272
- // Also, for Firefox, a click on an `option` element bubbles up directly
273
- // to the doc. So make sure the target wasn't the doc.
274
- // * In Firefox stopPropagation() doesn’t prevent right-click events from bubbling,
275
- // which causes the picker to unexpectedly close when right-clicking it. So make
276
- // sure the event wasn’t a right-click.
277
- if ( target != ELEMENT && target != document && event.which != 3 ) {
278
-
279
- // If the target was the holder that covers the screen,
280
- // keep the element focused to maintain tabindex.
281
- P.close( target === P.$holder[0] )
282
- }
283
-
284
- }).on( 'keydown.' + STATE.id, function( event ) {
285
-
286
- var
287
- // Get the keycode.
288
- keycode = event.keyCode,
289
-
290
- // Translate that to a selection change.
291
- keycodeToMove = P.component.key[ keycode ],
292
-
293
- // Grab the target.
294
- target = event.target
295
-
296
-
297
- // On escape, close the picker and give focus.
298
- if ( keycode == 27 ) {
299
- P.close( true )
300
- }
301
-
302
-
303
- // Check if there is a key movement or “enter” keypress on the element.
304
- else if ( target == P.$holder[0] && ( keycodeToMove || keycode == 13 ) ) {
305
-
306
- // Prevent the default action to stop page movement.
307
- event.preventDefault()
308
-
309
- // Trigger the key movement action.
310
- if ( keycodeToMove ) {
311
- PickerConstructor._.trigger( P.component.key.go, P, [ PickerConstructor._.trigger( keycodeToMove ) ] )
312
- }
313
-
314
- // On “enter”, if the highlighted item isn’t disabled, set the value and close.
315
- else if ( !P.$root.find( '.' + CLASSES.highlighted ).hasClass( CLASSES.disabled ) ) {
316
- P.set( 'select', P.component.item.highlight )
317
- if ( SETTINGS.closeOnSelect ) {
318
- P.close( true )
319
- }
320
- }
321
- }
322
-
323
-
324
- // If the target is within the root and “enter” is pressed,
325
- // prevent the default action and trigger a click on the target instead.
326
- else if ( $.contains( P.$root[0], target ) && keycode == 13 ) {
327
- event.preventDefault()
328
- target.click()
329
- }
330
- })
331
- }
332
-
333
- // Trigger the queued “open” events.
334
- return P.trigger( 'open' )
335
- }, //open
336
-
337
-
338
- /**
339
- * Close the picker
340
- */
341
- close: function( giveFocus ) {
342
-
343
- // If we need to give focus, do it before changing states.
344
- if ( giveFocus ) {
345
- if ( SETTINGS.editable ) {
346
- ELEMENT.focus()
347
- }
348
- else {
349
- // ....ah yes! It would’ve been incomplete without a crazy workaround for IE :|
350
- // The focus is triggered *after* the close has completed - causing it
351
- // to open again. So unbind and rebind the event at the next tick.
352
- P.$holder.off( 'focus.toOpen' ).focus()
353
- setTimeout( function() {
354
- P.$holder.on( 'focus.toOpen', handleFocusToOpenEvent )
355
- }, 0 )
356
- }
357
- }
358
-
359
- // Remove the “active” class.
360
- $ELEMENT.removeClass( CLASSES.active )
361
- aria( ELEMENT, 'expanded', false )
362
-
363
- // * A Firefox bug, when `html` has `overflow:hidden`, results in
364
- // killing transitions :(. So remove the “opened” state on the next tick.
365
- // Bug: https://bugzilla.mozilla.org/show_bug.cgi?id=625289
366
- setTimeout( function() {
367
-
368
- // Remove the “opened” and “focused” class from the picker root.
369
- P.$root.removeClass( CLASSES.opened + ' ' + CLASSES.focused )
370
- aria( P.$root[0], 'hidden', true )
371
-
372
- }, 0 )
373
-
374
- // If it’s already closed, do nothing more.
375
- if ( !STATE.open ) return P
376
-
377
- // Set it as closed.
378
- STATE.open = false
379
-
380
- // Allow the page to scroll.
381
- if ( IS_DEFAULT_THEME ) {
382
- $html.
383
- css( 'overflow', '' ).
384
- css( 'padding-right', '-=' + getScrollbarWidth() )
385
- }
386
-
387
- // Unbind the document events.
388
- $document.off( '.' + STATE.id )
389
-
390
- // Trigger the queued “close” events.
391
- return P.trigger( 'close' )
392
- }, //close
393
-
394
-
395
- /**
396
- * Clear the values
397
- */
398
- clear: function( options ) {
399
- return P.set( 'clear', null, options )
400
- }, //clear
401
-
402
-
403
- /**
404
- * Set something
405
- */
406
- set: function( thing, value, options ) {
407
-
408
- var thingItem, thingValue,
409
- thingIsObject = $.isPlainObject( thing ),
410
- thingObject = thingIsObject ? thing : {}
411
-
412
- // Make sure we have usable options.
413
- options = thingIsObject && $.isPlainObject( value ) ? value : options || {}
414
-
415
- if ( thing ) {
416
-
417
- // If the thing isn’t an object, make it one.
418
- if ( !thingIsObject ) {
419
- thingObject[ thing ] = value
420
- }
421
-
422
- // Go through the things of items to set.
423
- for ( thingItem in thingObject ) {
424
-
425
- // Grab the value of the thing.
426
- thingValue = thingObject[ thingItem ]
427
-
428
- // First, if the item exists and there’s a value, set it.
429
- if ( thingItem in P.component.item ) {
430
- if ( thingValue === undefined ) thingValue = null
431
- P.component.set( thingItem, thingValue, options )
432
- }
433
-
434
- // Then, check to update the element value and broadcast a change.
435
- if ( thingItem == 'select' || thingItem == 'clear' ) {
436
- $ELEMENT.
437
- val( thingItem == 'clear' ? '' : P.get( thingItem, SETTINGS.format ) ).
438
- trigger( 'change' )
439
- }
440
- }
441
-
442
- // Render a new picker.
443
- P.render()
444
- }
445
-
446
- // When the method isn’t muted, trigger queued “set” events and pass the `thingObject`.
447
- return options.muted ? P : P.trigger( 'set', thingObject )
448
- }, //set
449
-
450
-
451
- /**
452
- * Get something
453
- */
454
- get: function( thing, format ) {
455
-
456
- // Make sure there’s something to get.
457
- thing = thing || 'value'
458
-
459
- // If a picker state exists, return that.
460
- if ( STATE[ thing ] != null ) {
461
- return STATE[ thing ]
462
- }
463
-
464
- // Return the submission value, if that.
465
- if ( thing == 'valueSubmit' ) {
466
- if ( P._hidden ) {
467
- return P._hidden.value
468
- }
469
- thing = 'value'
470
- }
471
-
472
- // Return the value, if that.
473
- if ( thing == 'value' ) {
474
- return ELEMENT.value
475
- }
476
-
477
- // Check if a component item exists, return that.
478
- if ( thing in P.component.item ) {
479
- if ( typeof format == 'string' ) {
480
- var thingValue = P.component.get( thing )
481
- return thingValue ?
482
- PickerConstructor._.trigger(
483
- P.component.formats.toString,
484
- P.component,
485
- [ format, thingValue ]
486
- ) : ''
487
- }
488
- return P.component.get( thing )
489
- }
490
- }, //get
491
-
492
-
493
-
494
- /**
495
- * Bind events on the things.
496
- */
497
- on: function( thing, method, internal ) {
498
-
499
- var thingName, thingMethod,
500
- thingIsObject = $.isPlainObject( thing ),
501
- thingObject = thingIsObject ? thing : {}
502
-
503
- if ( thing ) {
504
-
505
- // If the thing isn’t an object, make it one.
506
- if ( !thingIsObject ) {
507
- thingObject[ thing ] = method
508
- }
509
-
510
- // Go through the things to bind to.
511
- for ( thingName in thingObject ) {
512
-
513
- // Grab the method of the thing.
514
- thingMethod = thingObject[ thingName ]
515
-
516
- // If it was an internal binding, prefix it.
517
- if ( internal ) {
518
- thingName = '_' + thingName
519
- }
520
-
521
- // Make sure the thing methods collection exists.
522
- STATE.methods[ thingName ] = STATE.methods[ thingName ] || []
523
-
524
- // Add the method to the relative method collection.
525
- STATE.methods[ thingName ].push( thingMethod )
526
- }
527
- }
528
-
529
- return P
530
- }, //on
531
-
532
-
533
-
534
- /**
535
- * Unbind events on the things.
536
- */
537
- off: function() {
538
- var i, thingName,
539
- names = arguments;
540
- for ( i = 0, namesCount = names.length; i < namesCount; i += 1 ) {
541
- thingName = names[i]
542
- if ( thingName in STATE.methods ) {
543
- delete STATE.methods[thingName]
544
- }
545
- }
546
- return P
547
- },
548
-
549
-
550
- /**
551
- * Fire off method events.
552
- */
553
- trigger: function( name, data ) {
554
- var _trigger = function( name ) {
555
- var methodList = STATE.methods[ name ]
556
- if ( methodList ) {
557
- methodList.map( function( method ) {
558
- PickerConstructor._.trigger( method, P, [ data ] )
559
- })
560
- }
561
- }
562
- _trigger( '_' + name )
563
- _trigger( name )
564
- return P
565
- } //trigger
566
- } //PickerInstance.prototype
567
-
568
-
569
- /**
570
- * Wrap the picker holder components together.
571
- */
572
- function createWrappedComponent() {
573
-
574
- // Create a picker wrapper holder
575
- return PickerConstructor._.node( 'div',
576
-
577
- // Create a picker wrapper node
578
- PickerConstructor._.node( 'div',
579
-
580
- // Create a picker frame
581
- PickerConstructor._.node( 'div',
582
-
583
- // Create a picker box node
584
- PickerConstructor._.node( 'div',
585
-
586
- // Create the components nodes.
587
- P.component.nodes( STATE.open ),
588
-
589
- // The picker box class
590
- CLASSES.box
591
- ),
592
-
593
- // Picker wrap class
594
- CLASSES.wrap
595
- ),
596
-
597
- // Picker frame class
598
- CLASSES.frame
599
- ),
600
-
601
- // Picker holder class
602
- CLASSES.holder,
603
-
604
- 'tabindex="-1"'
605
- ) //endreturn
606
- } //createWrappedComponent
607
-
608
-
609
-
610
- /**
611
- * Prepare the input element with all bindings.
612
- */
613
- function prepareElement() {
614
-
615
- $ELEMENT.
616
-
617
- // Store the picker data by component name.
618
- data(NAME, P).
619
-
620
- // Add the “input” class name.
621
- addClass(CLASSES.input).
622
-
623
- // If there’s a `data-value`, update the value of the element.
624
- val( $ELEMENT.data('value') ?
625
- P.get('select', SETTINGS.format) :
626
- ELEMENT.value
627
- )
628
-
629
-
630
- // Only bind keydown events if the element isn’t editable.
631
- if ( !SETTINGS.editable ) {
632
-
633
- $ELEMENT.
634
-
635
- // On focus/click, open the picker.
636
- on( 'focus.' + STATE.id + ' click.' + STATE.id, function(event) {
637
- event.preventDefault()
638
- P.open()
639
- }).
640
-
641
- // Handle keyboard event based on the picker being opened or not.
642
- on( 'keydown.' + STATE.id, handleKeydownEvent )
643
- }
644
-
645
-
646
- // Update the aria attributes.
647
- aria(ELEMENT, {
648
- haspopup: true,
649
- expanded: false,
650
- readonly: false,
651
- owns: ELEMENT.id + '_root'
652
- })
653
- }
654
-
655
-
656
- /**
657
- * Prepare the root picker element with all bindings.
658
- */
659
- function prepareElementRoot() {
660
- aria( P.$root[0], 'hidden', true )
661
- }
662
-
663
-
664
- /**
665
- * Prepare the holder picker element with all bindings.
666
- */
667
- function prepareElementHolder() {
668
-
669
- P.$holder.
670
-
671
- on({
672
-
673
- // For iOS8.
674
- keydown: handleKeydownEvent,
675
-
676
- 'focus.toOpen': handleFocusToOpenEvent,
677
-
678
- blur: function() {
679
- // Remove the “target” class.
680
- $ELEMENT.removeClass( CLASSES.target )
681
- },
682
-
683
- // When something within the holder is focused, stop from bubbling
684
- // to the doc and remove the “focused” state from the root.
685
- focusin: function( event ) {
686
- P.$root.removeClass( CLASSES.focused )
687
- event.stopPropagation()
688
- },
689
-
690
- // When something within the holder is clicked, stop it
691
- // from bubbling to the doc.
692
- 'mousedown click': function( event ) {
693
-
694
- var target = event.target
695
-
696
- // Make sure the target isn’t the root holder so it can bubble up.
697
- if ( target != P.$holder[0] ) {
698
-
699
- event.stopPropagation()
700
-
701
- // * For mousedown events, cancel the default action in order to
702
- // prevent cases where focus is shifted onto external elements
703
- // when using things like jQuery mobile or MagnificPopup (ref: #249 & #120).
704
- // Also, for Firefox, don’t prevent action on the `option` element.
705
- if ( event.type == 'mousedown' && !$( target ).is( 'input, select, textarea, button, option' )) {
706
-
707
- event.preventDefault()
708
-
709
- // Re-focus onto the holder so that users can click away
710
- // from elements focused within the picker.
711
- P.$holder[0].focus()
712
- }
713
- }
714
- }
715
-
716
- }).
717
-
718
- // If there’s a click on an actionable element, carry out the actions.
719
- on( 'click', '[data-pick], [data-nav], [data-clear], [data-close]', function() {
720
-
721
- var $target = $( this ),
722
- targetData = $target.data(),
723
- targetDisabled = $target.hasClass( CLASSES.navDisabled ) || $target.hasClass( CLASSES.disabled ),
724
-
725
- // * For IE, non-focusable elements can be active elements as well
726
- // (http://stackoverflow.com/a/2684561).
727
- activeElement = getActiveElement()
728
- activeElement = activeElement && ( activeElement.type || activeElement.href )
729
-
730
- // If it’s disabled or nothing inside is actively focused, re-focus the element.
731
- if ( targetDisabled || activeElement && !$.contains( P.$root[0], activeElement ) ) {
732
- P.$holder[0].focus()
733
- }
734
-
735
- // If something is superficially changed, update the `highlight` based on the `nav`.
736
- if ( !targetDisabled && targetData.nav ) {
737
- P.set( 'highlight', P.component.item.highlight, { nav: targetData.nav } )
738
- }
739
-
740
- // If something is picked, set `select` then close with focus.
741
- else if ( !targetDisabled && 'pick' in targetData ) {
742
- P.set( 'select', targetData.pick )
743
- if ( SETTINGS.closeOnSelect ) {
744
- P.close( true )
745
- }
746
- }
747
-
748
- // If a “clear” button is pressed, empty the values and close with focus.
749
- else if ( targetData.clear ) {
750
- P.clear()
751
- if ( SETTINGS.closeOnClear ) {
752
- P.close( true )
753
- }
754
- }
755
-
756
- else if ( targetData.close ) {
757
- P.close( true )
758
- }
759
-
760
- }) //P.$holder
761
-
762
- }
763
-
764
-
765
- /**
766
- * Prepare the hidden input element along with all bindings.
767
- */
768
- function prepareElementHidden() {
769
-
770
- var name
771
-
772
- if ( SETTINGS.hiddenName === true ) {
773
- name = ELEMENT.name
774
- ELEMENT.name = ''
775
- }
776
- else {
777
- name = [
778
- typeof SETTINGS.hiddenPrefix == 'string' ? SETTINGS.hiddenPrefix : '',
779
- typeof SETTINGS.hiddenSuffix == 'string' ? SETTINGS.hiddenSuffix : '_submit'
780
- ]
781
- name = name[0] + ELEMENT.name + name[1]
782
- }
783
-
784
- P._hidden = $(
785
- '<input ' +
786
- 'type=hidden ' +
787
-
788
- // Create the name using the original input’s with a prefix and suffix.
789
- 'name="' + name + '"' +
790
-
791
- // If the element has a value, set the hidden value as well.
792
- (
793
- $ELEMENT.data('value') || ELEMENT.value ?
794
- ' value="' + P.get('select', SETTINGS.formatSubmit) + '"' :
795
- ''
796
- ) +
797
- '>'
798
- )[0]
799
-
800
- $ELEMENT.
801
-
802
- // If the value changes, update the hidden input with the correct format.
803
- on('change.' + STATE.id, function() {
804
- P._hidden.value = ELEMENT.value ?
805
- P.get('select', SETTINGS.formatSubmit) :
806
- ''
807
- })
808
- }
809
-
810
-
811
- // Wait for transitions to end before focusing the holder. Otherwise, while
812
- // using the `container` option, the view jumps to the container.
813
- function focusPickerOnceOpened() {
814
-
815
- if (IS_DEFAULT_THEME && supportsTransitions) {
816
- P.$holder.find('.' + CLASSES.frame).one('transitionend', function() {
817
- P.$holder[0].focus()
818
- })
819
- }
820
- else {
821
- P.$holder[0].focus()
822
- }
823
- }
824
-
825
-
826
- function handleFocusToOpenEvent(event) {
827
-
828
- // Stop the event from propagating to the doc.
829
- event.stopPropagation()
830
-
831
- // Add the “target” class.
832
- $ELEMENT.addClass( CLASSES.target )
833
-
834
- // Add the “focused” class to the root.
835
- P.$root.addClass( CLASSES.focused )
836
-
837
- // And then finally open the picker.
838
- P.open()
839
- }
840
-
841
-
842
- // For iOS8.
843
- function handleKeydownEvent( event ) {
844
-
845
- var keycode = event.keyCode,
846
-
847
- // Check if one of the delete keys was pressed.
848
- isKeycodeDelete = /^(8|46)$/.test(keycode)
849
-
850
- // For some reason IE clears the input value on “escape”.
851
- if ( keycode == 27 ) {
852
- P.close( true )
853
- return false
854
- }
855
-
856
- // Check if `space` or `delete` was pressed or the picker is closed with a key movement.
857
- if ( keycode == 32 || isKeycodeDelete || !STATE.open && P.component.key[keycode] ) {
858
-
859
- // Prevent it from moving the page and bubbling to doc.
860
- event.preventDefault()
861
- event.stopPropagation()
862
-
863
- // If `delete` was pressed, clear the values and close the picker.
864
- // Otherwise open the picker.
865
- if ( isKeycodeDelete ) { P.clear().close() }
866
- else { P.open() }
867
- }
868
- }
869
-
870
-
871
- // Return a new picker instance.
872
- return new PickerInstance()
873
- } //PickerConstructor
874
-
875
-
876
-
877
- /**
878
- * The default classes and prefix to use for the HTML classes.
879
- */
880
- PickerConstructor.klasses = function( prefix ) {
881
- prefix = prefix || 'picker'
882
- return {
883
-
884
- picker: prefix,
885
- opened: prefix + '--opened',
886
- focused: prefix + '--focused',
887
-
888
- input: prefix + '__input',
889
- active: prefix + '__input--active',
890
- target: prefix + '__input--target',
891
-
892
- holder: prefix + '__holder',
893
-
894
- frame: prefix + '__frame',
895
- wrap: prefix + '__wrap',
896
-
897
- box: prefix + '__box'
898
- }
899
- } //PickerConstructor.klasses
900
-
901
-
902
-
903
- /**
904
- * Check if the default theme is being used.
905
- */
906
- function isUsingDefaultTheme( element ) {
907
-
908
- var theme,
909
- prop = 'position'
910
-
911
- // For IE.
912
- if ( element.currentStyle ) {
913
- theme = element.currentStyle[prop]
914
- }
915
-
916
- // For normal browsers.
917
- else if ( window.getComputedStyle ) {
918
- theme = getComputedStyle( element )[prop]
919
- }
920
-
921
- return theme == 'fixed'
922
- }
923
-
924
-
925
-
926
- /**
927
- * Get the width of the browser’s scrollbar.
928
- * Taken from: https://github.com/VodkaBears/Remodal/blob/master/src/jquery.remodal.js
929
- */
930
- function getScrollbarWidth() {
931
-
932
- if ( $html.height() <= $window.height() ) {
933
- return 0
934
- }
935
-
936
- var $outer = $( '<div style="visibility:hidden;width:100px" />' ).
937
- appendTo( 'body' )
938
-
939
- // Get the width without scrollbars.
940
- var widthWithoutScroll = $outer[0].offsetWidth
941
-
942
- // Force adding scrollbars.
943
- $outer.css( 'overflow', 'scroll' )
944
-
945
- // Add the inner div.
946
- var $inner = $( '<div style="width:100%" />' ).appendTo( $outer )
947
-
948
- // Get the width with scrollbars.
949
- var widthWithScroll = $inner[0].offsetWidth
950
-
951
- // Remove the divs.
952
- $outer.remove()
953
-
954
- // Return the difference between the widths.
955
- return widthWithoutScroll - widthWithScroll
956
- }
957
-
958
-
959
-
960
- /**
961
- * PickerConstructor helper methods.
962
- */
963
- PickerConstructor._ = {
964
-
965
- /**
966
- * Create a group of nodes. Expects:
967
- * `
968
- {
969
- min: {Integer},
970
- max: {Integer},
971
- i: {Integer},
972
- node: {String},
973
- item: {Function}
974
- }
975
- * `
976
- */
977
- group: function( groupObject ) {
978
-
979
- var
980
- // Scope for the looped object
981
- loopObjectScope,
982
-
983
- // Create the nodes list
984
- nodesList = '',
985
-
986
- // The counter starts from the `min`
987
- counter = PickerConstructor._.trigger( groupObject.min, groupObject )
988
-
989
-
990
- // Loop from the `min` to `max`, incrementing by `i`
991
- for ( ; counter <= PickerConstructor._.trigger( groupObject.max, groupObject, [ counter ] ); counter += groupObject.i ) {
992
-
993
- // Trigger the `item` function within scope of the object
994
- loopObjectScope = PickerConstructor._.trigger( groupObject.item, groupObject, [ counter ] )
995
-
996
- // Splice the subgroup and create nodes out of the sub nodes
997
- nodesList += PickerConstructor._.node(
998
- groupObject.node,
999
- loopObjectScope[ 0 ], // the node
1000
- loopObjectScope[ 1 ], // the classes
1001
- loopObjectScope[ 2 ] // the attributes
1002
- )
1003
- }
1004
-
1005
- // Return the list of nodes
1006
- return nodesList
1007
- }, //group
1008
-
1009
-
1010
- /**
1011
- * Create a dom node string
1012
- */
1013
- node: function( wrapper, item, klass, attribute ) {
1014
-
1015
- // If the item is false-y, just return an empty string
1016
- if ( !item ) return ''
1017
-
1018
- // If the item is an array, do a join
1019
- item = $.isArray( item ) ? item.join( '' ) : item
1020
-
1021
- // Check for the class
1022
- klass = klass ? ' class="' + klass + '"' : ''
1023
-
1024
- // Check for any attributes
1025
- attribute = attribute ? ' ' + attribute : ''
1026
-
1027
- // Return the wrapped item
1028
- return '<' + wrapper + klass + attribute + '>' + item + '</' + wrapper + '>'
1029
- }, //node
1030
-
1031
-
1032
- /**
1033
- * Lead numbers below 10 with a zero.
1034
- */
1035
- lead: function( number ) {
1036
- return ( number < 10 ? '0': '' ) + number
1037
- },
1038
-
1039
-
1040
- /**
1041
- * Trigger a function otherwise return the value.
1042
- */
1043
- trigger: function( callback, scope, args ) {
1044
- return typeof callback == 'function' ? callback.apply( scope, args || [] ) : callback
1045
- },
1046
-
1047
-
1048
- /**
1049
- * If the second character is a digit, length is 2 otherwise 1.
1050
- */
1051
- digits: function( string ) {
1052
- return ( /\d/ ).test( string[ 1 ] ) ? 2 : 1
1053
- },
1054
-
1055
-
1056
- /**
1057
- * Tell if something is a date object.
1058
- */
1059
- isDate: function( value ) {
1060
- return {}.toString.call( value ).indexOf( 'Date' ) > -1 && this.isInteger( value.getDate() )
1061
- },
1062
-
1063
-
1064
- /**
1065
- * Tell if something is an integer.
1066
- */
1067
- isInteger: function( value ) {
1068
- return {}.toString.call( value ).indexOf( 'Number' ) > -1 && value % 1 === 0
1069
- },
1070
-
1071
-
1072
- /**
1073
- * Create ARIA attribute strings.
1074
- */
1075
- ariaAttr: ariaAttr
1076
- } //PickerConstructor._
1077
-
1078
-
1079
-
1080
- /**
1081
- * Extend the picker with a component and defaults.
1082
- */
1083
- PickerConstructor.extend = function( name, Component ) {
1084
-
1085
- // Extend jQuery.
1086
- $.fn[ name ] = function( options, action ) {
1087
-
1088
- // Grab the component data.
1089
- var componentData = this.data( name )
1090
-
1091
- // If the picker is requested, return the data object.
1092
- if ( options == 'picker' ) {
1093
- return componentData
1094
- }
1095
-
1096
- // If the component data exists and `options` is a string, carry out the action.
1097
- if ( componentData && typeof options == 'string' ) {
1098
- return PickerConstructor._.trigger( componentData[ options ], componentData, [ action ] )
1099
- }
1100
-
1101
- // Otherwise go through each matched element and if the component
1102
- // doesn’t exist, create a new picker using `this` element
1103
- // and merging the defaults and options with a deep copy.
1104
- return this.each( function() {
1105
- var $this = $( this )
1106
- if ( !$this.data( name ) ) {
1107
- new PickerConstructor( this, name, Component, options )
1108
- }
1109
- })
1110
- }
1111
-
1112
- // Set the defaults.
1113
- $.fn[ name ].defaults = Component.defaults
1114
- } //PickerConstructor.extend
1115
-
1116
-
1117
-
1118
- function aria(element, attribute, value) {
1119
- if ( $.isPlainObject(attribute) ) {
1120
- for ( var key in attribute ) {
1121
- ariaSet(element, key, attribute[key])
1122
- }
1123
- }
1124
- else {
1125
- ariaSet(element, attribute, value)
1126
- }
1127
- }
1128
- function ariaSet(element, attribute, value) {
1129
- element.setAttribute(
1130
- (attribute == 'role' ? '' : 'aria-') + attribute,
1131
- value
1132
- )
1133
- }
1134
- function ariaAttr(attribute, data) {
1135
- if ( !$.isPlainObject(attribute) ) {
1136
- attribute = { attribute: data }
1137
- }
1138
- data = ''
1139
- for ( var key in attribute ) {
1140
- var attr = (key == 'role' ? '' : 'aria-') + key,
1141
- attrVal = attribute[key]
1142
- data += attrVal == null ? '' : attr + '="' + attribute[key] + '"'
1143
- }
1144
- return data
1145
- }
1146
-
1147
- // IE8 bug throws an error for activeElements within iframes.
1148
- function getActiveElement() {
1149
- try {
1150
- return document.activeElement
1151
- } catch ( err ) { }
1152
- }
1153
-
1154
-
1155
-
1156
- // Expose the picker constructor.
1157
- return PickerConstructor
1158
-
1159
-
1160
- }));
1161
-
1162
-
1163
-
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
assets/js/jquery.picker.time.js DELETED
@@ -1,1013 +0,0 @@
1
- /*!
2
- * Time picker for pickadate.js v3.5.6
3
- * http://amsul.github.io/pickadate.js/time.htm
4
- */
5
-
6
- (function ( factory ) {
7
-
8
- // AMD.
9
- if ( typeof define == 'function' && define.amd )
10
- define( ['picker', 'jquery'], factory )
11
-
12
- // Node.js/browserify.
13
- else if ( typeof exports == 'object' )
14
- module.exports = factory( require('./picker.js'), require('jquery') )
15
-
16
- // Browser globals.
17
- else factory( Picker, jQuery )
18
-
19
- }(function( Picker, $ ) {
20
-
21
-
22
- /**
23
- * Globals and constants
24
- */
25
- var HOURS_IN_DAY = 24,
26
- MINUTES_IN_HOUR = 60,
27
- HOURS_TO_NOON = 12,
28
- MINUTES_IN_DAY = HOURS_IN_DAY * MINUTES_IN_HOUR,
29
- _ = Picker._
30
-
31
-
32
-
33
- /**
34
- * The time picker constructor
35
- */
36
- function TimePicker( picker, settings ) {
37
-
38
- var clock = this,
39
- elementValue = picker.$node[ 0 ].value,
40
- elementDataValue = picker.$node.data( 'value' ),
41
- valueString = elementDataValue || elementValue,
42
- formatString = elementDataValue ? settings.formatSubmit : settings.format
43
-
44
- clock.settings = settings
45
- clock.$node = picker.$node
46
-
47
- // The queue of methods that will be used to build item objects.
48
- clock.queue = {
49
- interval: 'i',
50
- min: 'measure create',
51
- max: 'measure create',
52
- now: 'now create',
53
- select: 'parse create validate',
54
- highlight: 'parse create validate',
55
- view: 'parse create validate',
56
- disable: 'deactivate',
57
- enable: 'activate'
58
- }
59
-
60
- // The component's item object.
61
- clock.item = {}
62
-
63
- clock.item.clear = null
64
- clock.item.interval = settings.interval || 30
65
- clock.item.disable = ( settings.disable || [] ).slice( 0 )
66
- clock.item.enable = -(function( collectionDisabled ) {
67
- return collectionDisabled[ 0 ] === true ? collectionDisabled.shift() : -1
68
- })( clock.item.disable )
69
-
70
- clock.
71
- set( 'min', settings.min ).
72
- set( 'max', settings.max ).
73
- set( 'now' )
74
-
75
- // When there’s a value, set the `select`, which in turn
76
- // also sets the `highlight` and `view`.
77
- if ( valueString ) {
78
- clock.set( 'select', valueString, {
79
- format: formatString
80
- })
81
- }
82
-
83
- // If there’s no value, default to highlighting “today”.
84
- else {
85
- clock.
86
- set( 'select', null ).
87
- set( 'highlight', clock.item.now )
88
- }
89
-
90
- // The keycode to movement mapping.
91
- clock.key = {
92
- 40: 1, // Down
93
- 38: -1, // Up
94
- 39: 1, // Right
95
- 37: -1, // Left
96
- go: function( timeChange ) {
97
- clock.set(
98
- 'highlight',
99
- clock.item.highlight.pick + timeChange * clock.item.interval,
100
- { interval: timeChange * clock.item.interval }
101
- )
102
- this.render()
103
- }
104
- }
105
-
106
-
107
- // Bind some picker events.
108
- picker.
109
- on( 'render', function() {
110
- var $pickerHolder = picker.$root.children(),
111
- $viewset = $pickerHolder.find( '.' + settings.klass.viewset ),
112
- vendors = function( prop ) {
113
- return ['webkit', 'moz', 'ms', 'o', ''].map(function( vendor ) {
114
- return ( vendor ? '-' + vendor + '-' : '' ) + prop
115
- })
116
- },
117
- animations = function( $el, state ) {
118
- vendors( 'transform' ).map(function( prop ) {
119
- $el.css( prop, state )
120
- })
121
- vendors( 'transition' ).map(function( prop ) {
122
- $el.css( prop, state )
123
- })
124
- }
125
- if ( $viewset.length ) {
126
- animations( $pickerHolder, 'none' )
127
- $pickerHolder[ 0 ].scrollTop = ~~$viewset.position().top - ( $viewset[ 0 ].clientHeight * 2 )
128
- animations( $pickerHolder, '' )
129
- }
130
- }, 1 ).
131
- on( 'open', function() {
132
- picker.$root.find( 'button' ).attr( 'disabled', false )
133
- }, 1 ).
134
- on( 'close', function() {
135
- picker.$root.find( 'button' ).attr( 'disabled', true )
136
- }, 1 )
137
-
138
- } //TimePicker
139
-
140
-
141
- /**
142
- * Set a timepicker item object.
143
- */
144
- TimePicker.prototype.set = function( type, value, options ) {
145
-
146
- var clock = this,
147
- clockItem = clock.item
148
-
149
- // If the value is `null` just set it immediately.
150
- if ( value === null ) {
151
- if ( type == 'clear' ) type = 'select'
152
- clockItem[ type ] = value
153
- return clock
154
- }
155
-
156
- // Otherwise go through the queue of methods, and invoke the functions.
157
- // Update this as the time unit, and set the final value as this item.
158
- // * In the case of `enable`, keep the queue but set `disable` instead.
159
- // And in the case of `flip`, keep the queue but set `enable` instead.
160
- clockItem[ ( type == 'enable' ? 'disable' : type == 'flip' ? 'enable' : type ) ] = clock.queue[ type ].split( ' ' ).map( function( method ) {
161
- value = clock[ method ]( type, value, options )
162
- return value
163
- }).pop()
164
-
165
- // Check if we need to cascade through more updates.
166
- if ( type == 'select' ) {
167
- clock.set( 'highlight', clockItem.select, options )
168
- }
169
- else if ( type == 'highlight' ) {
170
- clock.set( 'view', clockItem.highlight, options )
171
- }
172
- else if ( type == 'interval' ) {
173
- clock.
174
- set( 'min', clockItem.min, options ).
175
- set( 'max', clockItem.max, options )
176
- }
177
- else if ( type.match( /^(flip|min|max|disable|enable)$/ ) ) {
178
- if ( clockItem.select && clock.disabled( clockItem.select ) ) {
179
- clock.set( 'select', value, options )
180
- }
181
- if ( clockItem.highlight && clock.disabled( clockItem.highlight ) ) {
182
- clock.set( 'highlight', value, options )
183
- }
184
- if ( type == 'min' ) {
185
- clock.set( 'max', clockItem.max, options )
186
- }
187
- }
188
-
189
- return clock
190
- } //TimePicker.prototype.set
191
-
192
-
193
- /**
194
- * Get a timepicker item object.
195
- */
196
- TimePicker.prototype.get = function( type ) {
197
- return this.item[ type ]
198
- } //TimePicker.prototype.get
199
-
200
-
201
- /**
202
- * Create a picker time object.
203
- */
204
- TimePicker.prototype.create = function( type, value, options ) {
205
-
206
- var clock = this
207
-
208
- // If there’s no value, use the type as the value.
209
- value = value === undefined ? type : value
210
-
211
- // If it’s a date object, convert it into an array.
212
- if ( _.isDate( value ) ) {
213
- value = [ value.getHours(), value.getMinutes() ]
214
- }
215
-
216
- // If it’s an object, use the “pick” value.
217
- if ( $.isPlainObject( value ) && _.isInteger( value.pick ) ) {
218
- value = value.pick
219
- }
220
-
221
- // If it’s an array, convert it into minutes.
222
- else if ( $.isArray( value ) ) {
223
- value = +value[ 0 ] * MINUTES_IN_HOUR + (+value[ 1 ])
224
- }
225
-
226
- // If no valid value is passed, set it to “now”.
227
- else if ( !_.isInteger( value ) ) {
228
- value = clock.now( type, value, options )
229
- }
230
-
231
- // If we’re setting the max, make sure it’s greater than the min.
232
- if ( type == 'max' && value < clock.item.min.pick ) {
233
- value += MINUTES_IN_DAY
234
- }
235
-
236
- // If the value doesn’t fall directly on the interval,
237
- // add one interval to indicate it as “passed”.
238
- if ( type != 'min' && type != 'max' && (value - clock.item.min.pick) % clock.item.interval !== 0 ) {
239
- value += clock.item.interval
240
- }
241
-
242
- // Normalize it into a “reachable” interval.
243
- value = clock.normalize( type, value, options )
244
-
245
- // Return the compiled object.
246
- return {
247
-
248
- // Divide to get hours from minutes.
249
- hour: ~~( HOURS_IN_DAY + value / MINUTES_IN_HOUR ) % HOURS_IN_DAY,
250
-
251
- // The remainder is the minutes.
252
- mins: ( MINUTES_IN_HOUR + value % MINUTES_IN_HOUR ) % MINUTES_IN_HOUR,
253
-
254
- // The time in total minutes.
255
- time: ( MINUTES_IN_DAY + value ) % MINUTES_IN_DAY,
256
-
257
- // Reference to the “relative” value to pick.
258
- pick: value % MINUTES_IN_DAY
259
- }
260
- } //TimePicker.prototype.create
261
-
262
-
263
- /**
264
- * Create a range limit object using an array, date object,
265
- * literal “true”, or integer relative to another time.
266
- */
267
- TimePicker.prototype.createRange = function( from, to ) {
268
-
269
- var clock = this,
270
- createTime = function( time ) {
271
- if ( time === true || $.isArray( time ) || _.isDate( time ) ) {
272
- return clock.create( time )
273
- }
274
- return time
275
- }
276
-
277
- // Create objects if possible.
278
- if ( !_.isInteger( from ) ) {
279
- from = createTime( from )
280
- }
281
- if ( !_.isInteger( to ) ) {
282
- to = createTime( to )
283
- }
284
-
285
- // Create relative times.
286
- if ( _.isInteger( from ) && $.isPlainObject( to ) ) {
287
- from = [ to.hour, to.mins + ( from * clock.settings.interval ) ];
288
- }
289
- else if ( _.isInteger( to ) && $.isPlainObject( from ) ) {
290
- to = [ from.hour, from.mins + ( to * clock.settings.interval ) ];
291
- }
292
-
293
- return {
294
- from: createTime( from ),
295
- to: createTime( to )
296
- }
297
- } //TimePicker.prototype.createRange
298
-
299
-
300
- /**
301
- * Check if a time unit falls within a time range object.
302
- */
303
- TimePicker.prototype.withinRange = function( range, timeUnit ) {
304
- range = this.createRange(range.from, range.to)
305
- return timeUnit.pick >= range.from.pick && timeUnit.pick <= range.to.pick
306
- }
307
-
308
-
309
- /**
310
- * Check if two time range objects overlap.
311
- */
312
- TimePicker.prototype.overlapRanges = function( one, two ) {
313
-
314
- var clock = this
315
-
316
- // Convert the ranges into comparable times.
317
- one = clock.createRange( one.from, one.to )
318
- two = clock.createRange( two.from, two.to )
319
-
320
- return clock.withinRange( one, two.from ) || clock.withinRange( one, two.to ) ||
321
- clock.withinRange( two, one.from ) || clock.withinRange( two, one.to )
322
- }
323
-
324
-
325
- /**
326
- * Get the time relative to now.
327
- */
328
- TimePicker.prototype.now = function( type, value/*, options*/ ) {
329
-
330
- var interval = this.item.interval,
331
- date = new Date(),
332
- nowMinutes = date.getHours() * MINUTES_IN_HOUR + date.getMinutes(),
333
- isValueInteger = _.isInteger( value ),
334
- isBelowInterval
335
-
336
- // Make sure “now” falls within the interval range.
337
- nowMinutes -= nowMinutes % interval
338
-
339
- // Check if the difference is less than the interval itself.
340
- isBelowInterval = value < 0 && interval * value + nowMinutes <= -interval
341
-
342
- // Add an interval because the time has “passed”.
343
- nowMinutes += type == 'min' && isBelowInterval ? 0 : interval
344
-
345
- // If the value is a number, adjust by that many intervals.
346
- if ( isValueInteger ) {
347
- nowMinutes += interval * (
348
- isBelowInterval && type != 'max' ?
349
- value + 1 :
350
- value
351
- )
352
- }
353
-
354
- // Return the final calculation.
355
- return nowMinutes
356
- } //TimePicker.prototype.now
357
-
358
-
359
- /**
360
- * Normalize minutes to be “reachable” based on the min and interval.
361
- */
362
- TimePicker.prototype.normalize = function( type, value/*, options*/ ) {
363
-
364
- var interval = this.item.interval,
365
- minTime = this.item.min && this.item.min.pick || 0
366
-
367
- // If setting min time, don’t shift anything.
368
- // Otherwise get the value and min difference and then
369
- // normalize the difference with the interval.
370
- value -= type == 'min' ? 0 : ( value - minTime ) % interval
371
-
372
- // Return the adjusted value.
373
- return value
374
- } //TimePicker.prototype.normalize
375
-
376
-
377
- /**
378
- * Measure the range of minutes.
379
- */
380
- TimePicker.prototype.measure = function( type, value, options ) {
381
-
382
- var clock = this
383
-
384
- // If it’s anything false-y, set it to the default.
385
- if ( !value ) {
386
- value = type == 'min' ? [ 0, 0 ] : [ HOURS_IN_DAY - 1, MINUTES_IN_HOUR - 1 ]
387
- }
388
-
389
- // If it’s a string, parse it.
390
- if ( typeof value == 'string' ) {
391
- value = clock.parse( type, value )
392
- }
393
-
394
- // If it’s a literal true, or an integer, make it relative to now.
395
- else if ( value === true || _.isInteger( value ) ) {
396
- value = clock.now( type, value, options )
397
- }
398
-
399
- // If it’s an object already, just normalize it.
400
- else if ( $.isPlainObject( value ) && _.isInteger( value.pick ) ) {
401
- value = clock.normalize( type, value.pick, options )
402
- }
403
-
404
- return value
405
- } ///TimePicker.prototype.measure
406
-
407
-
408
- /**
409
- * Validate an object as enabled.
410
- */
411
- TimePicker.prototype.validate = function( type, timeObject, options ) {
412
-
413
- var clock = this,
414
- interval = options && options.interval ? options.interval : clock.item.interval
415
-
416
- // Check if the object is disabled.
417
- if ( clock.disabled( timeObject ) ) {
418
-
419
- // Shift with the interval until we reach an enabled time.
420
- timeObject = clock.shift( timeObject, interval )
421
- }
422
-
423
- // Scope the object into range.
424
- timeObject = clock.scope( timeObject )
425
-
426
- // Do a second check to see if we landed on a disabled min/max.
427
- // In that case, shift using the opposite interval as before.
428
- if ( clock.disabled( timeObject ) ) {
429
- timeObject = clock.shift( timeObject, interval * -1 )
430
- }
431
-
432
- // Return the final object.
433
- return timeObject
434
- } //TimePicker.prototype.validate
435
-
436
-
437
- /**
438
- * Check if an object is disabled.
439
- */
440
- TimePicker.prototype.disabled = function( timeToVerify ) {
441
-
442
- var clock = this,
443
-
444
- // Filter through the disabled times to check if this is one.
445
- isDisabledMatch = clock.item.disable.filter( function( timeToDisable ) {
446
-
447
- // If the time is a number, match the hours.
448
- if ( _.isInteger( timeToDisable ) ) {
449
- return timeToVerify.hour == timeToDisable
450
- }
451
-
452
- // If it’s an array, create the object and match the times.
453
- if ( $.isArray( timeToDisable ) || _.isDate( timeToDisable ) ) {
454
- return timeToVerify.pick == clock.create( timeToDisable ).pick
455
- }
456
-
457
- // If it’s an object, match a time within the “from” and “to” range.
458
- if ( $.isPlainObject( timeToDisable ) ) {
459
- return clock.withinRange( timeToDisable, timeToVerify )
460
- }
461
- })
462
-
463
- // If this time matches a disabled time, confirm it’s not inverted.
464
- isDisabledMatch = isDisabledMatch.length && !isDisabledMatch.filter(function( timeToDisable ) {
465
- return $.isArray( timeToDisable ) && timeToDisable[2] == 'inverted' ||
466
- $.isPlainObject( timeToDisable ) && timeToDisable.inverted
467
- }).length
468
-
469
- // If the clock is "enabled" flag is flipped, flip the condition.
470
- return clock.item.enable === -1 ? !isDisabledMatch : isDisabledMatch ||
471
- timeToVerify.pick < clock.item.min.pick ||
472
- timeToVerify.pick > clock.item.max.pick
473
- } //TimePicker.prototype.disabled
474
-
475
-
476
- /**
477
- * Shift an object by an interval until we reach an enabled object.
478
- */
479
- TimePicker.prototype.shift = function( timeObject, interval ) {
480
-
481
- var clock = this,
482
- minLimit = clock.item.min.pick,
483
- maxLimit = clock.item.max.pick/*,
484
- safety = 1000*/
485
-
486
- interval = interval || clock.item.interval
487
-
488
- // Keep looping as long as the time is disabled.
489
- while ( /*safety &&*/ clock.disabled( timeObject ) ) {
490
-
491
- /*safety -= 1
492
- if ( !safety ) {
493
- throw 'Fell into an infinite loop while shifting to ' + timeObject.hour + ':' + timeObject.mins + '.'
494
- }*/
495
-
496
- // Increase/decrease the time by the interval and keep looping.
497
- timeObject = clock.create( timeObject.pick += interval )
498
-
499
- // If we've looped beyond the limits, break out of the loop.
500
- if ( timeObject.pick <= minLimit || timeObject.pick >= maxLimit ) {
501
- break
502
- }
503
- }
504
-
505
- // Return the final object.
506
- return timeObject
507
- } //TimePicker.prototype.shift
508
-
509
-
510
- /**
511
- * Scope an object to be within range of min and max.
512
- */
513
- TimePicker.prototype.scope = function( timeObject ) {
514
- var minLimit = this.item.min.pick,
515
- maxLimit = this.item.max.pick
516
- return this.create( timeObject.pick > maxLimit ? maxLimit : timeObject.pick < minLimit ? minLimit : timeObject )
517
- } //TimePicker.prototype.scope
518
-
519
-
520
- /**
521
- * Parse a string into a usable type.
522
- */
523
- TimePicker.prototype.parse = function( type, value, options ) {
524
-
525
- var hour, minutes, isPM, item, parseValue,
526
- clock = this,
527
- parsingObject = {}
528
-
529
- // If it’s already parsed, we’re good.
530
- if ( !value || typeof value != 'string' ) {
531
- return value
532
- }
533
-
534
- // We need a `.format` to parse the value with.
535
- if ( !( options && options.format ) ) {
536
- options = options || {}
537
- options.format = clock.settings.format
538
- }
539
-
540
- // Convert the format into an array and then map through it.
541
- clock.formats.toArray( options.format ).map( function( label ) {
542
-
543
- var
544
- substring,
545
-
546
- // Grab the formatting label.
547
- formattingLabel = clock.formats[ label ],
548
-
549
- // The format length is from the formatting label function or the
550
- // label length without the escaping exclamation (!) mark.
551
- formatLength = formattingLabel ?
552
- _.trigger( formattingLabel, clock, [ value, parsingObject ] ) :
553
- label.replace( /^!/, '' ).length
554
-
555
- // If there's a format label, split the value up to the format length.
556
- // Then add it to the parsing object with appropriate label.
557
- if ( formattingLabel ) {
558
- substring = value.substr( 0, formatLength )
559
- parsingObject[ label ] = substring.match(/^\d+$/) ? +substring : substring
560
- }
561
-
562
- // Update the time value as the substring from format length to end.
563
- value = value.substr( formatLength )
564
- })
565
-
566
- // Grab the hour and minutes from the parsing object.
567
- for ( item in parsingObject ) {
568
- parseValue = parsingObject[item]
569
- if ( _.isInteger(parseValue) ) {
570
- if ( item.match(/^(h|hh)$/i) ) {
571
- hour = parseValue
572
- if ( item == 'h' || item == 'hh' ) {
573
- hour %= 12
574
- }
575
- }
576
- else if ( item == 'i' ) {
577
- minutes = parseValue
578
- }
579
- }
580
- else if ( item.match(/^a$/i) && parseValue.match(/^p/i) && ('h' in parsingObject || 'hh' in parsingObject) ) {
581
- isPM = true
582
- }
583
- }
584
-
585
- // Calculate it in minutes and return.
586
- return (isPM ? hour + 12 : hour) * MINUTES_IN_HOUR + minutes
587
- } //TimePicker.prototype.parse
588
-
589
-
590
- /**
591
- * Various formats to display the object in.
592
- */
593
- TimePicker.prototype.formats = {
594
-
595
- h: function( string, timeObject ) {
596
-
597
- // If there's string, then get the digits length.
598
- // Otherwise return the selected hour in "standard" format.
599
- return string ? _.digits( string ) : timeObject.hour % HOURS_TO_NOON || HOURS_TO_NOON
600
- },
601
- hh: function( string, timeObject ) {
602
-
603
- // If there's a string, then the length is always 2.
604
- // Otherwise return the selected hour in "standard" format with a leading zero.
605
- return string ? 2 : _.lead( timeObject.hour % HOURS_TO_NOON || HOURS_TO_NOON )
606
- },
607
- H: function( string, timeObject ) {
608
-
609
- // If there's string, then get the digits length.
610
- // Otherwise return the selected hour in "military" format as a string.
611
- return string ? _.digits( string ) : '' + ( timeObject.hour % 24 )
612
- },
613
- HH: function( string, timeObject ) {
614
-
615
- // If there's string, then get the digits length.
616
- // Otherwise return the selected hour in "military" format with a leading zero.
617
- return string ? _.digits( string ) : _.lead( timeObject.hour % 24 )
618
- },
619
- i: function( string, timeObject ) {
620
-
621
- // If there's a string, then the length is always 2.
622
- // Otherwise return the selected minutes.
623
- return string ? 2 : _.lead( timeObject.mins )
624
- },
625
- a: function( string, timeObject ) {
626
-
627
- // If there's a string, then the length is always 4.
628
- // Otherwise check if it's more than "noon" and return either am/pm.
629
- return string ? 4 : MINUTES_IN_DAY / 2 > timeObject.time % MINUTES_IN_DAY ? 'a.m.' : 'p.m.'
630
- },
631
- A: function( string, timeObject ) {
632
-
633
- // If there's a string, then the length is always 2.
634
- // Otherwise check if it's more than "noon" and return either am/pm.
635
- return string ? 2 : MINUTES_IN_DAY / 2 > timeObject.time % MINUTES_IN_DAY ? 'AM' : 'PM'
636
- },
637
-
638
- // Create an array by splitting the formatting string passed.
639
- toArray: function( formatString ) { return formatString.split( /(h{1,2}|H{1,2}|i|a|A|!.)/g ) },
640
-
641
- // Format an object into a string using the formatting options.
642
- toString: function ( formatString, itemObject ) {
643
- var clock = this
644
- return clock.formats.toArray( formatString ).map( function( label ) {
645
- return _.trigger( clock.formats[ label ], clock, [ 0, itemObject ] ) || label.replace( /^!/, '' )
646
- }).join( '' )
647
- }
648
- } //TimePicker.prototype.formats
649
-
650
-
651
-
652
-
653
- /**
654
- * Check if two time units are the exact.
655
- */
656
- TimePicker.prototype.isTimeExact = function( one, two ) {
657
-
658
- var clock = this
659
-
660
- // When we’re working with minutes, do a direct comparison.
661
- if (
662
- ( _.isInteger( one ) && _.isInteger( two ) ) ||
663
- ( typeof one == 'boolean' && typeof two == 'boolean' )
664
- ) {
665
- return one === two
666
- }
667
-
668
- // When we’re working with time representations, compare the “pick” value.
669
- if (
670
- ( _.isDate( one ) || $.isArray( one ) ) &&
671
- ( _.isDate( two ) || $.isArray( two ) )
672
- ) {
673
- return clock.create( one ).pick === clock.create( two ).pick
674
- }
675
-
676
- // When we’re working with range objects, compare the “from” and “to”.
677
- if ( $.isPlainObject( one ) && $.isPlainObject( two ) ) {
678
- return clock.isTimeExact( one.from, two.from ) && clock.isTimeExact( one.to, two.to )
679
- }
680
-
681
- return false
682
- }
683
-
684
-
685
- /**
686
- * Check if two time units overlap.
687
- */
688
- TimePicker.prototype.isTimeOverlap = function( one, two ) {
689
-
690
- var clock = this
691
-
692
- // When we’re working with an integer, compare the hours.
693
- if ( _.isInteger( one ) && ( _.isDate( two ) || $.isArray( two ) ) ) {
694
- return one === clock.create( two ).hour
695
- }
696
- if ( _.isInteger( two ) && ( _.isDate( one ) || $.isArray( one ) ) ) {
697
- return two === clock.create( one ).hour
698
- }
699
-
700
- // When we’re working with range objects, check if the ranges overlap.
701
- if ( $.isPlainObject( one ) && $.isPlainObject( two ) ) {
702
- return clock.overlapRanges( one, two )
703
- }
704
-
705
- return false
706
- }
707
-
708
-
709
- /**
710
- * Flip the “enabled” state.
711
- */
712
- TimePicker.prototype.flipEnable = function(val) {
713
- var itemObject = this.item
714
- itemObject.enable = val || (itemObject.enable == -1 ? 1 : -1)
715
- }
716
-
717
-
718
- /**
719
- * Mark a collection of times as “disabled”.
720
- */
721
- TimePicker.prototype.deactivate = function( type, timesToDisable ) {
722
-
723
- var clock = this,
724
- disabledItems = clock.item.disable.slice(0)
725
-
726
-
727
- // If we’re flipping, that’s all we need to do.
728
- if ( timesToDisable == 'flip' ) {
729
- clock.flipEnable()
730
- }
731
-
732
- else if ( timesToDisable === false ) {
733
- clock.flipEnable(1)
734
- disabledItems = []
735
- }
736
-
737
- else if ( timesToDisable === true ) {
738
- clock.flipEnable(-1)
739
- disabledItems = []
740
- }
741
-
742
- // Otherwise go through the times to disable.
743
- else {
744
-
745
- timesToDisable.map(function( unitToDisable ) {
746
-
747
- var matchFound
748
-
749
- // When we have disabled items, check for matches.
750
- // If something is matched, immediately break out.
751
- for ( var index = 0; index < disabledItems.length; index += 1 ) {
752
- if ( clock.isTimeExact( unitToDisable, disabledItems[index] ) ) {
753
- matchFound = true
754
- break
755
- }
756
- }
757
-
758
- // If nothing was found, add the validated unit to the collection.
759
- if ( !matchFound ) {
760
- if (
761
- _.isInteger( unitToDisable ) ||
762
- _.isDate( unitToDisable ) ||
763
- $.isArray( unitToDisable ) ||
764
- ( $.isPlainObject( unitToDisable ) && unitToDisable.from && unitToDisable.to )
765
- ) {
766
- disabledItems.push( unitToDisable )
767
- }
768
- }
769
- })
770
- }
771
-
772
- // Return the updated collection.
773
- return disabledItems
774
- } //TimePicker.prototype.deactivate
775
-
776
-
777
- /**
778
- * Mark a collection of times as “enabled”.
779
- */
780
- TimePicker.prototype.activate = function( type, timesToEnable ) {
781
-
782
- var clock = this,
783
- disabledItems = clock.item.disable,
784
- disabledItemsCount = disabledItems.length
785
-
786
- // If we’re flipping, that’s all we need to do.
787
- if ( timesToEnable == 'flip' ) {
788
- clock.flipEnable()
789
- }
790
-
791
- else if ( timesToEnable === true ) {
792
- clock.flipEnable(1)
793
- disabledItems = []
794
- }
795
-
796
- else if ( timesToEnable === false ) {
797
- clock.flipEnable(-1)
798
- disabledItems = []
799
- }
800
-
801
- // Otherwise go through the disabled times.
802
- else {
803
-
804
- timesToEnable.map(function( unitToEnable ) {
805
-
806
- var matchFound,
807
- disabledUnit,
808
- index,
809
- isRangeMatched
810
-
811
- // Go through the disabled items and try to find a match.
812
- for ( index = 0; index < disabledItemsCount; index += 1 ) {
813
-
814
- disabledUnit = disabledItems[index]
815
-
816
- // When an exact match is found, remove it from the collection.
817
- if ( clock.isTimeExact( disabledUnit, unitToEnable ) ) {
818
- matchFound = disabledItems[index] = null
819
- isRangeMatched = true
820
- break
821
- }
822
-
823
- // When an overlapped match is found, add the “inverted” state to it.
824
- else if ( clock.isTimeOverlap( disabledUnit, unitToEnable ) ) {
825
- if ( $.isPlainObject( unitToEnable ) ) {
826
- unitToEnable.inverted = true
827
- matchFound = unitToEnable
828
- }
829
- else if ( $.isArray( unitToEnable ) ) {
830
- matchFound = unitToEnable
831
- if ( !matchFound[2] ) matchFound.push( 'inverted' )
832
- }
833
- else if ( _.isDate( unitToEnable ) ) {
834
- matchFound = [ unitToEnable.getFullYear(), unitToEnable.getMonth(), unitToEnable.getDate(), 'inverted' ]
835
- }
836
- break
837
- }
838
- }
839
-
840
- // If a match was found, remove a previous duplicate entry.
841
- if ( matchFound ) for ( index = 0; index < disabledItemsCount; index += 1 ) {
842
- if ( clock.isTimeExact( disabledItems[index], unitToEnable ) ) {
843
- disabledItems[index] = null
844
- break
845
- }
846
- }
847
-
848
- // In the event that we’re dealing with an overlap of range times,
849
- // make sure there are no “inverted” times because of it.
850
- if ( isRangeMatched ) for ( index = 0; index < disabledItemsCount; index += 1 ) {
851
- if ( clock.isTimeOverlap( disabledItems[index], unitToEnable ) ) {
852
- disabledItems[index] = null
853
- break
854
- }
855
- }
856
-
857
- // If something is still matched, add it into the collection.
858
- if ( matchFound ) {
859
- disabledItems.push( matchFound )
860
- }
861
- })
862
- }
863
-
864
- // Return the updated collection.
865
- return disabledItems.filter(function( val ) { return val != null })
866
- } //TimePicker.prototype.activate
867
-
868
-
869
- /**
870
- * The division to use for the range intervals.
871
- */
872
- TimePicker.prototype.i = function( type, value/*, options*/ ) {
873
- return _.isInteger( value ) && value > 0 ? value : this.item.interval
874
- }
875
-
876
-
877
- /**
878
- * Create a string for the nodes in the picker.
879
- */
880
- TimePicker.prototype.nodes = function( isOpen ) {
881
-
882
- var
883
- clock = this,
884
- settings = clock.settings,
885
- selectedObject = clock.item.select,
886
- highlightedObject = clock.item.highlight,
887
- viewsetObject = clock.item.view,
888
- disabledCollection = clock.item.disable
889
-
890
- return _.node(
891
- 'ul',
892
- _.group({
893
- min: clock.item.min.pick,
894
- max: clock.item.max.pick,
895
- i: clock.item.interval,
896
- node: 'li',
897
- item: function( loopedTime ) {
898
- loopedTime = clock.create( loopedTime )
899
- var timeMinutes = loopedTime.pick,
900
- isSelected = selectedObject && selectedObject.pick == timeMinutes,
901
- isHighlighted = highlightedObject && highlightedObject.pick == timeMinutes,
902
- isDisabled = disabledCollection && clock.disabled( loopedTime ),
903
- formattedTime = _.trigger( clock.formats.toString, clock, [ settings.format, loopedTime ] )
904
- return [
905
- _.trigger( clock.formats.toString, clock, [ _.trigger( settings.formatLabel, clock, [ loopedTime ] ) || settings.format, loopedTime ] ),
906
- (function( klasses ) {
907
-
908
- if ( isSelected ) {
909
- klasses.push( settings.klass.selected )
910
- }
911
-
912
- if ( isHighlighted ) {
913
- klasses.push( settings.klass.highlighted )
914
- }
915
-
916
- if ( viewsetObject && viewsetObject.pick == timeMinutes ) {
917
- klasses.push( settings.klass.viewset )
918
- }
919
-
920
- if ( isDisabled ) {
921
- klasses.push( settings.klass.disabled )
922
- }
923
-
924
- return klasses.join( ' ' )
925
- })( [ settings.klass.listItem ] ),
926
- 'data-pick=' + loopedTime.pick + ' ' + _.ariaAttr({
927
- role: 'option',
928
- label: formattedTime,
929
- selected: isSelected && clock.$node.val() === formattedTime ? true : null,
930
- activedescendant: isHighlighted ? true : null,
931
- disabled: isDisabled ? true : null
932
- })
933
- ]
934
- }
935
- }) +
936
-
937
- // * For Firefox forms to submit, make sure to set the button’s `type` attribute as “button”.
938
- _.node(
939
- 'li',
940
- _.node(
941
- 'button',
942
- settings.clear,
943
- settings.klass.buttonClear,
944
- 'type=button data-clear=1' + ( isOpen ? '' : ' disabled' ) + ' ' +
945
- _.ariaAttr({ controls: clock.$node[0].id })
946
- ),
947
- '', _.ariaAttr({ role: 'presentation' })
948
- ),
949
- settings.klass.list,
950
- _.ariaAttr({ role: 'listbox', controls: clock.$node[0].id })
951
- )
952
- } //TimePicker.prototype.nodes
953
-
954
-
955
-
956
-
957
-
958
-
959
-
960
- /**
961
- * Extend the picker to add the component with the defaults.
962
- */
963
- TimePicker.defaults = (function( prefix ) {
964
-
965
- return {
966
-
967
- // Clear
968
- clear: 'Clear',
969
-
970
- // The format to show on the `input` element
971
- format: 'h:i A',
972
-
973
- // The interval between each time
974
- interval: 30,
975
-
976
- // Picker close behavior
977
- closeOnSelect: true,
978
- closeOnClear: true,
979
-
980
- // Classes
981
- klass: {
982
-
983
- picker: prefix + ' ' + prefix + '--time',
984
- holder: prefix + '__holder',
985
-
986
- list: prefix + '__list',
987
- listItem: prefix + '__list-item',
988
-
989
- disabled: prefix + '__list-item--disabled',
990
- selected: prefix + '__list-item--selected',
991
- highlighted: prefix + '__list-item--highlighted',
992
- viewset: prefix + '__list-item--viewset',
993
- now: prefix + '__list-item--now',
994
-
995
- buttonClear: prefix + '__button--clear'
996
- }
997
- }
998
- })( Picker.klasses().picker )
999
-
1000
-
1001
-
1002
-
1003
-
1004
- /**
1005
- * Extend the picker to add the time picker.
1006
- */
1007
- Picker.extend( 'pickatime', TimePicker )
1008
-
1009
-
1010
- }));
1011
-
1012
-
1013
-
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
assets/js/jquery.timepicker.min.js ADDED
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
1
+ /*!
2
+ * jquery-timepicker v1.11.5 - A jQuery timepicker plugin inspired by Google Calendar. It supports both mouse and keyboard navigation.
3
+ * Copyright (c) 2016 Jon Thornton - http://jonthornton.github.com/jquery-timepicker/
4
+ * License: MIT
5
+ */
6
+
7
+ !function(a){"object"==typeof exports&&exports&&"object"==typeof module&&module&&module.exports===exports?a(require("jquery")):"function"==typeof define&&define.amd?define(["jquery"],a):a(jQuery)}(function(a){function b(a){var b=a[0];return b.offsetWidth>0&&b.offsetHeight>0}function c(b){if(b.minTime&&(b.minTime=t(b.minTime)),b.maxTime&&(b.maxTime=t(b.maxTime)),b.durationTime&&"function"!=typeof b.durationTime&&(b.durationTime=t(b.durationTime)),"now"==b.scrollDefault)b.scrollDefault=function(){return b.roundingFunction(t(new Date),b)};else if(b.scrollDefault&&"function"!=typeof b.scrollDefault){var c=b.scrollDefault;b.scrollDefault=function(){return b.roundingFunction(t(c),b)}}else b.minTime&&(b.scrollDefault=function(){return b.roundingFunction(b.minTime,b)});if("string"===a.type(b.timeFormat)&&b.timeFormat.match(/[gh]/)&&(b._twelveHourTime=!0),b.showOnFocus===!1&&-1!=b.showOn.indexOf("focus")&&b.showOn.splice(b.showOn.indexOf("focus"),1),b.disableTimeRanges.length>0){for(var d in b.disableTimeRanges)b.disableTimeRanges[d]=[t(b.disableTimeRanges[d][0]),t(b.disableTimeRanges[d][1])];b.disableTimeRanges=b.disableTimeRanges.sort(function(a,b){return a[0]-b[0]});for(var d=b.disableTimeRanges.length-1;d>0;d--)b.disableTimeRanges[d][0]<=b.disableTimeRanges[d-1][1]&&(b.disableTimeRanges[d-1]=[Math.min(b.disableTimeRanges[d][0],b.disableTimeRanges[d-1][0]),Math.max(b.disableTimeRanges[d][1],b.disableTimeRanges[d-1][1])],b.disableTimeRanges.splice(d,1))}return b}function d(b){var c=b.data("timepicker-settings"),d=b.data("timepicker-list");if(d&&d.length&&(d.remove(),b.data("timepicker-list",!1)),c.useSelect){d=a("<select />",{"class":"ui-timepicker-select"});var g=d}else{d=a("<ul />",{"class":"ui-timepicker-list"});var g=a("<div />",{"class":"ui-timepicker-wrapper",tabindex:-1});g.css({display:"none",position:"absolute"}).append(d)}if(c.noneOption)if(c.noneOption===!0&&(c.noneOption=c.useSelect?"Time...":"None"),a.isArray(c.noneOption)){for(var i in c.noneOption)if(parseInt(i,10)==i){var k=e(c.noneOption[i],c.useSelect);d.append(k)}}else{var k=e(c.noneOption,c.useSelect);d.append(k)}if(c.className&&g.addClass(c.className),(null!==c.minTime||null!==c.durationTime)&&c.showDuration){"function"==typeof c.step?"function":c.step;g.addClass("ui-timepicker-with-duration"),g.addClass("ui-timepicker-step-"+c.step)}var l=c.minTime;"function"==typeof c.durationTime?l=t(c.durationTime()):null!==c.durationTime&&(l=c.durationTime);var n=null!==c.minTime?c.minTime:0,o=null!==c.maxTime?c.maxTime:n+u-1;n>o&&(o+=u),o===u-1&&"string"===a.type(c.timeFormat)&&c.show2400&&(o=u);var p=c.disableTimeRanges,v=0,x=p.length,y=c.step;"function"!=typeof y&&(y=function(){return c.step});for(var i=n,z=0;o>=i;z++,i+=60*y(z)){var A=i,B=s(A,c);if(c.useSelect){var C=a("<option />",{value:B});C.text(B)}else{var C=a("<li />");C.addClass(43200>A%86400?"ui-timepicker-am":"ui-timepicker-pm"),C.data("time",86400>=A?A:A%86400),C.text(B)}if((null!==c.minTime||null!==c.durationTime)&&c.showDuration){var D=r(i-l,c.step);if(c.useSelect)C.text(C.text()+" ("+D+")");else{var E=a("<span />",{"class":"ui-timepicker-duration"});E.text(" ("+D+")"),C.append(E)}}x>v&&(A>=p[v][1]&&(v+=1),p[v]&&A>=p[v][0]&&A<p[v][1]&&(c.useSelect?C.prop("disabled",!0):C.addClass("ui-timepicker-disabled"))),d.append(C)}if(g.data("timepicker-input",b),b.data("timepicker-list",g),c.useSelect)b.val()&&d.val(f(t(b.val()),c)),d.on("focus",function(){a(this).data("timepicker-input").trigger("showTimepicker")}),d.on("blur",function(){a(this).data("timepicker-input").trigger("hideTimepicker")}),d.on("change",function(){m(b,a(this).val(),"select")}),m(b,d.val(),"initial"),b.hide().after(d);else{var F=c.appendTo;"string"==typeof F?F=a(F):"function"==typeof F&&(F=F(b)),F.append(g),j(b,d),d.on("mousedown click","li",function(c){b.off("focus.timepicker"),b.on("focus.timepicker-ie-hack",function(){b.off("focus.timepicker-ie-hack"),b.on("focus.timepicker",w.show)}),h(b)||b[0].focus(),d.find("li").removeClass("ui-timepicker-selected"),a(this).addClass("ui-timepicker-selected"),q(b)&&(b.trigger("hideTimepicker"),d.on("mouseup.timepicker click.timepicker","li",function(a){d.off("mouseup.timepicker click.timepicker"),g.hide()}))})}}function e(b,c){var d,e,f;return"object"==typeof b?(d=b.label,e=b.className,f=b.value):"string"==typeof b?d=b:a.error("Invalid noneOption value"),c?a("<option />",{value:f,"class":e,text:d}):a("<li />",{"class":e,text:d}).data("time",String(f))}function f(a,b){return a=b.roundingFunction(a,b),null!==a?s(a,b):void 0}function g(b){if(b.target!=window){var c=a(b.target);c.closest(".ui-timepicker-input").length||c.closest(".ui-timepicker-wrapper").length||(w.hide(),a(document).unbind(".ui-timepicker"),a(window).unbind(".ui-timepicker"))}}function h(a){var b=a.data("timepicker-settings");return(window.navigator.msMaxTouchPoints||"ontouchstart"in document)&&b.disableTouchKeyboard}function i(b,c,d){if(!d&&0!==d)return!1;var e=b.data("timepicker-settings"),f=!1,d=e.roundingFunction(d,e);return c.find("li").each(function(b,c){var e=a(c);if("number"==typeof e.data("time"))return e.data("time")==d?(f=e,!1):void 0}),f}function j(a,b){b.find("li").removeClass("ui-timepicker-selected");var c=t(l(a),a.data("timepicker-settings"));if(null!==c){var d=i(a,b,c);if(d){var e=d.offset().top-b.offset().top;(e+d.outerHeight()>b.outerHeight()||0>e)&&b.scrollTop(b.scrollTop()+d.position().top-d.outerHeight()),d.addClass("ui-timepicker-selected")}}}function k(b,c){if(""!==this.value&&"timepicker"!=c){var d=a(this);if(!d.is(":focus")||b&&"change"==b.type){var e=d.data("timepicker-settings"),f=t(this.value,e);if(null===f)return void d.trigger("timeFormatError");var g=!1;if(null!==e.minTime&&null!==e.maxTime&&(f<e.minTime||f>e.maxTime)&&(g=!0),a.each(e.disableTimeRanges,function(){return f>=this[0]&&f<this[1]?(g=!0,!1):void 0}),e.forceRoundTime){var h=e.roundingFunction(f,e);h!=f&&(f=h,c=null)}var i=s(f,e);g?m(d,i,"error")&&d.trigger("timeRangeError"):m(d,i,c)}}}function l(a){return a.is("input")?a.val():a.data("ui-timepicker-value")}function m(a,b,c){if(a.is("input")){a.val(b);var d=a.data("timepicker-settings");d.useSelect&&"select"!=c&&"initial"!=c&&a.data("timepicker-list").val(f(t(b),d))}return a.data("ui-timepicker-value")!=b?(a.data("ui-timepicker-value",b),"select"==c?a.trigger("selectTime").trigger("changeTime").trigger("change","timepicker"):-1==["error","initial"].indexOf(c)&&a.trigger("changeTime"),!0):(a.trigger("selectTime"),!1)}function n(a){switch(a.keyCode){case 13:case 9:return;default:a.preventDefault()}}function o(c){var d=a(this),e=d.data("timepicker-list");if(!e||!b(e)){if(40!=c.keyCode)return!0;w.show.call(d.get(0)),e=d.data("timepicker-list"),h(d)||d.focus()}switch(c.keyCode){case 13:return q(d)&&(k.call(d.get(0),{type:"change"}),w.hide.apply(this)),c.preventDefault(),!1;case 38:var f=e.find(".ui-timepicker-selected");return f.length?f.is(":first-child")||(f.removeClass("ui-timepicker-selected"),f.prev().addClass("ui-timepicker-selected"),f.prev().position().top<f.outerHeight()&&e.scrollTop(e.scrollTop()-f.outerHeight())):(e.find("li").each(function(b,c){return a(c).position().top>0?(f=a(c),!1):void 0}),f.addClass("ui-timepicker-selected")),!1;case 40:return f=e.find(".ui-timepicker-selected"),0===f.length?(e.find("li").each(function(b,c){return a(c).position().top>0?(f=a(c),!1):void 0}),f.addClass("ui-timepicker-selected")):f.is(":last-child")||(f.removeClass("ui-timepicker-selected"),f.next().addClass("ui-timepicker-selected"),f.next().position().top+2*f.outerHeight()>e.outerHeight()&&e.scrollTop(e.scrollTop()+f.outerHeight())),!1;case 27:e.find("li").removeClass("ui-timepicker-selected"),w.hide();break;case 9:w.hide();break;default:return!0}}function p(c){var d=a(this),e=d.data("timepicker-list"),f=d.data("timepicker-settings");if(!e||!b(e)||f.disableTextInput)return!0;switch(c.keyCode){case 96:case 97:case 98:case 99:case 100:case 101:case 102:case 103:case 104:case 105:case 48:case 49:case 50:case 51:case 52:case 53:case 54:case 55:case 56:case 57:case 65:case 77:case 80:case 186:case 8:case 46:f.typeaheadHighlight?j(d,e):e.hide()}}function q(a){var b=a.data("timepicker-settings"),c=a.data("timepicker-list"),d=null,e=c.find(".ui-timepicker-selected");return e.hasClass("ui-timepicker-disabled")?!1:(e.length&&(d=e.data("time")),null!==d&&("string"!=typeof d&&(d=s(d,b)),m(a,d,"select")),!0)}function r(a,b){a=Math.abs(a);var c,d,e=Math.round(a/60),f=[];return 60>e?f=[e,v.mins]:(c=Math.floor(e/60),d=e%60,30==b&&30==d&&(c+=v.decimal+5),f.push(c),f.push(1==c?v.hr:v.hrs),30!=b&&d&&(f.push(d),f.push(v.mins))),f.join(" ")}function s(b,c){if("number"!=typeof b)return null;var d=parseInt(b%60),e=parseInt(b/60%60),f=parseInt(b/3600%24),g=new Date(1970,0,2,f,e,d,0);if(isNaN(g.getTime()))return null;if("function"===a.type(c.timeFormat))return c.timeFormat(g);for(var h,i,j="",k=0;k<c.timeFormat.length;k++)switch(i=c.timeFormat.charAt(k)){case"a":j+=g.getHours()>11?v.pm:v.am;break;case"A":j+=g.getHours()>11?v.PM:v.AM;break;case"g":h=g.getHours()%12,j+=0===h?"12":h;break;case"G":h=g.getHours(),b===u&&(h=c.show2400?24:0),j+=h;break;case"h":h=g.getHours()%12,0!==h&&10>h&&(h="0"+h),j+=0===h?"12":h;break;case"H":h=g.getHours(),b===u&&(h=c.show2400?24:0),j+=h>9?h:"0"+h;break;case"i":var e=g.getMinutes();j+=e>9?e:"0"+e;break;case"s":d=g.getSeconds(),j+=d>9?d:"0"+d;break;case"\\":k++,j+=c.timeFormat.charAt(k);break;default:j+=i}return j}function t(a,b){if(""===a||null===a)return null;if("object"==typeof a)return 3600*a.getHours()+60*a.getMinutes()+a.getSeconds();if("string"!=typeof a)return a;a=a.toLowerCase().replace(/[\s\.]/g,""),("a"==a.slice(-1)||"p"==a.slice(-1))&&(a+="m");var c="("+v.am.replace(".","")+"|"+v.pm.replace(".","")+"|"+v.AM.replace(".","")+"|"+v.PM.replace(".","")+")?",d=new RegExp("^"+c+"([0-9]?[0-9])\\W?([0-5][0-9])?\\W?([0-5][0-9])?"+c+"$"),e=a.match(d);if(!e)return null;var f=parseInt(1*e[2],10);if(f>24){if(b&&b.wrapHours===!1)return null;f%=24}var g=e[1]||e[5],h=f;if(12>=f&&g){var i=g==v.pm||g==v.PM;h=12==f?i?12:0:f+(i?12:0)}var j=1*e[3]||0,k=1*e[4]||0,l=3600*h+60*j+k;if(12>f&&!g&&b&&b._twelveHourTime&&b.scrollDefault){var m=l-b.scrollDefault();0>m&&m>=u/-2&&(l=(l+u/2)%u)}return l}var u=86400,v={am:"am",pm:"pm",AM:"AM",PM:"PM",decimal:".",mins:"mins",hr:"hr",hrs:"hrs"},w={init:function(b){return this.each(function(){var e=a(this),f=[];for(var g in a.fn.timepicker.defaults)e.data(g)&&(f[g]=e.data(g));var h=a.extend({},a.fn.timepicker.defaults,f,b);if(h.lang&&(v=a.extend(v,h.lang)),h=c(h),e.data("timepicker-settings",h),e.addClass("ui-timepicker-input"),h.useSelect)d(e);else{if(e.prop("autocomplete","off"),h.showOn)for(var i in h.showOn)e.on(h.showOn[i]+".timepicker",w.show);e.on("change.timepicker",k),e.on("keydown.timepicker",o),e.on("keyup.timepicker",p),h.disableTextInput&&e.on("keydown.timepicker",n),k.call(e.get(0),null,"initial")}})},show:function(c){var e=a(this),f=e.data("timepicker-settings");if(c&&c.preventDefault(),f.useSelect)return void e.data("timepicker-list").focus();h(e)&&e.blur();var k=e.data("timepicker-list");if(!e.prop("readonly")&&(k&&0!==k.length&&"function"!=typeof f.durationTime||(d(e),k=e.data("timepicker-list")),!b(k))){e.data("ui-timepicker-value",e.val()),j(e,k),w.hide(),k.show();var m={};f.orientation.match(/r/)?m.left=e.offset().left+e.outerWidth()-k.outerWidth()+parseInt(k.css("marginLeft").replace("px",""),10):m.left=e.offset().left+parseInt(k.css("marginLeft").replace("px",""),10);var n;n=f.orientation.match(/t/)?"t":f.orientation.match(/b/)?"b":e.offset().top+e.outerHeight(!0)+k.outerHeight()>a(window).height()+a(window).scrollTop()?"t":"b","t"==n?(k.addClass("ui-timepicker-positioned-top"),m.top=e.offset().top-k.outerHeight()+parseInt(k.css("marginTop").replace("px",""),10)):(k.removeClass("ui-timepicker-positioned-top"),m.top=e.offset().top+e.outerHeight()+parseInt(k.css("marginTop").replace("px",""),10)),k.offset(m);var o=k.find(".ui-timepicker-selected");if(!o.length){var p=t(l(e));null!==p?o=i(e,k,p):f.scrollDefault&&(o=i(e,k,f.scrollDefault()))}if(o&&o.length){var q=k.scrollTop()+o.position().top-o.outerHeight();k.scrollTop(q)}else k.scrollTop(0);return f.stopScrollPropagation&&a(document).on("wheel.ui-timepicker",".ui-timepicker-wrapper",function(b){b.preventDefault();var c=a(this).scrollTop();a(this).scrollTop(c+b.originalEvent.deltaY)}),a(document).on("touchstart.ui-timepicker mousedown.ui-timepicker",g),a(window).on("resize.ui-timepicker",g),f.closeOnWindowScroll&&a(document).on("scroll.ui-timepicker",g),e.trigger("showTimepicker"),this}},hide:function(c){var d=a(this),e=d.data("timepicker-settings");return e&&e.useSelect&&d.blur(),a(".ui-timepicker-wrapper").each(function(){var c=a(this);if(b(c)){var d=c.data("timepicker-input"),e=d.data("timepicker-settings");e&&e.selectOnBlur&&q(d),c.hide(),d.trigger("hideTimepicker")}}),this},option:function(b,e){return"string"==typeof b&&"undefined"==typeof e?a(this).data("timepicker-settings")[b]:this.each(function(){var f=a(this),g=f.data("timepicker-settings"),h=f.data("timepicker-list");"object"==typeof b?g=a.extend(g,b):"string"==typeof b&&(g[b]=e),g=c(g),f.data("timepicker-settings",g),h&&(h.remove(),f.data("timepicker-list",!1)),g.useSelect&&d(f)})},getSecondsFromMidnight:function(){return t(l(this))},getTime:function(a){var b=this,c=l(b);if(!c)return null;var d=t(c);if(null===d)return null;a||(a=new Date);var e=new Date(a);return e.setHours(d/3600),e.setMinutes(d%3600/60),e.setSeconds(d%60),e.setMilliseconds(0),e},isVisible:function(){var a=this,c=a.data("timepicker-list");return!(!c||!b(c))},setTime:function(a){var b=this,c=b.data("timepicker-settings");if(c.forceRoundTime)var d=f(t(a),c);else var d=s(t(a),c);return a&&null===d&&c.noneOption&&(d=a),m(b,d),b.data("timepicker-list")&&j(b,b.data("timepicker-list")),this},remove:function(){var a=this;if(a.hasClass("ui-timepicker-input")){var b=a.data("timepicker-settings");return a.removeAttr("autocomplete","off"),a.removeClass("ui-timepicker-input"),a.removeData("timepicker-settings"),a.off(".timepicker"),a.data("timepicker-list")&&a.data("timepicker-list").remove(),b.useSelect&&a.show(),a.removeData("timepicker-list"),this}}};a.fn.timepicker=function(b){return this.length?w[b]?this.hasClass("ui-timepicker-input")?w[b].apply(this,Array.prototype.slice.call(arguments,1)):this:"object"!=typeof b&&b?void a.error("Method "+b+" does not exist on jQuery.timepicker"):w.init.apply(this,arguments):this},a.fn.timepicker.defaults={appendTo:"body",className:null,closeOnWindowScroll:!1,disableTextInput:!1,disableTimeRanges:[],disableTouchKeyboard:!1,durationTime:null,forceRoundTime:!1,maxTime:null,minTime:null,noneOption:!1,orientation:"l",roundingFunction:function(a,b){if(null===a)return null;if("number"!=typeof b.step)return a;var c=a%(60*b.step);return c>=30*b.step?a+=60*b.step-c:a-=c,a==u&&b.show2400?a:a%u},scrollDefault:null,selectOnBlur:!1,show2400:!1,showDuration:!1,showOn:["click","focus"],showOnFocus:!0,step:30,stopScrollPropagation:!1,timeFormat:"g:ia",typeaheadHighlight:!0,useSelect:!1,wrapHours:!0}});
assets/js/jquery.validate.min.js CHANGED
@@ -1,4 +1,4 @@
1
- /*! jQuery Validation Plugin - v1.13.1 - 10/14/2014
2
  * http://jqueryvalidation.org/
3
- * Copyright (c) 2014 Jörn Zaefferer; Licensed MIT */
4
- !function(a){"function"==typeof define&&define.amd?define(["jquery"],a):a(jQuery)}(function(a){a.extend(a.fn,{validate:function(b){if(!this.length)return void(b&&b.debug&&window.console&&console.warn("Nothing selected, can't validate, returning nothing."));var c=a.data(this[0],"validator");return c?c:(this.attr("novalidate","novalidate"),c=new a.validator(b,this[0]),a.data(this[0],"validator",c),c.settings.onsubmit&&(this.validateDelegate(":submit","click",function(b){c.settings.submitHandler&&(c.submitButton=b.target),a(b.target).hasClass("cancel")&&(c.cancelSubmit=!0),void 0!==a(b.target).attr("formnovalidate")&&(c.cancelSubmit=!0)}),this.submit(function(b){function d(){var d,e;return c.settings.submitHandler?(c.submitButton&&(d=a("<input type='hidden'/>").attr("name",c.submitButton.name).val(a(c.submitButton).val()).appendTo(c.currentForm)),e=c.settings.submitHandler.call(c,c.currentForm,b),c.submitButton&&d.remove(),void 0!==e?e:!1):!0}return c.settings.debug&&b.preventDefault(),c.cancelSubmit?(c.cancelSubmit=!1,d()):c.form()?c.pendingRequest?(c.formSubmitted=!0,!1):d():(c.focusInvalid(),!1)})),c)},valid:function(){var b,c;return a(this[0]).is("form")?b=this.validate().form():(b=!0,c=a(this[0].form).validate(),this.each(function(){b=c.element(this)&&b})),b},removeAttrs:function(b){var c={},d=this;return a.each(b.split(/\s/),function(a,b){c[b]=d.attr(b),d.removeAttr(b)}),c},rules:function(b,c){var d,e,f,g,h,i,j=this[0];if(b)switch(d=a.data(j.form,"validator").settings,e=d.rules,f=a.validator.staticRules(j),b){case"add":a.extend(f,a.validator.normalizeRule(c)),delete f.messages,e[j.name]=f,c.messages&&(d.messages[j.name]=a.extend(d.messages[j.name],c.messages));break;case"remove":return c?(i={},a.each(c.split(/\s/),function(b,c){i[c]=f[c],delete f[c],"required"===c&&a(j).removeAttr("aria-required")}),i):(delete e[j.name],f)}return g=a.validator.normalizeRules(a.extend({},a.validator.classRules(j),a.validator.attributeRules(j),a.validator.dataRules(j),a.validator.staticRules(j)),j),g.required&&(h=g.required,delete g.required,g=a.extend({required:h},g),a(j).attr("aria-required","true")),g.remote&&(h=g.remote,delete g.remote,g=a.extend(g,{remote:h})),g}}),a.extend(a.expr[":"],{blank:function(b){return!a.trim(""+a(b).val())},filled:function(b){return!!a.trim(""+a(b).val())},unchecked:function(b){return!a(b).prop("checked")}}),a.validator=function(b,c){this.settings=a.extend(!0,{},a.validator.defaults,b),this.currentForm=c,this.init()},a.validator.format=function(b,c){return 1===arguments.length?function(){var c=a.makeArray(arguments);return c.unshift(b),a.validator.format.apply(this,c)}:(arguments.length>2&&c.constructor!==Array&&(c=a.makeArray(arguments).slice(1)),c.constructor!==Array&&(c=[c]),a.each(c,function(a,c){b=b.replace(new RegExp("\\{"+a+"\\}","g"),function(){return c})}),b)},a.extend(a.validator,{defaults:{messages:{},groups:{},rules:{},errorClass:"error",validClass:"valid",errorElement:"label",focusCleanup:!1,focusInvalid:!0,errorContainer:a([]),errorLabelContainer:a([]),onsubmit:!0,ignore:":hidden",ignoreTitle:!1,onfocusin:function(a){this.lastActive=a,this.settings.focusCleanup&&(this.settings.unhighlight&&this.settings.unhighlight.call(this,a,this.settings.errorClass,this.settings.validClass),this.hideThese(this.errorsFor(a)))},onfocusout:function(a){this.checkable(a)||!(a.name in this.submitted)&&this.optional(a)||this.element(a)},onkeyup:function(a,b){(9!==b.which||""!==this.elementValue(a))&&(a.name in this.submitted||a===this.lastElement)&&this.element(a)},onclick:function(a){a.name in this.submitted?this.element(a):a.parentNode.name in this.submitted&&this.element(a.parentNode)},highlight:function(b,c,d){"radio"===b.type?this.findByName(b.name).addClass(c).removeClass(d):a(b).addClass(c).removeClass(d)},unhighlight:function(b,c,d){"radio"===b.type?this.findByName(b.name).removeClass(c).addClass(d):a(b).removeClass(c).addClass(d)}},setDefaults:function(b){a.extend(a.validator.defaults,b)},messages:{required:"This field is required.",remote:"Please fix this field.",email:"Please enter a valid email address.",url:"Please enter a valid URL.",date:"Please enter a valid date.",dateISO:"Please enter a valid date ( ISO ).",number:"Please enter a valid number.",digits:"Please enter only digits.",creditcard:"Please enter a valid credit card number.",equalTo:"Please enter the same value again.",maxlength:a.validator.format("Please enter no more than {0} characters."),minlength:a.validator.format("Please enter at least {0} characters."),rangelength:a.validator.format("Please enter a value between {0} and {1} characters long."),range:a.validator.format("Please enter a value between {0} and {1}."),max:a.validator.format("Please enter a value less than or equal to {0}."),min:a.validator.format("Please enter a value greater than or equal to {0}.")},autoCreateRanges:!1,prototype:{init:function(){function b(b){var c=a.data(this[0].form,"validator"),d="on"+b.type.replace(/^validate/,""),e=c.settings;e[d]&&!this.is(e.ignore)&&e[d].call(c,this[0],b)}this.labelContainer=a(this.settings.errorLabelContainer),this.errorContext=this.labelContainer.length&&this.labelContainer||a(this.currentForm),this.containers=a(this.settings.errorContainer).add(this.settings.errorLabelContainer),this.submitted={},this.valueCache={},this.pendingRequest=0,this.pending={},this.invalid={},this.reset();var c,d=this.groups={};a.each(this.settings.groups,function(b,c){"string"==typeof c&&(c=c.split(/\s/)),a.each(c,function(a,c){d[c]=b})}),c=this.settings.rules,a.each(c,function(b,d){c[b]=a.validator.normalizeRule(d)}),a(this.currentForm).validateDelegate(":text, [type='password'], [type='file'], select, textarea, [type='number'], [type='search'] ,[type='tel'], [type='url'], [type='email'], [type='datetime'], [type='date'], [type='month'], [type='week'], [type='time'], [type='datetime-local'], [type='range'], [type='color'], [type='radio'], [type='checkbox']","focusin focusout keyup",b).validateDelegate("select, option, [type='radio'], [type='checkbox']","click",b),this.settings.invalidHandler&&a(this.currentForm).bind("invalid-form.validate",this.settings.invalidHandler),a(this.currentForm).find("[required], [data-rule-required], .required").attr("aria-required","true")},form:function(){return this.checkForm(),a.extend(this.submitted,this.errorMap),this.invalid=a.extend({},this.errorMap),this.valid()||a(this.currentForm).triggerHandler("invalid-form",[this]),this.showErrors(),this.valid()},checkForm:function(){this.prepareForm();for(var a=0,b=this.currentElements=this.elements();b[a];a++)this.check(b[a]);return this.valid()},element:function(b){var c=this.clean(b),d=this.validationTargetFor(c),e=!0;return this.lastElement=d,void 0===d?delete this.invalid[c.name]:(this.prepareElement(d),this.currentElements=a(d),e=this.check(d)!==!1,e?delete this.invalid[d.name]:this.invalid[d.name]=!0),a(b).attr("aria-invalid",!e),this.numberOfInvalids()||(this.toHide=this.toHide.add(this.containers)),this.showErrors(),e},showErrors:function(b){if(b){a.extend(this.errorMap,b),this.errorList=[];for(var c in b)this.errorList.push({message:b[c],element:this.findByName(c)[0]});this.successList=a.grep(this.successList,function(a){return!(a.name in b)})}this.settings.showErrors?this.settings.showErrors.call(this,this.errorMap,this.errorList):this.defaultShowErrors()},resetForm:function(){a.fn.resetForm&&a(this.currentForm).resetForm(),this.submitted={},this.lastElement=null,this.prepareForm(),this.hideErrors(),this.elements().removeClass(this.settings.errorClass).removeData("previousValue").removeAttr("aria-invalid")},numberOfInvalids:function(){return this.objectLength(this.invalid)},objectLength:function(a){var b,c=0;for(b in a)c++;return c},hideErrors:function(){this.hideThese(this.toHide)},hideThese:function(a){a.not(this.containers).text(""),this.addWrapper(a).hide()},valid:function(){return 0===this.size()},size:function(){return this.errorList.length},focusInvalid:function(){if(this.settings.focusInvalid)try{a(this.findLastActive()||this.errorList.length&&this.errorList[0].element||[]).filter(":visible").focus().trigger("focusin")}catch(b){}},findLastActive:function(){var b=this.lastActive;return b&&1===a.grep(this.errorList,function(a){return a.element.name===b.name}).length&&b},elements:function(){var b=this,c={};return a(this.currentForm).find("input, select, textarea").not(":submit, :reset, :image, [disabled], [readonly]").not(this.settings.ignore).filter(function(){return!this.name&&b.settings.debug&&window.console&&console.error("%o has no name assigned",this),this.name in c||!b.objectLength(a(this).rules())?!1:(c[this.name]=!0,!0)})},clean:function(b){return a(b)[0]},errors:function(){var b=this.settings.errorClass.split(" ").join(".");return a(this.settings.errorElement+"."+b,this.errorContext)},reset:function(){this.successList=[],this.errorList=[],this.errorMap={},this.toShow=a([]),this.toHide=a([]),this.currentElements=a([])},prepareForm:function(){this.reset(),this.toHide=this.errors().add(this.containers)},prepareElement:function(a){this.reset(),this.toHide=this.errorsFor(a)},elementValue:function(b){var c,d=a(b),e=b.type;return"radio"===e||"checkbox"===e?a("input[name='"+b.name+"']:checked").val():"number"===e&&"undefined"!=typeof b.validity?b.validity.badInput?!1:d.val():(c=d.val(),"string"==typeof c?c.replace(/\r/g,""):c)},check:function(b){b=this.validationTargetFor(this.clean(b));var c,d,e,f=a(b).rules(),g=a.map(f,function(a,b){return b}).length,h=!1,i=this.elementValue(b);for(d in f){e={method:d,parameters:f[d]};try{if(c=a.validator.methods[d].call(this,i,b,e.parameters),"dependency-mismatch"===c&&1===g){h=!0;continue}if(h=!1,"pending"===c)return void(this.toHide=this.toHide.not(this.errorsFor(b)));if(!c)return this.formatAndAdd(b,e),!1}catch(j){throw this.settings.debug&&window.console&&console.log("Exception occurred when checking element "+b.id+", check the '"+e.method+"' method.",j),j}}if(!h)return this.objectLength(f)&&this.successList.push(b),!0},customDataMessage:function(b,c){return a(b).data("msg"+c.charAt(0).toUpperCase()+c.substring(1).toLowerCase())||a(b).data("msg")},customMessage:function(a,b){var c=this.settings.messages[a];return c&&(c.constructor===String?c:c[b])},findDefined:function(){for(var a=0;a<arguments.length;a++)if(void 0!==arguments[a])return arguments[a];return void 0},defaultMessage:function(b,c){return this.findDefined(this.customMessage(b.name,c),this.customDataMessage(b,c),!this.settings.ignoreTitle&&b.title||void 0,a.validator.messages[c],"<strong>Warning: No message defined for "+b.name+"</strong>")},formatAndAdd:function(b,c){var d=this.defaultMessage(b,c.method),e=/\$?\{(\d+)\}/g;"function"==typeof d?d=d.call(this,c.parameters,b):e.test(d)&&(d=a.validator.format(d.replace(e,"{$1}"),c.parameters)),this.errorList.push({message:d,element:b,method:c.method}),this.errorMap[b.name]=d,this.submitted[b.name]=d},addWrapper:function(a){return this.settings.wrapper&&(a=a.add(a.parent(this.settings.wrapper))),a},defaultShowErrors:function(){var a,b,c;for(a=0;this.errorList[a];a++)c=this.errorList[a],this.settings.highlight&&this.settings.highlight.call(this,c.element,this.settings.errorClass,this.settings.validClass),this.showLabel(c.element,c.message);if(this.errorList.length&&(this.toShow=this.toShow.add(this.containers)),this.settings.success)for(a=0;this.successList[a];a++)this.showLabel(this.successList[a]);if(this.settings.unhighlight)for(a=0,b=this.validElements();b[a];a++)this.settings.unhighlight.call(this,b[a],this.settings.errorClass,this.settings.validClass);this.toHide=this.toHide.not(this.toShow),this.hideErrors(),this.addWrapper(this.toShow).show()},validElements:function(){return this.currentElements.not(this.invalidElements())},invalidElements:function(){return a(this.errorList).map(function(){return this.element})},showLabel:function(b,c){var d,e,f,g=this.errorsFor(b),h=this.idOrName(b),i=a(b).attr("aria-describedby");g.length?(g.removeClass(this.settings.validClass).addClass(this.settings.errorClass),g.html(c)):(g=a("<"+this.settings.errorElement+">").attr("id",h+"-error").addClass(this.settings.errorClass).html(c||""),d=g,this.settings.wrapper&&(d=g.hide().show().wrap("<"+this.settings.wrapper+"/>").parent()),this.labelContainer.length?this.labelContainer.append(d):this.settings.errorPlacement?this.settings.errorPlacement(d,a(b)):d.insertAfter(b),g.is("label")?g.attr("for",h):0===g.parents("label[for='"+h+"']").length&&(f=g.attr("id").replace(/(:|\.|\[|\])/g,"\\$1"),i?i.match(new RegExp("\\b"+f+"\\b"))||(i+=" "+f):i=f,a(b).attr("aria-describedby",i),e=this.groups[b.name],e&&a.each(this.groups,function(b,c){c===e&&a("[name='"+b+"']",this.currentForm).attr("aria-describedby",g.attr("id"))}))),!c&&this.settings.success&&(g.text(""),"string"==typeof this.settings.success?g.addClass(this.settings.success):this.settings.success(g,b)),this.toShow=this.toShow.add(g)},errorsFor:function(b){var c=this.idOrName(b),d=a(b).attr("aria-describedby"),e="label[for='"+c+"'], label[for='"+c+"'] *";return d&&(e=e+", #"+d.replace(/\s+/g,", #")),this.errors().filter(e)},idOrName:function(a){return this.groups[a.name]||(this.checkable(a)?a.name:a.id||a.name)},validationTargetFor:function(b){return this.checkable(b)&&(b=this.findByName(b.name)),a(b).not(this.settings.ignore)[0]},checkable:function(a){return/radio|checkbox/i.test(a.type)},findByName:function(b){return a(this.currentForm).find("[name='"+b+"']")},getLength:function(b,c){switch(c.nodeName.toLowerCase()){case"select":return a("option:selected",c).length;case"input":if(this.checkable(c))return this.findByName(c.name).filter(":checked").length}return b.length},depend:function(a,b){return this.dependTypes[typeof a]?this.dependTypes[typeof a](a,b):!0},dependTypes:{"boolean":function(a){return a},string:function(b,c){return!!a(b,c.form).length},"function":function(a,b){return a(b)}},optional:function(b){var c=this.elementValue(b);return!a.validator.methods.required.call(this,c,b)&&"dependency-mismatch"},startRequest:function(a){this.pending[a.name]||(this.pendingRequest++,this.pending[a.name]=!0)},stopRequest:function(b,c){this.pendingRequest--,this.pendingRequest<0&&(this.pendingRequest=0),delete this.pending[b.name],c&&0===this.pendingRequest&&this.formSubmitted&&this.form()?(a(this.currentForm).submit(),this.formSubmitted=!1):!c&&0===this.pendingRequest&&this.formSubmitted&&(a(this.currentForm).triggerHandler("invalid-form",[this]),this.formSubmitted=!1)},previousValue:function(b){return a.data(b,"previousValue")||a.data(b,"previousValue",{old:null,valid:!0,message:this.defaultMessage(b,"remote")})}},classRuleSettings:{required:{required:!0},email:{email:!0},url:{url:!0},date:{date:!0},dateISO:{dateISO:!0},number:{number:!0},digits:{digits:!0},creditcard:{creditcard:!0}},addClassRules:function(b,c){b.constructor===String?this.classRuleSettings[b]=c:a.extend(this.classRuleSettings,b)},classRules:function(b){var c={},d=a(b).attr("class");return d&&a.each(d.split(" "),function(){this in a.validator.classRuleSettings&&a.extend(c,a.validator.classRuleSettings[this])}),c},attributeRules:function(b){var c,d,e={},f=a(b),g=b.getAttribute("type");for(c in a.validator.methods)"required"===c?(d=b.getAttribute(c),""===d&&(d=!0),d=!!d):d=f.attr(c),/min|max/.test(c)&&(null===g||/number|range|text/.test(g))&&(d=Number(d)),d||0===d?e[c]=d:g===c&&"range"!==g&&(e[c]=!0);return e.maxlength&&/-1|2147483647|524288/.test(e.maxlength)&&delete e.maxlength,e},dataRules:function(b){var c,d,e={},f=a(b);for(c in a.validator.methods)d=f.data("rule"+c.charAt(0).toUpperCase()+c.substring(1).toLowerCase()),void 0!==d&&(e[c]=d);return e},staticRules:function(b){var c={},d=a.data(b.form,"validator");return d.settings.rules&&(c=a.validator.normalizeRule(d.settings.rules[b.name])||{}),c},normalizeRules:function(b,c){return a.each(b,function(d,e){if(e===!1)return void delete b[d];if(e.param||e.depends){var f=!0;switch(typeof e.depends){case"string":f=!!a(e.depends,c.form).length;break;case"function":f=e.depends.call(c,c)}f?b[d]=void 0!==e.param?e.param:!0:delete b[d]}}),a.each(b,function(d,e){b[d]=a.isFunction(e)?e(c):e}),a.each(["minlength","maxlength"],function(){b[this]&&(b[this]=Number(b[this]))}),a.each(["rangelength","range"],function(){var c;b[this]&&(a.isArray(b[this])?b[this]=[Number(b[this][0]),Number(b[this][1])]:"string"==typeof b[this]&&(c=b[this].replace(/[\[\]]/g,"").split(/[\s,]+/),b[this]=[Number(c[0]),Number(c[1])]))}),a.validator.autoCreateRanges&&(null!=b.min&&null!=b.max&&(b.range=[b.min,b.max],delete b.min,delete b.max),null!=b.minlength&&null!=b.maxlength&&(b.rangelength=[b.minlength,b.maxlength],delete b.minlength,delete b.maxlength)),b},normalizeRule:function(b){if("string"==typeof b){var c={};a.each(b.split(/\s/),function(){c[this]=!0}),b=c}return b},addMethod:function(b,c,d){a.validator.methods[b]=c,a.validator.messages[b]=void 0!==d?d:a.validator.messages[b],c.length<3&&a.validator.addClassRules(b,a.validator.normalizeRule(b))},methods:{required:function(b,c,d){if(!this.depend(d,c))return"dependency-mismatch";if("select"===c.nodeName.toLowerCase()){var e=a(c).val();return e&&e.length>0}return this.checkable(c)?this.getLength(b,c)>0:a.trim(b).length>0},email:function(a,b){return this.optional(b)||/^[a-zA-Z0-9.!#$%&'*+\/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$/.test(a)},url:function(a,b){return this.optional(b)||/^(https?|s?ftp):\/\/(((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:)*@)?(((\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5]))|((([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])))\.?)(:\d*)?)(\/((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)+(\/(([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)*)*)?)?(\?((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|[\uE000-\uF8FF]|\/|\?)*)?(#((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|\/|\?)*)?$/i.test(a)},date:function(a,b){return this.optional(b)||!/Invalid|NaN/.test(new Date(a).toString())},dateISO:function(a,b){return this.optional(b)||/^\d{4}[\/\-](0?[1-9]|1[012])[\/\-](0?[1-9]|[12][0-9]|3[01])$/.test(a)},number:function(a,b){return this.optional(b)||/^-?(?:\d+|\d{1,3}(?:,\d{3})+)?(?:\.\d+)?$/.test(a)},digits:function(a,b){return this.optional(b)||/^\d+$/.test(a)},creditcard:function(a,b){if(this.optional(b))return"dependency-mismatch";if(/[^0-9 \-]+/.test(a))return!1;var c,d,e=0,f=0,g=!1;if(a=a.replace(/\D/g,""),a.length<13||a.length>19)return!1;for(c=a.length-1;c>=0;c--)d=a.charAt(c),f=parseInt(d,10),g&&(f*=2)>9&&(f-=9),e+=f,g=!g;return e%10===0},minlength:function(b,c,d){var e=a.isArray(b)?b.length:this.getLength(b,c);return this.optional(c)||e>=d},maxlength:function(b,c,d){var e=a.isArray(b)?b.length:this.getLength(b,c);return this.optional(c)||d>=e},rangelength:function(b,c,d){var e=a.isArray(b)?b.length:this.getLength(b,c);return this.optional(c)||e>=d[0]&&e<=d[1]},min:function(a,b,c){return this.optional(b)||a>=c},max:function(a,b,c){return this.optional(b)||c>=a},range:function(a,b,c){return this.optional(b)||a>=c[0]&&a<=c[1]},equalTo:function(b,c,d){var e=a(d);return this.settings.onfocusout&&e.unbind(".validate-equalTo").bind("blur.validate-equalTo",function(){a(c).valid()}),b===e.val()},remote:function(b,c,d){if(this.optional(c))return"dependency-mismatch";var e,f,g=this.previousValue(c);return this.settings.messages[c.name]||(this.settings.messages[c.name]={}),g.originalMessage=this.settings.messages[c.name].remote,this.settings.messages[c.name].remote=g.message,d="string"==typeof d&&{url:d}||d,g.old===b?g.valid:(g.old=b,e=this,this.startRequest(c),f={},f[c.name]=b,a.ajax(a.extend(!0,{url:d,mode:"abort",port:"validate"+c.name,dataType:"json",data:f,context:e.currentForm,success:function(d){var f,h,i,j=d===!0||"true"===d;e.settings.messages[c.name].remote=g.originalMessage,j?(i=e.formSubmitted,e.prepareElement(c),e.formSubmitted=i,e.successList.push(c),delete e.invalid[c.name],e.showErrors()):(f={},h=d||e.defaultMessage(c,"remote"),f[c.name]=g.message=a.isFunction(h)?h(b):h,e.invalid[c.name]=!0,e.showErrors(f)),g.valid=j,e.stopRequest(c,j)}},d)),"pending")}}}),a.format=function(){throw"$.format has been deprecated. Please use $.validator.format instead."};var b,c={};a.ajaxPrefilter?a.ajaxPrefilter(function(a,b,d){var e=a.port;"abort"===a.mode&&(c[e]&&c[e].abort(),c[e]=d)}):(b=a.ajax,a.ajax=function(d){var e=("mode"in d?d:a.ajaxSettings).mode,f=("port"in d?d:a.ajaxSettings).port;return"abort"===e?(c[f]&&c[f].abort(),c[f]=b.apply(this,arguments),c[f]):b.apply(this,arguments)}),a.extend(a.fn,{validateDelegate:function(b,c,d){return this.bind(c,function(c){var e=a(c.target);return e.is(b)?d.apply(e,arguments):void 0})}})});
1
+ /*! jQuery Validation Plugin - v1.15.1 - 7/22/2016
2
  * http://jqueryvalidation.org/
3
+ * Copyright (c) 2016 Jörn Zaefferer; Licensed MIT */
4
+ !function(a){"function"==typeof define&&define.amd?define(["jquery"],a):"object"==typeof module&&module.exports?module.exports=a(require("jquery")):a(jQuery)}(function(a){a.extend(a.fn,{validate:function(b){if(!this.length)return void(b&&b.debug&&window.console&&console.warn("Nothing selected, can't validate, returning nothing."));var c=a.data(this[0],"validator");return c?c:(this.attr("novalidate","novalidate"),c=new a.validator(b,this[0]),a.data(this[0],"validator",c),c.settings.onsubmit&&(this.on("click.validate",":submit",function(b){c.settings.submitHandler&&(c.submitButton=b.target),a(this).hasClass("cancel")&&(c.cancelSubmit=!0),void 0!==a(this).attr("formnovalidate")&&(c.cancelSubmit=!0)}),this.on("submit.validate",function(b){function d(){var d,e;return!c.settings.submitHandler||(c.submitButton&&(d=a("<input type='hidden'/>").attr("name",c.submitButton.name).val(a(c.submitButton).val()).appendTo(c.currentForm)),e=c.settings.submitHandler.call(c,c.currentForm,b),c.submitButton&&d.remove(),void 0!==e&&e)}return c.settings.debug&&b.preventDefault(),c.cancelSubmit?(c.cancelSubmit=!1,d()):c.form()?c.pendingRequest?(c.formSubmitted=!0,!1):d():(c.focusInvalid(),!1)})),c)},valid:function(){var b,c,d;return a(this[0]).is("form")?b=this.validate().form():(d=[],b=!0,c=a(this[0].form).validate(),this.each(function(){b=c.element(this)&&b,b||(d=d.concat(c.errorList))}),c.errorList=d),b},rules:function(b,c){var d,e,f,g,h,i,j=this[0];if(null!=j&&null!=j.form){if(b)switch(d=a.data(j.form,"validator").settings,e=d.rules,f=a.validator.staticRules(j),b){case"add":a.extend(f,a.validator.normalizeRule(c)),delete f.messages,e[j.name]=f,c.messages&&(d.messages[j.name]=a.extend(d.messages[j.name],c.messages));break;case"remove":return c?(i={},a.each(c.split(/\s/),function(b,c){i[c]=f[c],delete f[c],"required"===c&&a(j).removeAttr("aria-required")}),i):(delete e[j.name],f)}return g=a.validator.normalizeRules(a.extend({},a.validator.classRules(j),a.validator.attributeRules(j),a.validator.dataRules(j),a.validator.staticRules(j)),j),g.required&&(h=g.required,delete g.required,g=a.extend({required:h},g),a(j).attr("aria-required","true")),g.remote&&(h=g.remote,delete g.remote,g=a.extend(g,{remote:h})),g}}}),a.extend(a.expr[":"],{blank:function(b){return!a.trim(""+a(b).val())},filled:function(b){var c=a(b).val();return null!==c&&!!a.trim(""+c)},unchecked:function(b){return!a(b).prop("checked")}}),a.validator=function(b,c){this.settings=a.extend(!0,{},a.validator.defaults,b),this.currentForm=c,this.init()},a.validator.format=function(b,c){return 1===arguments.length?function(){var c=a.makeArray(arguments);return c.unshift(b),a.validator.format.apply(this,c)}:void 0===c?b:(arguments.length>2&&c.constructor!==Array&&(c=a.makeArray(arguments).slice(1)),c.constructor!==Array&&(c=[c]),a.each(c,function(a,c){b=b.replace(new RegExp("\\{"+a+"\\}","g"),function(){return c})}),b)},a.extend(a.validator,{defaults:{messages:{},groups:{},rules:{},errorClass:"error",pendingClass:"pending",validClass:"valid",errorElement:"label",focusCleanup:!1,focusInvalid:!0,errorContainer:a([]),errorLabelContainer:a([]),onsubmit:!0,ignore:":hidden",ignoreTitle:!1,onfocusin:function(a){this.lastActive=a,this.settings.focusCleanup&&(this.settings.unhighlight&&this.settings.unhighlight.call(this,a,this.settings.errorClass,this.settings.validClass),this.hideThese(this.errorsFor(a)))},onfocusout:function(a){this.checkable(a)||!(a.name in this.submitted)&&this.optional(a)||this.element(a)},onkeyup:function(b,c){var d=[16,17,18,20,35,36,37,38,39,40,45,144,225];9===c.which&&""===this.elementValue(b)||a.inArray(c.keyCode,d)!==-1||(b.name in this.submitted||b.name in this.invalid)&&this.element(b)},onclick:function(a){a.name in this.submitted?this.element(a):a.parentNode.name in this.submitted&&this.element(a.parentNode)},highlight:function(b,c,d){"radio"===b.type?this.findByName(b.name).addClass(c).removeClass(d):a(b).addClass(c).removeClass(d)},unhighlight:function(b,c,d){"radio"===b.type?this.findByName(b.name).removeClass(c).addClass(d):a(b).removeClass(c).addClass(d)}},setDefaults:function(b){a.extend(a.validator.defaults,b)},messages:{required:"This field is required.",remote:"Please fix this field.",email:"Please enter a valid email address.",url:"Please enter a valid URL.",date:"Please enter a valid date.",dateISO:"Please enter a valid date (ISO).",number:"Please enter a valid number.",digits:"Please enter only digits.",equalTo:"Please enter the same value again.",maxlength:a.validator.format("Please enter no more than {0} characters."),minlength:a.validator.format("Please enter at least {0} characters."),rangelength:a.validator.format("Please enter a value between {0} and {1} characters long."),range:a.validator.format("Please enter a value between {0} and {1}."),max:a.validator.format("Please enter a value less than or equal to {0}."),min:a.validator.format("Please enter a value greater than or equal to {0}."),step:a.validator.format("Please enter a multiple of {0}.")},autoCreateRanges:!1,prototype:{init:function(){function b(b){!this.form&&this.hasAttribute("contenteditable")&&(this.form=a(this).closest("form")[0]);var c=a.data(this.form,"validator"),d="on"+b.type.replace(/^validate/,""),e=c.settings;e[d]&&!a(this).is(e.ignore)&&e[d].call(c,this,b)}this.labelContainer=a(this.settings.errorLabelContainer),this.errorContext=this.labelContainer.length&&this.labelContainer||a(this.currentForm),this.containers=a(this.settings.errorContainer).add(this.settings.errorLabelContainer),this.submitted={},this.valueCache={},this.pendingRequest=0,this.pending={},this.invalid={},this.reset();var c,d=this.groups={};a.each(this.settings.groups,function(b,c){"string"==typeof c&&(c=c.split(/\s/)),a.each(c,function(a,c){d[c]=b})}),c=this.settings.rules,a.each(c,function(b,d){c[b]=a.validator.normalizeRule(d)}),a(this.currentForm).on("focusin.validate focusout.validate keyup.validate",":text, [type='password'], [type='file'], select, textarea, [type='number'], [type='search'], [type='tel'], [type='url'], [type='email'], [type='datetime'], [type='date'], [type='month'], [type='week'], [type='time'], [type='datetime-local'], [type='range'], [type='color'], [type='radio'], [type='checkbox'], [contenteditable]",b).on("click.validate","select, option, [type='radio'], [type='checkbox']",b),this.settings.invalidHandler&&a(this.currentForm).on("invalid-form.validate",this.settings.invalidHandler),a(this.currentForm).find("[required], [data-rule-required], .required").attr("aria-required","true")},form:function(){return this.checkForm(),a.extend(this.submitted,this.errorMap),this.invalid=a.extend({},this.errorMap),this.valid()||a(this.currentForm).triggerHandler("invalid-form",[this]),this.showErrors(),this.valid()},checkForm:function(){this.prepareForm();for(var a=0,b=this.currentElements=this.elements();b[a];a++)this.check(b[a]);return this.valid()},element:function(b){var c,d,e=this.clean(b),f=this.validationTargetFor(e),g=this,h=!0;return void 0===f?delete this.invalid[e.name]:(this.prepareElement(f),this.currentElements=a(f),d=this.groups[f.name],d&&a.each(this.groups,function(a,b){b===d&&a!==f.name&&(e=g.validationTargetFor(g.clean(g.findByName(a))),e&&e.name in g.invalid&&(g.currentElements.push(e),h=g.check(e)&&h))}),c=this.check(f)!==!1,h=h&&c,c?this.invalid[f.name]=!1:this.invalid[f.name]=!0,this.numberOfInvalids()||(this.toHide=this.toHide.add(this.containers)),this.showErrors(),a(b).attr("aria-invalid",!c)),h},showErrors:function(b){if(b){var c=this;a.extend(this.errorMap,b),this.errorList=a.map(this.errorMap,function(a,b){return{message:a,element:c.findByName(b)[0]}}),this.successList=a.grep(this.successList,function(a){return!(a.name in b)})}this.settings.showErrors?this.settings.showErrors.call(this,this.errorMap,this.errorList):this.defaultShowErrors()},resetForm:function(){a.fn.resetForm&&a(this.currentForm).resetForm(),this.invalid={},this.submitted={},this.prepareForm(),this.hideErrors();var b=this.elements().removeData("previousValue").removeAttr("aria-invalid");this.resetElements(b)},resetElements:function(a){var b;if(this.settings.unhighlight)for(b=0;a[b];b++)this.settings.unhighlight.call(this,a[b],this.settings.errorClass,""),this.findByName(a[b].name).removeClass(this.settings.validClass);else a.removeClass(this.settings.errorClass).removeClass(this.settings.validClass)},numberOfInvalids:function(){return this.objectLength(this.invalid)},objectLength:function(a){var b,c=0;for(b in a)a[b]&&c++;return c},hideErrors:function(){this.hideThese(this.toHide)},hideThese:function(a){a.not(this.containers).text(""),this.addWrapper(a).hide()},valid:function(){return 0===this.size()},size:function(){return this.errorList.length},focusInvalid:function(){if(this.settings.focusInvalid)try{a(this.findLastActive()||this.errorList.length&&this.errorList[0].element||[]).filter(":visible").focus().trigger("focusin")}catch(a){}},findLastActive:function(){var b=this.lastActive;return b&&1===a.grep(this.errorList,function(a){return a.element.name===b.name}).length&&b},elements:function(){var b=this,c={};return a(this.currentForm).find("input, select, textarea, [contenteditable]").not(":submit, :reset, :image, :disabled").not(this.settings.ignore).filter(function(){var d=this.name||a(this).attr("name");return!d&&b.settings.debug&&window.console&&console.error("%o has no name assigned",this),this.hasAttribute("contenteditable")&&(this.form=a(this).closest("form")[0]),!(d in c||!b.objectLength(a(this).rules()))&&(c[d]=!0,!0)})},clean:function(b){return a(b)[0]},errors:function(){var b=this.settings.errorClass.split(" ").join(".");return a(this.settings.errorElement+"."+b,this.errorContext)},resetInternals:function(){this.successList=[],this.errorList=[],this.errorMap={},this.toShow=a([]),this.toHide=a([])},reset:function(){this.resetInternals(),this.currentElements=a([])},prepareForm:function(){this.reset(),this.toHide=this.errors().add(this.containers)},prepareElement:function(a){this.reset(),this.toHide=this.errorsFor(a)},elementValue:function(b){var c,d,e=a(b),f=b.type;return"radio"===f||"checkbox"===f?this.findByName(b.name).filter(":checked").val():"number"===f&&"undefined"!=typeof b.validity?b.validity.badInput?"NaN":e.val():(c=b.hasAttribute("contenteditable")?e.text():e.val(),"file"===f?"C:\\fakepath\\"===c.substr(0,12)?c.substr(12):(d=c.lastIndexOf("/"),d>=0?c.substr(d+1):(d=c.lastIndexOf("\\"),d>=0?c.substr(d+1):c)):"string"==typeof c?c.replace(/\r/g,""):c)},check:function(b){b=this.validationTargetFor(this.clean(b));var c,d,e,f=a(b).rules(),g=a.map(f,function(a,b){return b}).length,h=!1,i=this.elementValue(b);if("function"==typeof f.normalizer){if(i=f.normalizer.call(b,i),"string"!=typeof i)throw new TypeError("The normalizer should return a string value.");delete f.normalizer}for(d in f){e={method:d,parameters:f[d]};try{if(c=a.validator.methods[d].call(this,i,b,e.parameters),"dependency-mismatch"===c&&1===g){h=!0;continue}if(h=!1,"pending"===c)return void(this.toHide=this.toHide.not(this.errorsFor(b)));if(!c)return this.formatAndAdd(b,e),!1}catch(a){throw this.settings.debug&&window.console&&console.log("Exception occurred when checking element "+b.id+", check the '"+e.method+"' method.",a),a instanceof TypeError&&(a.message+=". Exception occurred when checking element "+b.id+", check the '"+e.method+"' method."),a}}if(!h)return this.objectLength(f)&&this.successList.push(b),!0},customDataMessage:function(b,c){return a(b).data("msg"+c.charAt(0).toUpperCase()+c.substring(1).toLowerCase())||a(b).data("msg")},customMessage:function(a,b){var c=this.settings.messages[a];return c&&(c.constructor===String?c:c[b])},findDefined:function(){for(var a=0;a<arguments.length;a++)if(void 0!==arguments[a])return arguments[a]},defaultMessage:function(b,c){"string"==typeof c&&(c={method:c});var d=this.findDefined(this.customMessage(b.name,c.method),this.customDataMessage(b,c.method),!this.settings.ignoreTitle&&b.title||void 0,a.validator.messages[c.method],"<strong>Warning: No message defined for "+b.name+"</strong>"),e=/\$?\{(\d+)\}/g;return"function"==typeof d?d=d.call(this,c.parameters,b):e.test(d)&&(d=a.validator.format(d.replace(e,"{$1}"),c.parameters)),d},formatAndAdd:function(a,b){var c=this.defaultMessage(a,b);this.errorList.push({message:c,element:a,method:b.method}),this.errorMap[a.name]=c,this.submitted[a.name]=c},addWrapper:function(a){return this.settings.wrapper&&(a=a.add(a.parent(this.settings.wrapper))),a},defaultShowErrors:function(){var a,b,c;for(a=0;this.errorList[a];a++)c=this.errorList[a],this.settings.highlight&&this.settings.highlight.call(this,c.element,this.settings.errorClass,this.settings.validClass),this.showLabel(c.element,c.message);if(this.errorList.length&&(this.toShow=this.toShow.add(this.containers)),this.settings.success)for(a=0;this.successList[a];a++)this.showLabel(this.successList[a]);if(this.settings.unhighlight)for(a=0,b=this.validElements();b[a];a++)this.settings.unhighlight.call(this,b[a],this.settings.errorClass,this.settings.validClass);this.toHide=this.toHide.not(this.toShow),this.hideErrors(),this.addWrapper(this.toShow).show()},validElements:function(){return this.currentElements.not(this.invalidElements())},invalidElements:function(){return a(this.errorList).map(function(){return this.element})},showLabel:function(b,c){var d,e,f,g,h=this.errorsFor(b),i=this.idOrName(b),j=a(b).attr("aria-describedby");h.length?(h.removeClass(this.settings.validClass).addClass(this.settings.errorClass),h.html(c)):(h=a("<"+this.settings.errorElement+">").attr("id",i+"-error").addClass(this.settings.errorClass).html(c||""),d=h,this.settings.wrapper&&(d=h.hide().show().wrap("<"+this.settings.wrapper+"/>").parent()),this.labelContainer.length?this.labelContainer.append(d):this.settings.errorPlacement?this.settings.errorPlacement.call(this,d,a(b)):d.insertAfter(b),h.is("label")?h.attr("for",i):0===h.parents("label[for='"+this.escapeCssMeta(i)+"']").length&&(f=h.attr("id"),j?j.match(new RegExp("\\b"+this.escapeCssMeta(f)+"\\b"))||(j+=" "+f):j=f,a(b).attr("aria-describedby",j),e=this.groups[b.name],e&&(g=this,a.each(g.groups,function(b,c){c===e&&a("[name='"+g.escapeCssMeta(b)+"']",g.currentForm).attr("aria-describedby",h.attr("id"))})))),!c&&this.settings.success&&(h.text(""),"string"==typeof this.settings.success?h.addClass(this.settings.success):this.settings.success(h,b)),this.toShow=this.toShow.add(h)},errorsFor:function(b){var c=this.escapeCssMeta(this.idOrName(b)),d=a(b).attr("aria-describedby"),e="label[for='"+c+"'], label[for='"+c+"'] *";return d&&(e=e+", #"+this.escapeCssMeta(d).replace(/\s+/g,", #")),this.errors().filter(e)},escapeCssMeta:function(a){return a.replace(/([\\!"#$%&'()*+,./:;<=>?@\[\]^`{|}~])/g,"\\$1")},idOrName:function(a){return this.groups[a.name]||(this.checkable(a)?a.name:a.id||a.name)},validationTargetFor:function(b){return this.checkable(b)&&(b=this.findByName(b.name)),a(b).not(this.settings.ignore)[0]},checkable:function(a){return/radio|checkbox/i.test(a.type)},findByName:function(b){return a(this.currentForm).find("[name='"+this.escapeCssMeta(b)+"']")},getLength:function(b,c){switch(c.nodeName.toLowerCase()){case"select":return a("option:selected",c).length;case"input":if(this.checkable(c))return this.findByName(c.name).filter(":checked").length}return b.length},depend:function(a,b){return!this.dependTypes[typeof a]||this.dependTypes[typeof a](a,b)},dependTypes:{boolean:function(a){return a},string:function(b,c){return!!a(b,c.form).length},function:function(a,b){return a(b)}},optional:function(b){var c=this.elementValue(b);return!a.validator.methods.required.call(this,c,b)&&"dependency-mismatch"},startRequest:function(b){this.pending[b.name]||(this.pendingRequest++,a(b).addClass(this.settings.pendingClass),this.pending[b.name]=!0)},stopRequest:function(b,c){this.pendingRequest--,this.pendingRequest<0&&(this.pendingRequest=0),delete this.pending[b.name],a(b).removeClass(this.settings.pendingClass),c&&0===this.pendingRequest&&this.formSubmitted&&this.form()?(a(this.currentForm).submit(),this.formSubmitted=!1):!c&&0===this.pendingRequest&&this.formSubmitted&&(a(this.currentForm).triggerHandler("invalid-form",[this]),this.formSubmitted=!1)},previousValue:function(b,c){return c="string"==typeof c&&c||"remote",a.data(b,"previousValue")||a.data(b,"previousValue",{old:null,valid:!0,message:this.defaultMessage(b,{method:c})})},destroy:function(){this.resetForm(),a(this.currentForm).off(".validate").removeData("validator").find(".validate-equalTo-blur").off(".validate-equalTo").removeClass("validate-equalTo-blur")}},classRuleSettings:{required:{required:!0},email:{email:!0},url:{url:!0},date:{date:!0},dateISO:{dateISO:!0},number:{number:!0},digits:{digits:!0},creditcard:{creditcard:!0}},addClassRules:function(b,c){b.constructor===String?this.classRuleSettings[b]=c:a.extend(this.classRuleSettings,b)},classRules:function(b){var c={},d=a(b).attr("class");return d&&a.each(d.split(" "),function(){this in a.validator.classRuleSettings&&a.extend(c,a.validator.classRuleSettings[this])}),c},normalizeAttributeRule:function(a,b,c,d){/min|max|step/.test(c)&&(null===b||/number|range|text/.test(b))&&(d=Number(d),isNaN(d)&&(d=void 0)),d||0===d?a[c]=d:b===c&&"range"!==b&&(a[c]=!0)},attributeRules:function(b){var c,d,e={},f=a(b),g=b.getAttribute("type");for(c in a.validator.methods)"required"===c?(d=b.getAttribute(c),""===d&&(d=!0),d=!!d):d=f.attr(c),this.normalizeAttributeRule(e,g,c,d);return e.maxlength&&/-1|2147483647|524288/.test(e.maxlength)&&delete e.maxlength,e},dataRules:function(b){var c,d,e={},f=a(b),g=b.getAttribute("type");for(c in a.validator.methods)d=f.data("rule"+c.charAt(0).toUpperCase()+c.substring(1).toLowerCase()),this.normalizeAttributeRule(e,g,c,d);return e},staticRules:function(b){var c={},d=a.data(b.form,"validator");return d.settings.rules&&(c=a.validator.normalizeRule(d.settings.rules[b.name])||{}),c},normalizeRules:function(b,c){return a.each(b,function(d,e){if(e===!1)return void delete b[d];if(e.param||e.depends){var f=!0;switch(typeof e.depends){case"string":f=!!a(e.depends,c.form).length;break;case"function":f=e.depends.call(c,c)}f?b[d]=void 0===e.param||e.param:(a.data(c.form,"validator").resetElements(a(c)),delete b[d])}}),a.each(b,function(d,e){b[d]=a.isFunction(e)&&"normalizer"!==d?e(c):e}),a.each(["minlength","maxlength"],function(){b[this]&&(b[this]=Number(b[this]))}),a.each(["rangelength","range"],function(){var c;b[this]&&(a.isArray(b[this])?b[this]=[Number(b[this][0]),Number(b[this][1])]:"string"==typeof b[this]&&(c=b[this].replace(/[\[\]]/g,"").split(/[\s,]+/),b[this]=[Number(c[0]),Number(c[1])]))}),a.validator.autoCreateRanges&&(null!=b.min&&null!=b.max&&(b.range=[b.min,b.max],delete b.min,delete b.max),null!=b.minlength&&null!=b.maxlength&&(b.rangelength=[b.minlength,b.maxlength],delete b.minlength,delete b.maxlength)),b},normalizeRule:function(b){if("string"==typeof b){var c={};a.each(b.split(/\s/),function(){c[this]=!0}),b=c}return b},addMethod:function(b,c,d){a.validator.methods[b]=c,a.validator.messages[b]=void 0!==d?d:a.validator.messages[b],c.length<3&&a.validator.addClassRules(b,a.validator.normalizeRule(b))},methods:{required:function(b,c,d){if(!this.depend(d,c))return"dependency-mismatch";if("select"===c.nodeName.toLowerCase()){var e=a(c).val();return e&&e.length>0}return this.checkable(c)?this.getLength(b,c)>0:b.length>0},email:function(a,b){return this.optional(b)||/^[a-zA-Z0-9.!#$%&'*+\/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$/.test(a)},url:function(a,b){return this.optional(b)||/^(?:(?:(?:https?|ftp):)?\/\/)(?:\S+(?::\S*)?@)?(?:(?!(?:10|127)(?:\.\d{1,3}){3})(?!(?:169\.254|192\.168)(?:\.\d{1,3}){2})(?!172\.(?:1[6-9]|2\d|3[0-1])(?:\.\d{1,3}){2})(?:[1-9]\d?|1\d\d|2[01]\d|22[0-3])(?:\.(?:1?\d{1,2}|2[0-4]\d|25[0-5])){2}(?:\.(?:[1-9]\d?|1\d\d|2[0-4]\d|25[0-4]))|(?:(?:[a-z\u00a1-\uffff0-9]-*)*[a-z\u00a1-\uffff0-9]+)(?:\.(?:[a-z\u00a1-\uffff0-9]-*)*[a-z\u00a1-\uffff0-9]+)*(?:\.(?:[a-z\u00a1-\uffff]{2,})).?)(?::\d{2,5})?(?:[/?#]\S*)?$/i.test(a)},date:function(a,b){return this.optional(b)||!/Invalid|NaN/.test(new Date(a).toString())},dateISO:function(a,b){return this.optional(b)||/^\d{4}[\/\-](0?[1-9]|1[012])[\/\-](0?[1-9]|[12][0-9]|3[01])$/.test(a)},number:function(a,b){return this.optional(b)||/^(?:-?\d+|-?\d{1,3}(?:,\d{3})+)?(?:\.\d+)?$/.test(a)},digits:function(a,b){return this.optional(b)||/^\d+$/.test(a)},minlength:function(b,c,d){var e=a.isArray(b)?b.length:this.getLength(b,c);return this.optional(c)||e>=d},maxlength:function(b,c,d){var e=a.isArray(b)?b.length:this.getLength(b,c);return this.optional(c)||e<=d},rangelength:function(b,c,d){var e=a.isArray(b)?b.length:this.getLength(b,c);return this.optional(c)||e>=d[0]&&e<=d[1]},min:function(a,b,c){return this.optional(b)||a>=c},max:function(a,b,c){return this.optional(b)||a<=c},range:function(a,b,c){return this.optional(b)||a>=c[0]&&a<=c[1]},step:function(b,c,d){var e,f=a(c).attr("type"),g="Step attribute on input type "+f+" is not supported.",h=["text","number","range"],i=new RegExp("\\b"+f+"\\b"),j=f&&!i.test(h.join()),k=function(a){var b=(""+a).match(/(?:\.(\d+))?$/);return b&&b[1]?b[1].length:0},l=function(a){return Math.round(a*Math.pow(10,e))},m=!0;if(j)throw new Error(g);return e=k(d),(k(b)>e||l(b)%l(d)!==0)&&(m=!1),this.optional(c)||m},equalTo:function(b,c,d){var e=a(d);return this.settings.onfocusout&&e.not(".validate-equalTo-blur").length&&e.addClass("validate-equalTo-blur").on("blur.validate-equalTo",function(){a(c).valid()}),b===e.val()},remote:function(b,c,d,e){if(this.optional(c))return"dependency-mismatch";e="string"==typeof e&&e||"remote";var f,g,h,i=this.previousValue(c,e);return this.settings.messages[c.name]||(this.settings.messages[c.name]={}),i.originalMessage=i.originalMessage||this.settings.messages[c.name][e],this.settings.messages[c.name][e]=i.message,d="string"==typeof d&&{url:d}||d,h=a.param(a.extend({data:b},d.data)),i.old===h?i.valid:(i.old=h,f=this,this.startRequest(c),g={},g[c.name]=b,a.ajax(a.extend(!0,{mode:"abort",port:"validate"+c.name,dataType:"json",data:g,context:f.currentForm,success:function(a){var d,g,h,j=a===!0||"true"===a;f.settings.messages[c.name][e]=i.originalMessage,j?(h=f.formSubmitted,f.resetInternals(),f.toHide=f.errorsFor(c),f.formSubmitted=h,f.successList.push(c),f.invalid[c.name]=!1,f.showErrors()):(d={},g=a||f.defaultMessage(c,{method:e,parameters:b}),d[c.name]=i.message=g,f.invalid[c.name]=!0,f.showErrors(d)),i.valid=j,f.stopRequest(c,j)}},d)),"pending")}}});var b,c={};a.ajaxPrefilter?a.ajaxPrefilter(function(a,b,d){var e=a.port;"abort"===a.mode&&(c[e]&&c[e].abort(),c[e]=d)}):(b=a.ajax,a.ajax=function(d){var e=("mode"in d?d:a.ajaxSettings).mode,f=("port"in d?d:a.ajaxSettings).port;return"abort"===e?(c[f]&&c[f].abort(),c[f]=b.apply(this,arguments),c[f]):b.apply(this,arguments)})});
assets/js/wpforms.js CHANGED
@@ -30,6 +30,8 @@
30
  WPForms.loadTimePicker();
31
  WPForms.loadInputMask();
32
  WPForms.loadPayments();
 
 
33
  },
34
 
35
  /**
@@ -72,7 +74,6 @@
72
  }, $.validator.format("File type is not allowed") );
73
 
74
  // Validate method for file size
75
- // @link https://github.com/jzaefferer/jquery-validation/pull/1512
76
  $.validator.addMethod("maxsize", function(value, element, param) {
77
  var maxSize = param,
78
  optionalValue = this.optional(element),
@@ -98,6 +99,23 @@
98
  return this.optional( element ) || /^[a-zA-Z0-9.!#$%&'*+\/=?^_`{|}~-]+@((?=[a-z0-9-]{1,63}\.)(xn--)?[a-z0-9]+(-[a-z0-9]+)*\.)+[a-z]{2,63}$/.test( value );
99
  }
100
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
101
  // Finally load jQuery Validation library for our forms
102
  $('.wpforms-validate').each(function() {
103
  var form = $(this),
@@ -114,16 +132,24 @@
114
  errorPlacement: function(error, element) {
115
  if (element.attr('type') == 'radio' || element.attr('type') == 'checkbox' ) {
116
  element.parent().parent().parent().append(error);
 
 
 
 
117
  } else {
118
  error.insertAfter(element);
119
  }
120
  },
121
  submitHandler: function(form) {
122
- var $submit = $(form).find('.wpforms-submit'),
 
 
123
  altText = $submit.data('alt-text');
 
124
  if (altText) {
125
  $submit.text(altText).prop('disabled', true);
126
  }
 
127
  form.submit();
128
  }
129
  }
@@ -141,27 +167,20 @@
141
  loadDatePicker: function() {
142
 
143
  // Only load if jQuery datepicker library exists
144
- if (typeof $.fn.pickadate !== 'undefined') {
145
  $('.wpforms-datepicker').each(function() {
146
  var element = $(this),
147
  form = element.closest('.wpforms-form'),
148
  formID = form.data('formid');
149
 
150
- if (typeof window['wpforms_'+formID] != "undefined" && window['wpforms_'+formID].hasOwnProperty('pickadate') ) {
151
- properties = window['wpforms_'+formID].pickadate;
152
- } else if ( typeof wpforms_pickadate != "undefined") {
153
- properties = wpforms_pickadate;
154
  } else {
155
- properties = {
156
- selectYears: true,
157
- selectMonths: true,
158
- today: false,
159
- clear: false,
160
- close: false,
161
- format: element.data('format')
162
- }
163
  }
164
- element.pickadate(properties)
165
  });
166
  };
167
  },
@@ -174,24 +193,23 @@
174
  loadTimePicker: function() {
175
 
176
  // Only load if jQuery timepicker library exists
177
- if (typeof $.fn.pickatime !== 'undefined') {
178
  $('.wpforms-timepicker').each(function() {
179
  var element = $(this),
180
  form = element.closest('.wpforms-form'),
181
  formID = form.data('formid');
182
 
183
- if (typeof window['wpforms_'+formID] != "undefined" && window['wpforms_'+formID].hasOwnProperty('pickatime') ) {
184
- properties = window['wpforms_'+formID].pickadate;
185
- } else if ( typeof wpforms_pickatime != "undefined") {
186
- properties = wpforms_pickatime;
187
  } else {
188
  properties = {
189
- clear: false,
190
- format: element.data('format'),
191
- interval: element.data('interval')
192
  }
193
  }
194
- element.pickatime(properties);
195
  });
196
  }
197
  },
30
  WPForms.loadTimePicker();
31
  WPForms.loadInputMask();
32
  WPForms.loadPayments();
33
+
34
+ $(document).trigger('wpformsReady');
35
  },
36
 
37
  /**
74
  }, $.validator.format("File type is not allowed") );
75
 
76
  // Validate method for file size
 
77
  $.validator.addMethod("maxsize", function(value, element, param) {
78
  var maxSize = param,
79
  optionalValue = this.optional(element),
99
  return this.optional( element ) || /^[a-zA-Z0-9.!#$%&'*+\/=?^_`{|}~-]+@((?=[a-z0-9-]{1,63}\.)(xn--)?[a-z0-9]+(-[a-z0-9]+)*\.)+[a-z]{2,63}$/.test( value );
100
  }
101
 
102
+ // Validate confirmations
103
+ $.validator.addMethod("confirm", function(value, element, param) {
104
+ return $.validator.methods.equalTo.call(this, value, element, param);
105
+ }, function(params, element) {
106
+ return $(element).data('rule-confirm-msg');
107
+ });
108
+
109
+ // Validate 12-hour time
110
+ $.validator.addMethod( "time12h", function( value, element ) {
111
+ return this.optional( element ) || /^((0?[1-9]|1[012])(:[0-5]\d){1,2}(\ ?[AP]M))$/i.test( value );
112
+ }, "Please enter time in 12-hour AM/PM format (eg 8:45 AM)" );
113
+
114
+ // Validate 24-hour time
115
+ $.validator.addMethod( "time24h", function( value, element ) {
116
+ return this.optional(element) || /^(([0-1]?[0-9])|([2][0-3])):([0-5]?[0-9])(\ ?[AP]M)?$/i.test(value);
117
+ }, "Please enter time in 24-hour format (eg 22:45)" );
118
+
119
  // Finally load jQuery Validation library for our forms
120
  $('.wpforms-validate').each(function() {
121
  var form = $(this),
132
  errorPlacement: function(error, element) {
133
  if (element.attr('type') == 'radio' || element.attr('type') == 'checkbox' ) {
134
  element.parent().parent().parent().append(error);
135
+ } else if (element.is('select') && element.attr('class').match(/date-month|date-day|date-year/)) {
136
+ if (element.parent().find('label.wpforms-error:visible').length === 0) {
137
+ element.parent().find('select:last').after(error);
138
+ }
139
  } else {
140
  error.insertAfter(element);
141
  }
142
  },
143
  submitHandler: function(form) {
144
+
145
+ var $form = $(form),
146
+ $submit = $form.find('.wpforms-submit'),
147
  altText = $submit.data('alt-text');
148
+
149
  if (altText) {
150
  $submit.text(altText).prop('disabled', true);
151
  }
152
+
153
  form.submit();
154
  }
155
  }
167
  loadDatePicker: function() {
168
 
169
  // Only load if jQuery datepicker library exists
170
+ if (typeof $.fn.flatpickr !== 'undefined') {
171
  $('.wpforms-datepicker').each(function() {
172
  var element = $(this),
173
  form = element.closest('.wpforms-form'),
174
  formID = form.data('formid');
175
 
176
+ if (typeof window['wpforms_'+formID] != "undefined" && window['wpforms_'+formID].hasOwnProperty('datepicker') ) {
177
+ properties = window['wpforms_'+formID].datepicker;
178
+ } else if ( typeof wpforms_datepicker != "undefined") {
179
+ properties = wpforms_datepicker;
180
  } else {
181
+ properties = {}
 
 
 
 
 
 
 
182
  }
183
+ element.flatpickr(properties)
184
  });
185
  };
186
  },
193
  loadTimePicker: function() {
194
 
195
  // Only load if jQuery timepicker library exists
196
+ if (typeof $.fn.timepicker !== 'undefined') {
197
  $('.wpforms-timepicker').each(function() {
198
  var element = $(this),
199
  form = element.closest('.wpforms-form'),
200
  formID = form.data('formid');
201
 
202
+ if (typeof window['wpforms_'+formID] != "undefined" && window['wpforms_'+formID].hasOwnProperty('timepicker') ) {
203
+ properties = window['wpforms_'+formID].timepicker;
204
+ } else if ( typeof wpforms_timepicker != "undefined") {
205
+ properties = wpforms_timepicker;
206
  } else {
207
  properties = {
208
+ scrollDefault: 'now',
209
+ forceRoundTime: true
 
210
  }
211
  }
212
+ element.timepicker(properties);
213
  });
214
  }
215
  },
includes/admin/builder/class-builder.php CHANGED
@@ -257,6 +257,8 @@ class WPForms_Builder {
257
 
258
  $strings = array(
259
  'ajax_url' => admin_url( 'admin-ajax.php' ),
 
 
260
  'dynamic_choice_limit' => __( 'The {source} {type} contains over {limit} items ({total}). This may make the field difficult for your vistors to use and/or cause the form to be slow.', 'wpforms' ),
261
  'cancel' => __( 'Cancel', 'wpforms' ),
262
  'ok' => __( 'OK', 'wpforms' ),
257
 
258
  $strings = array(
259
  'ajax_url' => admin_url( 'admin-ajax.php' ),
260
+ 'date_select_day' => __( 'DD', 'wpforms' ),
261
+ 'date_select_month' => __( 'MM', 'wpforms' ),
262
  'dynamic_choice_limit' => __( 'The {source} {type} contains over {limit} items ({total}). This may make the field difficult for your vistors to use and/or cause the form to be slow.', 'wpforms' ),
263
  'cancel' => __( 'Cancel', 'wpforms' ),
264
  'ok' => __( 'OK', 'wpforms' ),
includes/admin/builder/panels/class-fields.php CHANGED
@@ -206,7 +206,9 @@ class WPForms_Builder_Panel_Fields extends WPForms_Builder_Panel {
206
 
207
  foreach( $fields as $field ) {
208
 
209
- printf( '<div class="wpforms-field-option wpforms-field-option-%s" id="wpforms-field-option-%d" data-field-id="%d">', esc_attr( $field['type'] ), $field['id'], $field['id'] );
 
 
210
 
211
  printf( '<input type="hidden" name="fields[%d][id]" value="%d" class="wpforms-field-option-hidden-id">', $field['id'], $field['id'] );
212
 
206
 
207
  foreach( $fields as $field ) {
208
 
209
+ $class = apply_filters( 'wpforms_builder_field_option_class', '', $field );
210
+
211
+ printf( '<div class="wpforms-field-option wpforms-field-option-%s %s" id="wpforms-field-option-%d" data-field-id="%d">', esc_attr( $field['type'] ), $class, $field['id'], $field['id'] );
212
 
213
  printf( '<input type="hidden" name="fields[%d][id]" value="%d" class="wpforms-field-option-hidden-id">', $field['id'], $field['id'] );
214
 
includes/admin/builder/panels/class-settings.php CHANGED
@@ -114,7 +114,7 @@ class WPForms_Builder_Panel_Settings extends WPForms_Builder_Panel {
114
  'form_class',
115
  $this->form_data,
116
  __( 'Form CSS Class', 'wpforms' ),
117
- array( 'tooltip' => __( 'Enter CSS class names for the form wrapper. Multiple class names should be seperated with spaces.', 'wpforms' ) )
118
  );
119
  wpforms_panel_field(
120
  'text',
@@ -138,7 +138,7 @@ class WPForms_Builder_Panel_Settings extends WPForms_Builder_Panel {
138
  'submit_class',
139
  $this->form_data,
140
  __( 'Submit Button CSS Class', 'wpforms' ),
141
- array( 'tooltip' => __( 'Enter CSS class names for the form submit button. Multiple names should be seperated with spaces.', 'wpforms' ) )
142
  );
143
  wpforms_panel_field(
144
  'checkbox',
@@ -190,7 +190,7 @@ class WPForms_Builder_Panel_Settings extends WPForms_Builder_Panel {
190
  // __( 'Send To Email Address', 'wpforms' ),
191
  // array(
192
  // 'default' => '{admin_email}',
193
- // 'tooltip' => __( 'Enter the email address to receive form entry notifications. For multiple notifications, seperate email addresses with a comma.', 'wpforms' ),
194
  // 'smarttags' => array(
195
  // 'type' => 'fields',
196
  // 'fields' => 'name,email,text',
114
  'form_class',
115
  $this->form_data,
116
  __( 'Form CSS Class', 'wpforms' ),
117
+ array( 'tooltip' => __( 'Enter CSS class names for the form wrapper. Multiple class names should be separated with spaces.', 'wpforms' ) )
118
  );
119
  wpforms_panel_field(
120
  'text',
138
  'submit_class',
139
  $this->form_data,
140
  __( 'Submit Button CSS Class', 'wpforms' ),
141
+ array( 'tooltip' => __( 'Enter CSS class names for the form submit button. Multiple names should be separated with spaces.', 'wpforms' ) )
142
  );
143
  wpforms_panel_field(
144
  'checkbox',
190
  // __( 'Send To Email Address', 'wpforms' ),
191
  // array(
192
  // 'default' => '{admin_email}',
193
+ // 'tooltip' => __( 'Enter the email address to receive form entry notifications. For multiple notifications, separate email addresses with a comma.', 'wpforms' ),
194
  // 'smarttags' => array(
195
  // 'type' => 'fields',
196
  // 'fields' => 'name,email,text',
includes/class-frontend.php CHANGED
@@ -53,18 +53,25 @@ class WPForms_Frontend {
53
  */
54
  public function output( $id, $title = false, $description = false ) {
55
 
 
 
 
56
  // Grab the form data, if not found then we bail
57
  $form = wpforms()->form->get( (int) $id );
58
- if ( ! $form )
 
59
  return;
 
60
  // Basic information
61
- $form_data = wpforms_decode( $form->post_content, true );
62
- $form_id = absint( $form->ID );
63
- $settings = $form_data['settings'];
64
- $action = esc_url_raw( remove_query_arg( 'wpforms' ) );
65
- $class[] = wpforms_setting( 'disable-css', '1' ) == '1' ? 'wpforms-container-full' : '';
66
- $errors = empty( wpforms()->process->errors[$form->ID] ) ? array() : wpforms()->process->errors[$form->ID];
67
- $success = false;
 
 
68
 
69
  // If the form does not contain any fields do not proceed
70
  if ( empty( $form_data['fields'] ) ) {
@@ -174,15 +181,15 @@ class WPForms_Frontend {
174
  public function head( $form_data, $form, $title, $description, $errors ) {
175
 
176
  // Output title and/or desc
177
- if ( $title || $description ) {
178
 
179
  echo '<div class="wpforms-head-container">';
180
 
181
- if ( $title && !empty( $form->post_title ) ) {
182
  echo '<div class="wpforms-title">' . esc_html( $form->post_title ) . '</div>';
183
  }
184
 
185
- if ( $description && !empty( $form->post_excerpt ) ) {
186
  echo '<div class="wpforms-description">' . $form->post_excerpt . '</div>';
187
  }
188
 
@@ -676,22 +683,16 @@ class WPForms_Frontend {
676
  // jquery date/time library CSS
677
  if ( $this->assets_global() || true == wpforms_has_field_type( 'date-time', $this->forms, true ) ) :
678
  wp_enqueue_style(
679
- 'wpforms-pickadate-core',
680
- WPFORMS_PLUGIN_URL . 'assets/css/pickadate.classic.css',
681
- array(),
682
- '3.5.6'
683
- );
684
- wp_enqueue_style(
685
- 'wpforms-pickadate-date',
686
- WPFORMS_PLUGIN_URL . 'assets/css/pickadate.classic.date.css',
687
  array(),
688
- '3.5.6'
689
  );
690
  wp_enqueue_style(
691
- 'wpforms-pickadate-time',
692
- WPFORMS_PLUGIN_URL . 'assets/css/pickadate.classic.time.css',
693
  array(),
694
- '3.5.6'
695
  );
696
  endif;
697
 
@@ -728,31 +729,24 @@ class WPForms_Frontend {
728
  'wpforms-validation',
729
  WPFORMS_PLUGIN_URL . 'assets/js/jquery.validate.min.js',
730
  array( 'jquery' ),
731
- '1.13.1',
732
  true
733
  );
734
 
735
- // Load jquery date/time library - http://http://amsul.ca/pickadate.js/
736
  if ( $this->assets_global() || true == wpforms_has_field_type( 'date-time', $this->forms, true ) ) :
737
  wp_enqueue_script(
738
- 'wpforms-pickadate-core',
739
- WPFORMS_PLUGIN_URL . 'assets/js/jquery.picker.js',
740
- array( 'jquery' ),
741
- '3.5.6',
742
- true
743
- );
744
- wp_enqueue_script(
745
- 'wpforms-pickadate-date',
746
- WPFORMS_PLUGIN_URL . 'assets/js/jquery.picker.date.js',
747
  array( 'jquery' ),
748
- '3.5.6',
749
  true
750
  );
751
  wp_enqueue_script(
752
- 'wpforms-pickadate-time',
753
- WPFORMS_PLUGIN_URL . 'assets/js/jquery.picker.time.js',
754
  array( 'jquery' ),
755
- '3.5.6',
756
  true
757
  );
758
  endif;
@@ -812,11 +806,17 @@ class WPForms_Frontend {
812
  if ( !empty( $site_key ) && !empty( $secret_key ) ) {
813
  wp_enqueue_script(
814
  'wpforms-recaptcha',
815
- 'https://www.google.com/recaptcha/api.js',
816
- array(),
817
  '2.0.0',
818
  true
819
  );
 
 
 
 
 
 
820
  }
821
  }
822
 
53
  */
54
  public function output( $id, $title = false, $description = false ) {
55
 
56
+ if ( empty( $id ) )
57
+ return;
58
+
59
  // Grab the form data, if not found then we bail
60
  $form = wpforms()->form->get( (int) $id );
61
+
62
+ if ( empty( $form ) )
63
  return;
64
+
65
  // Basic information
66
+ $form_data = wpforms_decode( $form->post_content, true );
67
+ $form_id = absint( $form->ID );
68
+ $settings = $form_data['settings'];
69
+ $action = esc_url_raw( remove_query_arg( 'wpforms' ) );
70
+ $class[] = wpforms_setting( 'disable-css', '1' ) == '1' ? 'wpforms-container-full' : '';
71
+ $errors = empty( wpforms()->process->errors[$form->ID] ) ? array() : wpforms()->process->errors[$form->ID];
72
+ $success = false;
73
+ $title = $title == 'false' ? false : $title;
74
+ $description = $description == 'false' ? false : $description;
75
 
76
  // If the form does not contain any fields do not proceed
77
  if ( empty( $form_data['fields'] ) ) {
181
  public function head( $form_data, $form, $title, $description, $errors ) {
182
 
183
  // Output title and/or desc
184
+ if ( !empty( $title ) || !empty( $description ) ) {
185
 
186
  echo '<div class="wpforms-head-container">';
187
 
188
+ if ( !empty( $title ) && !empty( $form->post_title ) ) {
189
  echo '<div class="wpforms-title">' . esc_html( $form->post_title ) . '</div>';
190
  }
191
 
192
+ if ( !empty( $description ) && !empty( $form->post_excerpt ) ) {
193
  echo '<div class="wpforms-description">' . $form->post_excerpt . '</div>';
194
  }
195
 
683
  // jquery date/time library CSS
684
  if ( $this->assets_global() || true == wpforms_has_field_type( 'date-time', $this->forms, true ) ) :
685
  wp_enqueue_style(
686
+ 'wpforms-jquery-timepicker',
687
+ WPFORMS_PLUGIN_URL . 'assets/css/jquery.timepicker.css',
 
 
 
 
 
 
688
  array(),
689
+ '1.11.5'
690
  );
691
  wp_enqueue_style(
692
+ 'wpforms-flatpickr',
693
+ WPFORMS_PLUGIN_URL . 'assets/css/flatpickr.min.css',
694
  array(),
695
+ '2.0.5'
696
  );
697
  endif;
698
 
729
  'wpforms-validation',
730
  WPFORMS_PLUGIN_URL . 'assets/js/jquery.validate.min.js',
731
  array( 'jquery' ),
732
+ '1.15.1',
733
  true
734
  );
735
 
736
+ // Load jquery date/time libraries
737
  if ( $this->assets_global() || true == wpforms_has_field_type( 'date-time', $this->forms, true ) ) :
738
  wp_enqueue_script(
739
+ 'wpforms-flatpickr',
740
+ WPFORMS_PLUGIN_URL . 'assets/js/flatpickr.min.js',
 
 
 
 
 
 
 
741
  array( 'jquery' ),
742
+ '2.0.5',
743
  true
744
  );
745
  wp_enqueue_script(
746
+ 'wpforms-jquery-timepicker',
747
+ WPFORMS_PLUGIN_URL . 'assets/js/jquery.timepicker.min.js',
748
  array( 'jquery' ),
749
+ '1.11.5',
750
  true
751
  );
752
  endif;
806
  if ( !empty( $site_key ) && !empty( $secret_key ) ) {
807
  wp_enqueue_script(
808
  'wpforms-recaptcha',
809
+ 'https://www.google.com/recaptcha/api.js?onload=wpformsRecaptcha&render=explicit',
810
+ array( 'jquery' ),
811
  '2.0.0',
812
  true
813
  );
814
+ $reCAPTCHA_init = 'var wpformsRecaptcha = function(){
815
+ jQuery(".g-recaptcha").each(function(index, el) {
816
+ grecaptcha.render(el, {sitekey : \'' . $site_key . '\'});
817
+ });
818
+ };';
819
+ wp_add_inline_script( 'wpforms-recaptcha', $reCAPTCHA_init );
820
  }
821
  }
822
 
includes/class-install.php CHANGED
@@ -19,21 +19,77 @@ class WPForms_Install {
19
 
20
  // When activated, trigger install method
21
  register_activation_hook( WPFORMS_PLUGIN_FILE, array( $this, 'install' ) );
 
 
 
22
  }
23
 
24
  /**
25
  * Let's get the party started.
26
  *
27
  * @since 1.0.0
 
28
  */
29
- public function install() {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
30
 
31
- $wpforms_install = new stdClass();
32
- $wpforms_install->preview = new WPForms_Preview;
 
33
 
34
- // Form preview
 
 
 
 
 
 
 
 
 
 
35
  $wpforms_install->preview->form_preview_check();
36
 
 
37
  do_action( 'wpforms_install' );
38
 
39
  // Set current version, to be referenced in future updates
@@ -46,15 +102,29 @@ class WPForms_Install {
46
  $activated[$type] = time();
47
  update_option( 'wpforms_activated', $activated );
48
  }
 
49
 
50
- // Abort so we only set the transient for single site installs
51
- if ( is_network_admin() || isset( $_GET['activate-multi'] ) ) {
52
- return;
53
- }
 
 
 
 
 
 
 
 
 
54
 
55
- // Add transiet to trigger redirect to the Welcome screen
56
- set_transient( 'wpforms_activation_redirect', true, 30 );
57
- }
 
 
58
 
 
 
59
  }
60
  new WPForms_Install;
19
 
20
  // When activated, trigger install method
21
  register_activation_hook( WPFORMS_PLUGIN_FILE, array( $this, 'install' ) );
22
+
23
+ // Watch for new multisite blogs
24
+ add_action( 'wpmu_new_blog', array( $this, 'new_multisite_blog' ), 10, 6 );
25
  }
26
 
27
  /**
28
  * Let's get the party started.
29
  *
30
  * @since 1.0.0
31
+ * @param boolean $network_wide
32
  */
33
+ public function install( $network_wide = false ) {
34
+
35
+ // Check if we are on multisite and network activating
36
+ if ( is_multisite() && $network_wide ) {
37
+
38
+ // Multisite - go through each subsite and run the installer
39
+ if ( function_exists( 'get_sites' ) && class_exists( 'WP_Site_Query' ) ) {
40
+
41
+ // WP 4.6+
42
+ $sites = get_sites();
43
+
44
+ foreach ( $sites as $site ) {
45
+
46
+ switch_to_blog( $site->blog_id );
47
+ $this->run_install();
48
+ restore_current_blog();
49
+ }
50
+
51
+ } else {
52
+
53
+ $sites = wp_get_sites( array( 'limit' => 0 ) );
54
+
55
+ foreach ( $sites as $site ) {
56
+
57
+ switch_to_blog( $site['blog_id'] );
58
+ $this->run_install();
59
+ restore_current_blog();
60
+ }
61
+ }
62
+
63
+ } else {
64
+
65
+ // Normal single site
66
+ $this->run_install();
67
+ }
68
+
69
+
70
+ // Abort so we only set the transient for single site installs
71
+ if ( is_network_admin() || isset( $_GET['activate-multi'] ) ) {
72
+ return;
73
+ }
74
 
75
+ // Add transiet to trigger redirect to the Welcome screen
76
+ set_transient( 'wpforms_activation_redirect', true, 30 );
77
+ }
78
 
79
+ /**
80
+ * Run the actual installer.
81
+ *
82
+ * @since 1.3.0
83
+ */
84
+ function run_install() {
85
+
86
+ $wpforms_install = new stdClass();
87
+ $wpforms_install->preview = new WPForms_Preview;
88
+
89
+ // Create form preview page
90
  $wpforms_install->preview->form_preview_check();
91
 
92
+ // Hook for Pro users
93
  do_action( 'wpforms_install' );
94
 
95
  // Set current version, to be referenced in future updates
102
  $activated[$type] = time();
103
  update_option( 'wpforms_activated', $activated );
104
  }
105
+ }
106
 
107
+ /**
108
+ * When a new site is created in multisite, see if we are network activated,
109
+ * and if so run the installer.
110
+ *
111
+ * @since 1.3.0
112
+ * @param int $blog_id
113
+ * @param int $user_id
114
+ * @param string $domain
115
+ * @param string $path
116
+ * @param int $site_id
117
+ * @param array $meta
118
+ */
119
+ function new_multisite_blog( $blog_id, $user_id, $domain, $path, $site_id, $meta ) {
120
 
121
+ if ( is_plugin_active_for_network( plugin_basename( WPFORMS_PLUGIN_FILE ) ) ) {
122
+
123
+ switch_to_blog( $blog_id );
124
+ $this->run_install();
125
+ restore_current_blog();
126
 
127
+ }
128
+ }
129
  }
130
  new WPForms_Install;
includes/class-process.php CHANGED
@@ -276,7 +276,7 @@ class WPForms_Process {
276
  }
277
 
278
  if ( !empty( $url ) ) {
279
- $url = apply_filters( 'wpforms_process_redirect_url', $url, $form_id );
280
  wp_redirect( esc_url_raw( $url ) );
281
  do_action( 'wpforms_process_redirect', $form_id );
282
  do_action( "wpforms_process_redirect_{$form_id}", $form_id );
@@ -355,7 +355,7 @@ class WPForms_Process {
355
 
356
  // Go
357
  foreach( $email['address'] as $address ) {
358
- $emails->send( $address, $email['subject'], $email['message'] );
359
  }
360
  }
361
  }
276
  }
277
 
278
  if ( !empty( $url ) ) {
279
+ $url = apply_filters( 'wpforms_process_redirect_url', $url, $form_id, $this->fields );
280
  wp_redirect( esc_url_raw( $url ) );
281
  do_action( 'wpforms_process_redirect', $form_id );
282
  do_action( "wpforms_process_redirect_{$form_id}", $form_id );
355
 
356
  // Go
357
  foreach( $email['address'] as $address ) {
358
+ $emails->send( trim( $address ), $email['subject'], $email['message'] );
359
  }
360
  }
361
  }
includes/emails/class-emails.php CHANGED
@@ -260,6 +260,11 @@ class WPForms_WP_Emails {
260
  return false;
261
  }
262
 
 
 
 
 
 
263
  // Hooks before email is sent
264
  do_action( 'wpforms_email_send_before', $this );
265
 
260
  return false;
261
  }
262
 
263
+ // Don't send if email address is invalid
264
+ if ( ! is_email( $to ) ) {
265
+ return false;
266
+ }
267
+
268
  // Hooks before email is sent
269
  do_action( 'wpforms_email_send_before', $this );
270
 
includes/fields/class-base.php CHANGED
@@ -365,7 +365,7 @@ abstract class WPForms_Field {
365
  // Field option choices inputs
366
  $option_choices = sprintf( '<ul data-next-id="%s" class="%s" data-field-id="%d" data-field-type="%s">', max( array_keys( $values ) ) +1, $class, $field['id'], $this->type );
367
  foreach ( $values as $key => $value ) {
368
- $default = !empty( $choices_values['default'] ) ? $choices_values['default'] : '';
369
  $option_choices .= sprintf( '<li data-key="%d">', $key );
370
  $option_choices .= sprintf( '<input type="radio" name="fields[%s][choices][%s][default]" class="default" value="1" %s>', $field['id'], $key, checked( '1', $default, false ) );
371
  $option_choices .= '<span class="move"><i class="fa fa-bars"></i></span>';
@@ -472,7 +472,7 @@ abstract class WPForms_Field {
472
 
473
  case 'css':
474
  $value = !empty( $field['css'] ) ? esc_attr( $field['css'] ) : '';
475
- $tooltip = __( 'Enter CSS class names for the form field container. Class names should be seperated with spaces.', 'wpforms' );
476
  // Build output
477
  $output = $this->field_element( 'label', $field, array( 'slug' => 'css', 'value' => __( 'CSS Classes', 'wpforms' ), 'tooltip' => $tooltip ), false );
478
  $output .= $this->field_element( 'text', $field, array( 'slug' => 'css', 'value' => $value ), false );
365
  // Field option choices inputs
366
  $option_choices = sprintf( '<ul data-next-id="%s" class="%s" data-field-id="%d" data-field-type="%s">', max( array_keys( $values ) ) +1, $class, $field['id'], $this->type );
367
  foreach ( $values as $key => $value ) {
368
+ $default = !empty( $value['default'] ) ? $value['default'] : '';
369
  $option_choices .= sprintf( '<li data-key="%d">', $key );
370
  $option_choices .= sprintf( '<input type="radio" name="fields[%s][choices][%s][default]" class="default" value="1" %s>', $field['id'], $key, checked( '1', $default, false ) );
371
  $option_choices .= '<span class="move"><i class="fa fa-bars"></i></span>';
472
 
473
  case 'css':
474
  $value = !empty( $field['css'] ) ? esc_attr( $field['css'] ) : '';
475
+ $tooltip = __( 'Enter CSS class names for the form field container. Class names should be separated with spaces.', 'wpforms' );
476
  // Build output
477
  $output = $this->field_element( 'label', $field, array( 'slug' => 'css', 'value' => __( 'CSS Classes', 'wpforms' ), 'tooltip' => $tooltip ), false );
478
  $output .= $this->field_element( 'text', $field, array( 'slug' => 'css', 'value' => $value ), false );
includes/fields/class-email.php CHANGED
@@ -25,6 +25,9 @@ class WPForms_Field_Email extends WPForms_Field {
25
 
26
  // Set field to default to required
27
  add_filter( 'wpforms_field_new_required', array( $this, 'default_required' ), 10, 2 );
 
 
 
28
  }
29
 
30
  /**
@@ -39,24 +42,103 @@ class WPForms_Field_Email extends WPForms_Field {
39
  // Basic field options
40
  //--------------------------------------------------------------------//
41
 
 
42
  $this->field_option( 'basic-options', $field, array( 'markup' => 'open' ) );
43
- $this->field_option( 'label', $field );
44
- $this->field_option( 'description', $field );
45
- $this->field_option( 'required', $field );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
46
  $this->field_option( 'basic-options', $field, array( 'markup' => 'close' ) );
47
 
48
  //--------------------------------------------------------------------//
49
  // Advanced field options
50
  //--------------------------------------------------------------------//
51
 
 
52
  $this->field_option( 'advanced-options', $field, array( 'markup' => 'open' ) );
53
- $this->field_option( 'size', $field );
54
- $this->field_option( 'placeholder', $field );
55
- $this->field_option( 'label_hide', $field );
56
- $this->field_option( 'css', $field );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
57
  $this->field_option( 'advanced-options', $field, array( 'markup' => 'close' ) );
58
  }
59
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
60
  /**
61
  * Field preview inside the builder.
62
  *
@@ -65,12 +147,28 @@ class WPForms_Field_Email extends WPForms_Field {
65
  */
66
  public function field_preview( $field ) {
67
 
68
- $placeholder = !empty( $field['placeholder'] ) ? esc_attr( $field['placeholder'] ) : '';
69
-
70
- $this->field_preview_option( 'label', $field );
71
 
72
- printf( '<input type="email" placeholder="%s" class="primary-input" disabled>', $placeholder );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
73
 
 
74
  $this->field_preview_option( 'description', $field );
75
  }
76
 
@@ -84,13 +182,16 @@ class WPForms_Field_Email extends WPForms_Field {
84
  public function field_display( $field, $field_atts, $form_data ) {
85
 
86
  // Setup and sanitize the necessary data
87
- $field = apply_filters( 'wpforms_email_field_display', $field, $field_atts, $form_data );
88
- $field_placeholder = !empty( $field['placeholder']) ? esc_attr( $field['placeholder'] ) : '';
89
- $field_required = !empty( $field['required'] ) ? ' required' : '';
90
- $field_class = implode( ' ', array_map( 'sanitize_html_class', $field_atts['input_class'] ) );
91
- $field_id = implode( ' ', array_map( 'sanitize_html_class', $field_atts['input_id'] ) );
92
- $field_value = !empty( $field['default_value'] ) ? esc_attr( apply_filters( 'wpforms_process_smart_tags', $field['default_value'], $form_data ) ) : '';
93
- $field_data = '';
 
 
 
94
 
95
  if ( !empty( $field_atts['input_data'] ) ) {
96
  foreach ( $field_atts['input_data'] as $key => $val ) {
@@ -98,40 +199,104 @@ class WPForms_Field_Email extends WPForms_Field {
98
  }
99
  }
100
 
101
- // Primary email field
102
- printf(
103
- '<input type="email" name="wpforms[fields][%d]" id="%s" class="%s" value="%s" placeholder="%s" %s %s>',
104
- $field['id'],
105
- $field_id,
106
- $field_class,
107
- $field_value,
108
- $field_placeholder,
109
- $field_required,
110
- $field_data
111
- );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
112
  }
113
 
114
  /**
115
- * Validates field on form submit.
116
  *
117
- * @since 1.0.0
118
  * @param int $field_id
119
  * @param array $field_submit
120
  * @param array $form_data
121
  */
122
- public function validate( $field_id, $field_submit, $form_data ) {
123
 
124
- $form_id = $form_data['id'];
125
-
126
- // Basic required check - If field is marked as required, check for entry data
127
- if ( !empty( $form_data['fields'][$field_id]['required'] ) && empty( $field_submit ) ) {
128
- wpforms()->process->errors[$form_id][$field_id] = apply_filters( 'wpforms_required_label', __('This field is required', 'wpforms' ) );
129
- }
130
-
131
- // Check that email is valid format
132
- if ( !empty( $field_submit ) && !is_email( $field_submit ) ) {
133
- wpforms()->process->errors[$form_id][$field_id] = apply_filters( 'wpforms_valid_email_label', __('Please enter a valid email address.', 'wpforms' ) );
134
  }
 
 
 
 
 
 
 
 
 
135
  }
136
 
137
  /**
25
 
26
  // Set field to default to required
27
  add_filter( 'wpforms_field_new_required', array( $this, 'default_required' ), 10, 2 );
28
+
29
+ // Set confirmation status to option wrapper class
30
+ add_filter( 'wpforms_builder_field_option_class', array( $this, 'field_option_class' ), 10, 2 );
31
  }
32
 
33
  /**
42
  // Basic field options
43
  //--------------------------------------------------------------------//
44
 
45
+ // Options open markup
46
  $this->field_option( 'basic-options', $field, array( 'markup' => 'open' ) );
47
+
48
+ // Label
49
+ $this->field_option( 'label', $field );
50
+
51
+ // Description
52
+ $this->field_option( 'description', $field );
53
+
54
+ // Required toggle
55
+ $this->field_option( 'required', $field );
56
+
57
+ // Confirmation toggle
58
+ $confirm_check = $this->field_element(
59
+ 'checkbox',
60
+ $field,
61
+ array(
62
+ 'slug' => 'confirmation',
63
+ 'value' => isset( $field['confirmation'] ) ? '1' : '0',
64
+ 'desc' => __( 'Enable Email Confirmation', 'wpforms' ),
65
+ 'tooltip' => __( 'Check this option ask the user to provide their email address twice.', 'wpforms' ),
66
+ ),
67
+ false
68
+ );
69
+ $this->field_element( 'row', $field, array( 'slug' => 'confirmation', 'content' => $confirm_check ) );
70
+
71
+ // Options close markup
72
  $this->field_option( 'basic-options', $field, array( 'markup' => 'close' ) );
73
 
74
  //--------------------------------------------------------------------//
75
  // Advanced field options
76
  //--------------------------------------------------------------------//
77
 
78
+ // Options open markup
79
  $this->field_option( 'advanced-options', $field, array( 'markup' => 'open' ) );
80
+
81
+ // Size
82
+ $this->field_option( 'size', $field );
83
+
84
+ // Placeholder
85
+ $this->field_option( 'placeholder', $field );
86
+
87
+ // Confirmation Placeholder
88
+ $confirm_placehlder_label = $this->field_element(
89
+ 'label',
90
+ $field,
91
+ array(
92
+ 'slug' => 'confirmation_placeholder',
93
+ 'value' => __( 'Confirmation Placeholder Text', 'wpforms' ),
94
+ 'tooltip' => __( 'Enter text for the confirmation field placeholder.', 'wpforms' )
95
+ ),
96
+ false
97
+ );
98
+ $confirm_placehlder_text = $this->field_element(
99
+ 'text',
100
+ $field,
101
+ array(
102
+ 'slug' => 'confirmation_placeholder',
103
+ 'value' => !empty( $field['confirmation_placeholder'] ) ? esc_attr( $field['confirmation_placeholder'] ) : '',
104
+ ),
105
+ false
106
+ );
107
+ $this->field_element( 'row', $field, array( 'slug' => 'confirmation_placeholder', 'content' => $confirm_placehlder_label . $confirm_placehlder_text ) );
108
+
109
+ // Hide Label
110
+ $this->field_option( 'label_hide', $field );
111
+
112
+ // Hide Sub-labels
113
+ $this->field_option( 'sublabel_hide', $field );
114
+
115
+ // Custom CSS classes
116
+ $this->field_option( 'css', $field );
117
+
118
+ // Options close markup
119
  $this->field_option( 'advanced-options', $field, array( 'markup' => 'close' ) );
120
  }
121
 
122
+ /**
123
+ * Add class to field options wrapper to indicate if field confirmation is enabled.
124
+ *
125
+ * @since 1.3.0
126
+ * @param string $class
127
+ * @param array $field
128
+ * @return string
129
+ */
130
+ function field_option_class( $class, $field ) {
131
+
132
+ if ( 'email' == $field['type'] ) {
133
+ if ( isset( $field['confirmation'] ) ) {
134
+ $class = 'wpforms-confirm-enabled';
135
+ } else {
136
+ $class = 'wpforms-confirm-disabled';
137
+ }
138
+ }
139
+ return $class;
140
+ }
141
+
142
  /**
143
  * Field preview inside the builder.
144
  *
147
  */
148
  public function field_preview( $field ) {
149
 
150
+ $placeholder = !empty( $field['placeholder'] ) ? esc_attr( $field['placeholder'] ) : '';
151
+ $confirm = !empty( $field['confirmation'] ) ? 'enabled' : 'disabled';
152
+ $confirm_placeholder = !empty( $field['confirmation_placeholder'] ) ? esc_attr( $field['confirmation_placeholder'] ) : '';
153
 
154
+ // Label
155
+ $this->field_preview_option( 'label', $field );
156
+
157
+ printf( '<div class="wpforms-confirm wpforms-confirm-%s">', $confirm );
158
+
159
+ echo '<div class="wpforms-confirm-primary">';
160
+ printf( '<input type="email" placeholder="%s" class="primary-input" disabled>', $placeholder );
161
+ printf( '<label class="wpforms-sub-label">%s</label>', __( 'Email' , 'wpforms') );
162
+ echo '</div>';
163
+
164
+ echo '<div class="wpforms-confirm-confirmation">';
165
+ printf( '<input type="email" placeholder="%s" class="secondary-input" disabled>', $confirm_placeholder );
166
+ printf( '<label class="wpforms-sub-label">%s</label>', __( 'Confirm Email' , 'wpforms') );
167
+ echo '</div>';
168
+
169
+ echo '</div>';
170
 
171
+ // Description
172
  $this->field_preview_option( 'description', $field );
173
  }
174
 
182
  public function field_display( $field, $field_atts, $form_data ) {
183
 
184
  // Setup and sanitize the necessary data
185
+ $field = apply_filters( 'wpforms_email_field_display', $field, $field_atts, $form_data );
186
+ $field_placeholder = !empty( $field['placeholder']) ? esc_attr( $field['placeholder'] ) : '';
187
+ $field_required = !empty( $field['required'] ) ? ' required' : '';
188
+ $field_class = implode( ' ', array_map( 'sanitize_html_class', $field_atts['input_class'] ) );
189
+ $field_id = implode( ' ', array_map( 'sanitize_html_class', $field_atts['input_id'] ) );
190
+ $field_sublabel = !empty( $field['sublabel_hide'] ) ? 'wpforms-sublabel-hide' : '';
191
+ $field_data = '';
192
+ $confirmation = !empty( $field['confirmation'] ) ? true : false;
193
+ $confirmation_placeholder = !empty( $field['confirmation_placeholder']) ? esc_attr( $field['confirmation_placeholder'] ) : '';
194
+ $form_id = $form_data['id'];
195
 
196
  if ( !empty( $field_atts['input_data'] ) ) {
197
  foreach ( $field_atts['input_data'] as $key => $val ) {
199
  }
200
  }
201
 
202
+ // Normal field
203
+ if ( ! $confirmation ) :
204
+
205
+ // Primary email field
206
+ printf(
207
+ '<input type="email" name="wpforms[fields][%d]" id="%s" class="%s" value="" placeholder="%s" %s %s>',
208
+ $field['id'],
209
+ $field_id,
210
+ $field_class,
211
+ $field_placeholder,
212
+ $field_required,
213
+ $field_data
214
+ );
215
+
216
+ // Field confirmation enabled
217
+ else:
218
+
219
+ printf( '<div class="wpforms-field-row %s">', $field_class );
220
+
221
+ // Primary email field
222
+ echo '<div class="wpforms-field-row-block wpforms-one-half wpforms-first">';
223
+
224
+ $primary_class = 'wpforms-field-email-primary';
225
+ $primary_class .= !empty( $field_required ) ? ' wpforms-field-required' : '';
226
+ $primary_class .= !empty( wpforms()->process->errors[$form_id][$field['id']]['primary'] ) ? ' wpforms-error' : '';
227
+
228
+ printf(
229
+ '<input type="email" name="wpforms[fields][%d][primary]" id="%s" class="%s" value="" placeholder="%s" %s>',
230
+ $field['id'],
231
+ $field_id,
232
+ $primary_class,
233
+ $field_placeholder,
234
+ $field_required
235
+ );
236
+
237
+ if ( !empty( wpforms()->process->errors[$form_id][$field['id']]['primary'] ) ) {
238
+ printf( '<label id="wpforms-%d-field_%d-error" class="wpforms-error" for="wpforms-field_%d">%s</label>', $form_id, $field['id'], $field['id'], esc_html( wpforms()->process->errors[$form_id][$field['id']]['primary'] ) );
239
+ }
240
+
241
+ printf( '<label for="wpforms-%d-field_%d" class="wpforms-field-sublabel %s">%s</label>', $form_id, $field['id'], $field_sublabel, __( 'Email', 'wpforms' ) );
242
+
243
+ echo '</div>';
244
+
245
+ // Secondary email field for confirmation
246
+ echo '<div class="wpforms-field-row-block wpforms-one-half">';
247
+
248
+ $confirmation_class = 'wpforms-field-email-confirmation';
249
+ $confirmation_class .= !empty( $field_required ) ? ' wpforms-field-required' : '';
250
+ $confirmation_class .= !empty( wpforms()->process->errors[$form_id][$field['id']]['confirmation'] ) ? ' wpforms-error' : '';
251
+
252
+ printf(
253
+ '<input type="email" name="wpforms[fields][%d][confirmation]" id="%s" class="%s" value="" placeholder="%s" data-rule-confirm-msg="%s" data-rule-confirm="#%s" %s>',
254
+ $field['id'],
255
+ "wpforms-{$form_id}-field_{$field['id']}-confirmation",
256
+ $confirmation_class,
257
+ $confirmation_placeholder,
258
+ esc_attr( apply_filters( 'wpforms_email_confirmation_msg', __( 'Email does not match.', 'wpforms') ) ),
259
+ $field_id,
260
+ $field_required
261
+ );
262
+
263
+ if ( !empty( wpforms()->process->errors[$form_id][$field['id']]['confirmation'] ) ) {
264
+ printf( '<label id="wpforms-%d-field_%d-confirmation-error" class="wpforms-error" for="wpforms-field_%d-confirmation">%s</label>', $form_id, $field['id'], $field['id'], esc_html( wpforms()->process->errors[$form_id][$field['id']]['confirmation'] ) );
265
+ }
266
+
267
+ printf( '<label for="wpforms-%d-field_%d-confirmation" class="wpforms-field-sublabel %s">%s</label>', $form_id, $field['id'], $field_sublabel, __( 'Confirm Email', 'wpforms' ) );
268
+
269
+ echo '</div>';
270
+
271
+ echo '</div>';
272
+
273
+ endif;
274
  }
275
 
276
  /**
277
+ * Formats and sanitizes field.
278
  *
279
+ * @since 1.3.0
280
  * @param int $field_id
281
  * @param array $field_submit
282
  * @param array $form_data
283
  */
284
+ public function format( $field_id, $field_submit, $form_data ) {
285
 
286
+ if ( empty( $form_data['fields'][$field_id]['confirmation'] ) ) {
287
+ $value = sanitize_text_field( $field_submit );
288
+ } else {
289
+ $value = sanitize_text_field( $field_submit['primary'] );
 
 
 
 
 
 
290
  }
291
+
292
+ $name = !empty( $form_data['fields'][$field_id]['label'] ) ? sanitize_text_field( $form_data['fields'][$field_id]['label'] ) : '';
293
+
294
+ wpforms()->process->fields[$field_id] = array(
295
+ 'name' => $name,
296
+ 'value' => $value,
297
+ 'id' => absint( $field_id ),
298
+ 'type' => $this->type,
299
+ );
300
  }
301
 
302
  /**
includes/fields/class-select.php CHANGED
@@ -126,7 +126,7 @@ class WPForms_Field_Select extends WPForms_Field {
126
 
127
  // Optional placeholder
128
  if ( !empty( $placeholder ) ) {
129
- printf( '<option value="" class="placeholder" selected>%s</option>', $placeholder );
130
  }
131
 
132
  // Check to see if this field is configured for Dynamic Choices,
@@ -203,6 +203,7 @@ class WPForms_Field_Select extends WPForms_Field {
203
  $field_data = '';
204
  $dynamic = !empty( $field['dynamic_choices'] ) ? $field['dynamic_choices'] : false;
205
  $choices = $field['choices'];
 
206
 
207
  if ( !empty( $field_atts['input_data'] ) ) {
208
  foreach ( $field_atts['input_data'] as $key => $val ) {
@@ -210,6 +211,14 @@ class WPForms_Field_Select extends WPForms_Field {
210
  }
211
  }
212
 
 
 
 
 
 
 
 
 
213
  // Primary select field
214
  printf( '<select name="wpforms[fields][%d]" id="%s" class="%s" %s %s>',
215
  $field['id'],
@@ -221,7 +230,7 @@ class WPForms_Field_Select extends WPForms_Field {
221
 
222
  // Optional placeholder
223
  if ( !empty( $field_placeholder ) ) {
224
- printf('<option class="placeholder" selected disabled>%s</option>', $field_placeholder );
225
  }
226
 
227
  // Check to see if this field is configured for Dynamic Choices,
126
 
127
  // Optional placeholder
128
  if ( !empty( $placeholder ) ) {
129
+ printf( '<option value="" class="placeholder">%s</option>', $placeholder );
130
  }
131
 
132
  // Check to see if this field is configured for Dynamic Choices,
203
  $field_data = '';
204
  $dynamic = !empty( $field['dynamic_choices'] ) ? $field['dynamic_choices'] : false;
205
  $choices = $field['choices'];
206
+ $has_default = false;
207
 
208
  if ( !empty( $field_atts['input_data'] ) ) {
209
  foreach ( $field_atts['input_data'] as $key => $val ) {
211
  }
212
  }
213
 
214
+ // Check to see if any of the options have selected by default
215
+ foreach ( $choices as $choice ) {
216
+ if ( isset( $choice['default'] ) ) {
217
+ $has_default = true;
218
+ break;
219
+ }
220
+ }
221
+
222
  // Primary select field
223
  printf( '<select name="wpforms[fields][%d]" id="%s" class="%s" %s %s>',
224
  $field['id'],
230
 
231
  // Optional placeholder
232
  if ( !empty( $field_placeholder ) ) {
233
+ printf('<option value="" class="placeholder" disabled %s>%s</option>', selected( false, $has_default, true ), $field_placeholder );
234
  }
235
 
236
  // Check to see if this field is configured for Dynamic Choices,
includes/integrations.php ADDED
@@ -0,0 +1,109 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Contains various WPForms integrations
4
+ *
5
+ * @package WPForms
6
+ * @author WPForms
7
+ * @since 1.3.0
8
+ * @license GPL-2.0+
9
+ * @copyright Copyright (c) 2016, WPForms LLC
10
+ */
11
+
12
+ /**
13
+ * Register and setup WPForms as a Visual Composer element.
14
+ *
15
+ * @since 1.3.0
16
+ */
17
+ function wpforms_visual_composer_shortcode() {
18
+
19
+ if ( !is_user_logged_in() )
20
+ return;
21
+
22
+ $wpf = wpforms()->form->get( '', array( 'orderby' => 'title' ) );
23
+
24
+ if ( !empty( $wpf ) ) {
25
+ $forms = array( __( 'Select a form to display', 'wpforms' ) => '' );
26
+ foreach( $wpf as $form ) {
27
+ $forms[ $form->post_title ] = $form->ID;
28
+ }
29
+ } else {
30
+ $forms = array( __( 'No forms found', 'wpforms' ) => '' );
31
+ }
32
+
33
+ vc_map( array(
34
+ 'name' => __( 'WPForms', 'wpforms' ),
35
+ 'base' => 'wpforms',
36
+ 'icon' => WPFORMS_PLUGIN_URL . 'assets/images/sullie-vc.png',
37
+ 'category' => __( 'Content', 'wpforms' ),
38
+ 'description' => __( 'Add your form', 'wpforms' ),
39
+ 'params' => array(
40
+ array(
41
+ 'type' => 'dropdown',
42
+ 'heading' => __( 'Form', 'wpforms' ),
43
+ 'param_name' => 'id',
44
+ 'value' => $forms,
45
+ 'save_always' => true,
46
+ 'description' => __( 'Select a form to add it to your post or page.', 'wpforms' ),
47
+ 'admin_label' => true,
48
+ ),
49
+ array(
50
+ 'type' => 'dropdown',
51
+ 'heading' => __( 'Display Form Title', 'wpforms' ),
52
+ 'param_name' => 'title',
53
+ 'value' => array(
54
+ __( 'No', 'wpforms' ) => 'false',
55
+ __( 'Yes', 'wpforms' ) => 'true',
56
+ ),
57
+ 'save_always' => true,
58
+ 'description' => __( 'Would you like to display the forms title?', 'wpforms' ),
59
+ 'dependency' => array(
60
+ 'element' => 'id',
61
+ 'not_empty' => true,
62
+ ),
63
+ ),
64
+ array(
65
+ 'type' => 'dropdown',
66
+ 'heading' => __( 'Display Form Description', 'wpforms' ),
67
+ 'param_name' => 'description',
68
+ 'value' => array(
69
+ __( 'No', 'wpforms' ) => 'false',
70
+ __( 'Yes', 'wpforms' ) => 'true',
71
+ ),
72
+ 'save_always' => true,
73
+ 'description' => __( 'Would you like to display the forms description?', 'wpforms' ),
74
+ 'dependency' => array(
75
+ 'element' => 'id',
76
+ 'not_empty' => true,
77
+ ),
78
+ ),
79
+ ),
80
+ ) );
81
+ }
82
+ add_action( 'vc_before_init', 'wpforms_visual_composer_shortcode' );
83
+
84
+ /**
85
+ * Load our basic CSS when in Visual Composer's frontend editor.
86
+ *
87
+ * @since 1.3.0
88
+ */
89
+ function wpforms_visual_composer_shortcode_css() {
90
+
91
+ // Load CSS per global setting
92
+ if ( wpforms_setting( 'disable-css', '1' ) == '1' ) {
93
+ wp_enqueue_style(
94
+ 'wpforms-full',
95
+ WPFORMS_PLUGIN_URL . 'assets/css/wpforms-full.css',
96
+ array(),
97
+ WPFORMS_VERSION
98
+ );
99
+ }
100
+ if ( wpforms_setting( 'disable-css', '1' ) == '2' ) {
101
+ wp_enqueue_style(
102
+ 'wpforms-base',
103
+ WPFORMS_PLUGIN_URL . 'assets/css/wpforms-base.css',
104
+ array(),
105
+ WPFORMS_VERSION
106
+ );
107
+ }
108
+ }
109
+ add_action( 'vc_load_iframe_jscss', 'wpforms_visual_composer_shortcode_css' );
languages/wpforms.pot CHANGED
@@ -2,9 +2,9 @@
2
  # This file is distributed under the same license as the WPForms package.
3
  msgid ""
4
  msgstr ""
5
- "Project-Id-Version: WPForms 1.2.9\n"
6
  "Report-Msgid-Bugs-To: https://wordpress.org/support/plugin/wpforms\n"
7
- "POT-Creation-Date: 2016-10-04 15:34:00+00:00\n"
8
  "MIME-Version: 1.0\n"
9
  "Content-Type: text/plain; charset=UTF-8\n"
10
  "Content-Transfer-Encoding: 8bit\n"
@@ -49,218 +49,235 @@ msgid "taxonomy"
49
  msgstr ""
50
 
51
  #: includes/admin/builder/class-builder.php:260
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
52
  msgid ""
53
  "The {source} {type} contains over {limit} items ({total}). This may make the "
54
  "field difficult for your vistors to use and/or cause the form to be slow."
55
  msgstr ""
56
 
57
- #: includes/admin/builder/class-builder.php:261
58
  #: includes/admin/class-editor.php:96
59
  #: pro/includes/admin/entries/class-entries.php:977
60
  msgid "Cancel"
61
  msgstr ""
62
 
63
- #: includes/admin/builder/class-builder.php:262
64
  msgid "OK"
65
  msgstr ""
66
 
67
- #: includes/admin/builder/class-builder.php:263
68
  #: includes/admin/class-editor.php:70
69
  msgid "Close"
70
  msgstr ""
71
 
72
- #: includes/admin/builder/class-builder.php:264
73
  msgid ""
74
  "Due to form changes, conditional logic rules have been removed or updated:"
75
  msgstr ""
76
 
77
- #: includes/admin/builder/class-builder.php:265
78
  #: pro/includes/admin/entries/class-entries-table.php:167
79
  msgid "Field"
80
  msgstr ""
81
 
82
- #: includes/admin/builder/class-builder.php:266
83
  msgid "Field Locked"
84
  msgstr ""
85
 
86
- #: includes/admin/builder/class-builder.php:267
87
  msgid "This field cannot be deleted or duplicated."
88
  msgstr ""
89
 
90
- #: includes/admin/builder/class-builder.php:268
91
  msgid "Available Fields"
92
  msgstr ""
93
 
94
- #: includes/admin/builder/class-builder.php:269
95
  msgid "No fields available"
96
  msgstr ""
97
 
98
- #: includes/admin/builder/class-builder.php:270
99
  msgid "Heads up!"
100
  msgstr ""
101
 
102
- #: includes/admin/builder/class-builder.php:272
103
  msgid "No email fields"
104
  msgstr ""
105
 
106
- #: includes/admin/builder/class-builder.php:273
107
  msgid "Are you sure you want to delete this notification?"
108
  msgstr ""
109
 
110
- #: includes/admin/builder/class-builder.php:274
111
  msgid "Enter a notification name"
112
  msgstr ""
113
 
114
- #: includes/admin/builder/class-builder.php:275
115
  msgid "Eg: User Confirmation"
116
  msgstr ""
117
 
118
- #: includes/admin/builder/class-builder.php:276
119
  msgid "You must provide a notification name"
120
  msgstr ""
121
 
122
- #: includes/admin/builder/class-builder.php:277
123
  msgid ""
124
  "Form must contain one notification. To disable all notifications use the "
125
  "setting Notifications dropdown setting."
126
  msgstr ""
127
 
128
- #: includes/admin/builder/class-builder.php:278
129
  #: lite/includes/admin/class-settings.php:131
130
  #: pro/includes/admin/class-settings.php:135
131
  msgid "Saving ..."
132
  msgstr ""
133
 
134
- #: includes/admin/builder/class-builder.php:279
135
  msgid "Saved!"
136
  msgstr ""
137
 
138
- #: includes/admin/builder/class-builder.php:280
139
  msgid "Save and Exit"
140
  msgstr ""
141
 
142
- #: includes/admin/builder/class-builder.php:281
143
- #: includes/admin/builder/class-builder.php:344
144
  msgid "Loading"
145
  msgstr ""
146
 
147
- #: includes/admin/builder/class-builder.php:287
148
  msgid "Use Template"
149
  msgstr ""
150
 
151
- #: includes/admin/builder/class-builder.php:288
152
  msgid ""
153
  "Changing templates on an existing form will DELETE existing form fields. Are "
154
  "you sure you want apply the new template?"
155
  msgstr ""
156
 
157
- #: includes/admin/builder/class-builder.php:289
158
  msgid ""
159
  "You are almost done. To embed this form on your site, please paste the "
160
  "following shortcode inside a post or page."
161
  msgstr ""
162
 
163
- #: includes/admin/builder/class-builder.php:290
164
  msgid "Or you can follow the instructions in this video."
165
  msgstr ""
166
 
167
- #: includes/admin/builder/class-builder.php:291
168
- #: includes/admin/builder/class-builder.php:394
169
  msgid "Exit"
170
  msgstr ""
171
 
172
- #: includes/admin/builder/class-builder.php:293
173
  msgid "If you exit without saving, your changes will be lost."
174
  msgstr ""
175
 
176
- #: includes/admin/builder/class-builder.php:294
177
  msgid "Are you sure you want to delete this field?"
178
  msgstr ""
179
 
180
- #: includes/admin/builder/class-builder.php:295
181
  msgid "Are you sure you want to duplicate this field?"
182
  msgstr ""
183
 
184
- #: includes/admin/builder/class-builder.php:296
185
  msgid "(copy)"
186
  msgstr ""
187
 
188
- #: includes/admin/builder/class-builder.php:297
189
  msgid "Please enter a form title."
190
  msgstr ""
191
 
192
- #: includes/admin/builder/class-builder.php:298
193
  msgid "This item must contain at least one choice."
194
  msgstr ""
195
 
196
- #: includes/admin/builder/class-builder.php:299
197
  #: includes/fields/class-base.php:239 includes/fields/class-base.php:523
198
  #: lite/wpforms-lite.php:75 pro/wpforms-pro.php:258
199
  msgid "Off"
200
  msgstr ""
201
 
202
- #: includes/admin/builder/class-builder.php:300
203
  #: includes/fields/class-base.php:239 lite/wpforms-lite.php:74
204
  #: pro/wpforms-pro.php:257
205
  msgid "On"
206
  msgstr ""
207
 
208
- #: includes/admin/builder/class-builder.php:301
209
  #: includes/templates/class-suggestion.php:59
210
  msgid "Other"
211
  msgstr ""
212
 
213
- #: includes/admin/builder/class-builder.php:302
214
- #: includes/class-frontend.php:485
215
  #: pro/includes/fields/class-page-break.php:144
216
  msgid "Previous"
217
  msgstr ""
218
 
219
- #: includes/admin/builder/class-builder.php:305
220
  #: includes/admin/builder/functions.php:210 includes/fields/class-base.php:424
221
  msgid "Show Smart Tags"
222
  msgstr ""
223
 
224
- #: includes/admin/builder/class-builder.php:306
225
  msgid "Hide Smart Tags"
226
  msgstr ""
227
 
228
- #: includes/admin/builder/class-builder.php:307
229
  msgid "-- Select Field --"
230
  msgstr ""
231
 
232
- #: includes/admin/builder/class-builder.php:308
233
  #: pro/includes/class-provider.php:945
234
  msgid "-- Select Choice --"
235
  msgstr ""
236
 
237
- #: includes/admin/builder/class-builder.php:367
238
  msgid "Now editing"
239
  msgstr ""
240
 
241
- #: includes/admin/builder/class-builder.php:377
242
  #: pro/includes/admin/entries/class-entries.php:511
243
  msgid "Preview Form"
244
  msgstr ""
245
 
246
- #: includes/admin/builder/class-builder.php:379
247
  #: includes/admin/overview/class-overview-table.php:159
248
  msgid "Preview"
249
  msgstr ""
250
 
251
- #: includes/admin/builder/class-builder.php:382
252
  msgid "Embed Form"
253
  msgstr ""
254
 
255
- #: includes/admin/builder/class-builder.php:384
256
  msgid "Embed"
257
  msgstr ""
258
 
259
- #: includes/admin/builder/class-builder.php:387
260
  msgid "Save Form"
261
  msgstr ""
262
 
263
- #: includes/admin/builder/class-builder.php:389
264
  #: pro/includes/admin/class-settings.php:441
265
  msgid "Save"
266
  msgstr ""
@@ -308,21 +325,21 @@ msgstr ""
308
  msgid "You don't have any fields yet."
309
  msgstr ""
310
 
311
- #: includes/admin/builder/panels/class-fields.php:230
312
  msgid "You don't have any fields yet. Add some!"
313
  msgstr ""
314
 
315
- #: includes/admin/builder/panels/class-fields.php:250
316
  #: includes/fields/class-base.php:703
317
  msgid "Duplicate Field"
318
  msgstr ""
319
 
320
- #: includes/admin/builder/panels/class-fields.php:252
321
  #: includes/fields/class-base.php:704
322
  msgid "Delete Field"
323
  msgstr ""
324
 
325
- #: includes/admin/builder/panels/class-fields.php:254
326
  #: includes/fields/class-base.php:705
327
  msgid "Click to edit. Drag to reorder."
328
  msgstr ""
@@ -376,7 +393,7 @@ msgstr ""
376
  #: includes/admin/builder/panels/class-settings.php:117
377
  msgid ""
378
  "Enter CSS class names for the form wrapper. Multiple class names should be "
379
- "seperated with spaces."
380
  msgstr ""
381
 
382
  #: includes/admin/builder/panels/class-settings.php:124
@@ -400,7 +417,7 @@ msgstr ""
400
  #: includes/admin/builder/panels/class-settings.php:141
401
  msgid ""
402
  "Enter CSS class names for the form submit button. Multiple names should be "
403
- "seperated with spaces."
404
  msgstr ""
405
 
406
  #: includes/admin/builder/panels/class-settings.php:148
@@ -514,12 +531,12 @@ msgid ""
514
  "a>?"
515
  msgstr ""
516
 
517
- #. #-#-#-#-# wpforms.pot (WPForms 1.2.9) #-#-#-#-#
518
  #. Plugin Name of the plugin/theme
519
- #. #-#-#-#-# wpforms.pot (WPForms 1.2.9) #-#-#-#-#
520
  #. Author of the plugin/theme
521
  #: includes/admin/class-menu.php:39 includes/admin/class-menu.php:40
522
- #: includes/admin/class-menu.php:51
523
  msgid "WPForms"
524
  msgstr ""
525
 
@@ -715,11 +732,11 @@ msgstr ""
715
  msgid "Forms Overview"
716
  msgstr ""
717
 
718
- #: includes/class-frontend.php:287
719
  msgid "Step"
720
  msgstr ""
721
 
722
- #: includes/class-frontend.php:288
723
  msgid "of"
724
  msgstr ""
725
 
@@ -826,10 +843,11 @@ msgstr ""
826
  #: includes/class-smart-tags.php:40
827
  #: pro/includes/admin/entries/class-entries-export.php:172
828
  #: pro/includes/admin/entries/class-entries-table.php:129
829
- #: pro/includes/fields/class-date-time.php:48
830
- #: pro/includes/fields/class-date-time.php:77
831
- #: pro/includes/fields/class-date-time.php:155
832
- #: pro/includes/fields/class-date-time.php:218
 
833
  msgid "Date"
834
  msgstr ""
835
 
@@ -891,7 +909,7 @@ msgid ""
891
  "reached"
892
  msgstr ""
893
 
894
- #: includes/emails/class-emails.php:370 includes/emails/class-emails.php:392
895
  msgid "Field ID #"
896
  msgstr ""
897
 
@@ -1000,7 +1018,7 @@ msgstr ""
1000
  #: includes/fields/class-base.php:475
1001
  msgid ""
1002
  "Enter CSS class names for the form field container. Class names should be "
1003
- "seperated with spaces."
1004
  msgstr ""
1005
 
1006
  #: includes/fields/class-base.php:477
@@ -1075,11 +1093,14 @@ msgstr ""
1075
  msgid "No field type found"
1076
  msgstr ""
1077
 
1078
- #: includes/fields/class-base.php:751 includes/fields/class-email.php:128
1079
- #: includes/fields/class-name.php:311 includes/fields/class-number.php:127
1080
  #: pro/includes/fields/class-address.php:624
1081
- #: pro/includes/fields/class-date-time.php:293
1082
- #: pro/includes/fields/class-file-upload.php:358
 
 
 
1083
  #: pro/includes/fields/class-payment-multiple.php:177
1084
  #: pro/includes/fields/class-payment-single.php:189
1085
  #: pro/includes/fields/class-url.php:126
@@ -1125,7 +1146,8 @@ msgid ""
1125
  "viewing the form."
1126
  msgstr ""
1127
 
1128
- #: includes/fields/class-email.php:21
 
1129
  #: lite/includes/admin/class-settings.php:235
1130
  #: pro/includes/admin/class-settings.php:300
1131
  #: pro/includes/templates/class-donation.php:42
@@ -1135,8 +1157,30 @@ msgstr ""
1135
  msgid "Email"
1136
  msgstr ""
1137
 
1138
- #: includes/fields/class-email.php:133
1139
- msgid "Please enter a valid email address."
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1140
  msgstr ""
1141
 
1142
  #: includes/fields/class-name.php:47
@@ -1156,9 +1200,9 @@ msgid "First Middle Last"
1156
  msgstr ""
1157
 
1158
  #: includes/fields/class-name.php:53
1159
- #: pro/includes/fields/class-date-time.php:51
1160
- #: pro/includes/fields/class-date-time.php:88
1161
- #: pro/includes/fields/class-date-time.php:118
1162
  #: pro/includes/fields/class-phone.php:50
1163
  msgid "Format"
1164
  msgstr ""
@@ -1175,8 +1219,8 @@ msgstr ""
1175
  #: pro/includes/fields/class-address.php:162
1176
  #: pro/includes/fields/class-address.php:177
1177
  #: pro/includes/fields/class-address.php:194
1178
- #: pro/includes/fields/class-date-time.php:80
1179
- #: pro/includes/fields/class-date-time.php:110
1180
  msgid "Placeholder"
1181
  msgstr ""
1182
 
@@ -1247,6 +1291,54 @@ msgstr ""
1247
  msgid "Paragraph Text"
1248
  msgstr ""
1249
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1250
  #: includes/templates/class-blank.php:20
1251
  msgid "Blank Form"
1252
  msgstr ""
@@ -1491,7 +1583,7 @@ msgstr ""
1491
  #: lite/wpforms-lite.php:94 pro/wpforms-pro.php:283
1492
  msgid ""
1493
  "Enter the email address to receive form entry notifications. For multiple "
1494
- "notifications, seperate email addresses with a comma."
1495
  msgstr ""
1496
 
1497
  #: lite/wpforms-lite.php:109 pro/wpforms-pro.php:298
@@ -2389,49 +2481,61 @@ msgstr ""
2389
  msgid "Date / Time"
2390
  msgstr ""
2391
 
2392
- #: pro/includes/fields/class-date-time.php:45
2393
  msgid "Select format for the date field."
2394
  msgstr ""
2395
 
2396
- #: pro/includes/fields/class-date-time.php:47
2397
  msgid "Date and Time"
2398
  msgstr ""
2399
 
2400
- #: pro/includes/fields/class-date-time.php:49
2401
- #: pro/includes/fields/class-date-time.php:107
2402
- #: pro/includes/fields/class-date-time.php:159
2403
- #: pro/includes/fields/class-date-time.php:243
2404
  msgid "Time"
2405
  msgstr ""
2406
 
2407
- #: pro/includes/fields/class-date-time.php:77
2408
  msgid "Advanced date options."
2409
  msgstr ""
2410
 
2411
- #: pro/includes/fields/class-date-time.php:101
2412
- msgid "1 minute"
 
 
 
 
 
 
 
 
2413
  msgstr ""
2414
 
2415
- #: pro/includes/fields/class-date-time.php:102
2416
  msgid "15 minutes"
2417
  msgstr ""
2418
 
2419
- #: pro/includes/fields/class-date-time.php:103
2420
  msgid "30 minute"
2421
  msgstr ""
2422
 
2423
- #: pro/includes/fields/class-date-time.php:104
2424
  msgid "1 hour"
2425
  msgstr ""
2426
 
2427
- #: pro/includes/fields/class-date-time.php:107
2428
  msgid "Advanced time options"
2429
  msgstr ""
2430
 
2431
- #: pro/includes/fields/class-date-time.php:126
2432
  msgid "Interval"
2433
  msgstr ""
2434
 
 
 
 
 
2435
  #: pro/includes/fields/class-divider.php:21
2436
  msgid "Section Divider"
2437
  msgstr ""
@@ -2440,79 +2544,79 @@ msgstr ""
2440
  msgid "File Upload"
2441
  msgstr ""
2442
 
2443
- #: pro/includes/fields/class-file-upload.php:140
2444
  msgid "Allowed File Extensions"
2445
  msgstr ""
2446
 
2447
- #: pro/includes/fields/class-file-upload.php:141
2448
  msgid "Enter the extensions you would like to allow, comma separated."
2449
  msgstr ""
2450
 
2451
- #: pro/includes/fields/class-file-upload.php:162
2452
  msgid "Max File Size"
2453
  msgstr ""
2454
 
2455
- #: pro/includes/fields/class-file-upload.php:163
2456
  msgid ""
2457
  "Enter the max file size, in megabytyes, to allow. If left blank, the value "
2458
  "defaults to the maximum size the server allows which is "
2459
  msgstr ""
2460
 
2461
- #: pro/includes/fields/class-file-upload.php:207
2462
  msgid "Store file in WordPress Media Library"
2463
  msgstr ""
2464
 
2465
- #: pro/includes/fields/class-file-upload.php:208
2466
  msgid ""
2467
  "Check this option to store the final uploaded file in the WordPress Media "
2468
  "Library"
2469
  msgstr ""
2470
 
2471
- #: pro/includes/fields/class-file-upload.php:340
2472
  msgid "The uploaded file exceeds the upload_max_filesize directive in php.ini."
2473
  msgstr ""
2474
 
2475
- #: pro/includes/fields/class-file-upload.php:341
2476
  msgid ""
2477
  "The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in "
2478
  "the HTML form."
2479
  msgstr ""
2480
 
2481
- #: pro/includes/fields/class-file-upload.php:342
2482
  msgid "The uploaded file was only partially uploaded."
2483
  msgstr ""
2484
 
2485
- #: pro/includes/fields/class-file-upload.php:343
2486
  msgid "No file was uploaded."
2487
  msgstr ""
2488
 
2489
- #: pro/includes/fields/class-file-upload.php:345
2490
  msgid "Missing a temporary folder."
2491
  msgstr ""
2492
 
2493
- #: pro/includes/fields/class-file-upload.php:346
2494
  msgid "Failed to write file to disk."
2495
  msgstr ""
2496
 
2497
- #: pro/includes/fields/class-file-upload.php:347
2498
  msgid "File upload stopped by extension."
2499
  msgstr ""
2500
 
2501
- #: pro/includes/fields/class-file-upload.php:349
2502
  msgid "File upload error. "
2503
  msgstr ""
2504
 
2505
- #: pro/includes/fields/class-file-upload.php:368
2506
  msgid "File exceeds max size allowed"
2507
  msgstr ""
2508
 
2509
- #: pro/includes/fields/class-file-upload.php:386
2510
  msgid "File must have an extension."
2511
  msgstr ""
2512
 
2513
- #: pro/includes/fields/class-file-upload.php:396
2514
- #: pro/includes/fields/class-file-upload.php:415
2515
- #: pro/includes/fields/class-file-upload.php:433
2516
  msgid "File type is not allowed."
2517
  msgstr ""
2518
 
@@ -2629,9 +2733,32 @@ msgid "First Page"
2629
  msgstr ""
2630
 
2631
  #: pro/includes/fields/class-password.php:21
 
 
2632
  msgid "Password"
2633
  msgstr ""
2634
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2635
  #: pro/includes/fields/class-payment-credit-card.php:21
2636
  msgid "Credit Card"
2637
  msgstr ""
@@ -2674,10 +2801,6 @@ msgid ""
2674
  "only."
2675
  msgstr ""
2676
 
2677
- #: pro/includes/fields/class-payment-credit-card.php:265
2678
- msgid "MM"
2679
- msgstr ""
2680
-
2681
  #: pro/includes/fields/class-payment-credit-card.php:284
2682
  msgid "YY"
2683
  msgstr ""
@@ -2983,9 +3106,9 @@ msgstr ""
2983
  msgid "Please deactivate WPForms Lite before activating WPForms"
2984
  msgstr ""
2985
 
2986
- #. #-#-#-#-# wpforms.pot (WPForms 1.2.9) #-#-#-#-#
2987
  #. Plugin URI of the plugin/theme
2988
- #. #-#-#-#-# wpforms.pot (WPForms 1.2.9) #-#-#-#-#
2989
  #. Author URI of the plugin/theme
2990
  msgid "https://wpforms.com"
2991
  msgstr ""
2
  # This file is distributed under the same license as the WPForms package.
3
  msgid ""
4
  msgstr ""
5
+ "Project-Id-Version: WPForms 1.3.0\n"
6
  "Report-Msgid-Bugs-To: https://wordpress.org/support/plugin/wpforms\n"
7
+ "POT-Creation-Date: 2016-10-21 15:08:29+00:00\n"
8
  "MIME-Version: 1.0\n"
9
  "Content-Type: text/plain; charset=UTF-8\n"
10
  "Content-Transfer-Encoding: 8bit\n"
49
  msgstr ""
50
 
51
  #: includes/admin/builder/class-builder.php:260
52
+ #: pro/includes/fields/class-date-time.php:229
53
+ #: pro/includes/fields/class-date-time.php:231
54
+ #: pro/includes/fields/class-date-time.php:452
55
+ #: pro/includes/fields/class-date-time.php:471
56
+ msgid "DD"
57
+ msgstr ""
58
+
59
+ #: includes/admin/builder/class-builder.php:261
60
+ #: pro/includes/fields/class-date-time.php:228
61
+ #: pro/includes/fields/class-date-time.php:232
62
+ #: pro/includes/fields/class-date-time.php:433
63
+ #: pro/includes/fields/class-date-time.php:490
64
+ #: pro/includes/fields/class-payment-credit-card.php:265
65
+ msgid "MM"
66
+ msgstr ""
67
+
68
+ #: includes/admin/builder/class-builder.php:262
69
  msgid ""
70
  "The {source} {type} contains over {limit} items ({total}). This may make the "
71
  "field difficult for your vistors to use and/or cause the form to be slow."
72
  msgstr ""
73
 
74
+ #: includes/admin/builder/class-builder.php:263
75
  #: includes/admin/class-editor.php:96
76
  #: pro/includes/admin/entries/class-entries.php:977
77
  msgid "Cancel"
78
  msgstr ""
79
 
80
+ #: includes/admin/builder/class-builder.php:264
81
  msgid "OK"
82
  msgstr ""
83
 
84
+ #: includes/admin/builder/class-builder.php:265
85
  #: includes/admin/class-editor.php:70
86
  msgid "Close"
87
  msgstr ""
88
 
89
+ #: includes/admin/builder/class-builder.php:266
90
  msgid ""
91
  "Due to form changes, conditional logic rules have been removed or updated:"
92
  msgstr ""
93
 
94
+ #: includes/admin/builder/class-builder.php:267
95
  #: pro/includes/admin/entries/class-entries-table.php:167
96
  msgid "Field"
97
  msgstr ""
98
 
99
+ #: includes/admin/builder/class-builder.php:268
100
  msgid "Field Locked"
101
  msgstr ""
102
 
103
+ #: includes/admin/builder/class-builder.php:269
104
  msgid "This field cannot be deleted or duplicated."
105
  msgstr ""
106
 
107
+ #: includes/admin/builder/class-builder.php:270
108
  msgid "Available Fields"
109
  msgstr ""
110
 
111
+ #: includes/admin/builder/class-builder.php:271
112
  msgid "No fields available"
113
  msgstr ""
114
 
115
+ #: includes/admin/builder/class-builder.php:272
116
  msgid "Heads up!"
117
  msgstr ""
118
 
119
+ #: includes/admin/builder/class-builder.php:274
120
  msgid "No email fields"
121
  msgstr ""
122
 
123
+ #: includes/admin/builder/class-builder.php:275
124
  msgid "Are you sure you want to delete this notification?"
125
  msgstr ""
126
 
127
+ #: includes/admin/builder/class-builder.php:276
128
  msgid "Enter a notification name"
129
  msgstr ""
130
 
131
+ #: includes/admin/builder/class-builder.php:277
132
  msgid "Eg: User Confirmation"
133
  msgstr ""
134
 
135
+ #: includes/admin/builder/class-builder.php:278
136
  msgid "You must provide a notification name"
137
  msgstr ""
138
 
139
+ #: includes/admin/builder/class-builder.php:279
140
  msgid ""
141
  "Form must contain one notification. To disable all notifications use the "
142
  "setting Notifications dropdown setting."
143
  msgstr ""
144
 
145
+ #: includes/admin/builder/class-builder.php:280
146
  #: lite/includes/admin/class-settings.php:131
147
  #: pro/includes/admin/class-settings.php:135
148
  msgid "Saving ..."
149
  msgstr ""
150
 
151
+ #: includes/admin/builder/class-builder.php:281
152
  msgid "Saved!"
153
  msgstr ""
154
 
155
+ #: includes/admin/builder/class-builder.php:282
156
  msgid "Save and Exit"
157
  msgstr ""
158
 
159
+ #: includes/admin/builder/class-builder.php:283
160
+ #: includes/admin/builder/class-builder.php:346
161
  msgid "Loading"
162
  msgstr ""
163
 
164
+ #: includes/admin/builder/class-builder.php:289
165
  msgid "Use Template"
166
  msgstr ""
167
 
168
+ #: includes/admin/builder/class-builder.php:290
169
  msgid ""
170
  "Changing templates on an existing form will DELETE existing form fields. Are "
171
  "you sure you want apply the new template?"
172
  msgstr ""
173
 
174
+ #: includes/admin/builder/class-builder.php:291
175
  msgid ""
176
  "You are almost done. To embed this form on your site, please paste the "
177
  "following shortcode inside a post or page."
178
  msgstr ""
179
 
180
+ #: includes/admin/builder/class-builder.php:292
181
  msgid "Or you can follow the instructions in this video."
182
  msgstr ""
183
 
184
+ #: includes/admin/builder/class-builder.php:293
185
+ #: includes/admin/builder/class-builder.php:396
186
  msgid "Exit"
187
  msgstr ""
188
 
189
+ #: includes/admin/builder/class-builder.php:295
190
  msgid "If you exit without saving, your changes will be lost."
191
  msgstr ""
192
 
193
+ #: includes/admin/builder/class-builder.php:296
194
  msgid "Are you sure you want to delete this field?"
195
  msgstr ""
196
 
197
+ #: includes/admin/builder/class-builder.php:297
198
  msgid "Are you sure you want to duplicate this field?"
199
  msgstr ""
200
 
201
+ #: includes/admin/builder/class-builder.php:298
202
  msgid "(copy)"
203
  msgstr ""
204
 
205
+ #: includes/admin/builder/class-builder.php:299
206
  msgid "Please enter a form title."
207
  msgstr ""
208
 
209
+ #: includes/admin/builder/class-builder.php:300
210
  msgid "This item must contain at least one choice."
211
  msgstr ""
212
 
213
+ #: includes/admin/builder/class-builder.php:301
214
  #: includes/fields/class-base.php:239 includes/fields/class-base.php:523
215
  #: lite/wpforms-lite.php:75 pro/wpforms-pro.php:258
216
  msgid "Off"
217
  msgstr ""
218
 
219
+ #: includes/admin/builder/class-builder.php:302
220
  #: includes/fields/class-base.php:239 lite/wpforms-lite.php:74
221
  #: pro/wpforms-pro.php:257
222
  msgid "On"
223
  msgstr ""
224
 
225
+ #: includes/admin/builder/class-builder.php:303
226
  #: includes/templates/class-suggestion.php:59
227
  msgid "Other"
228
  msgstr ""
229
 
230
+ #: includes/admin/builder/class-builder.php:304
231
+ #: includes/class-frontend.php:492
232
  #: pro/includes/fields/class-page-break.php:144
233
  msgid "Previous"
234
  msgstr ""
235
 
236
+ #: includes/admin/builder/class-builder.php:307
237
  #: includes/admin/builder/functions.php:210 includes/fields/class-base.php:424
238
  msgid "Show Smart Tags"
239
  msgstr ""
240
 
241
+ #: includes/admin/builder/class-builder.php:308
242
  msgid "Hide Smart Tags"
243
  msgstr ""
244
 
245
+ #: includes/admin/builder/class-builder.php:309
246
  msgid "-- Select Field --"
247
  msgstr ""
248
 
249
+ #: includes/admin/builder/class-builder.php:310
250
  #: pro/includes/class-provider.php:945
251
  msgid "-- Select Choice --"
252
  msgstr ""
253
 
254
+ #: includes/admin/builder/class-builder.php:369
255
  msgid "Now editing"
256
  msgstr ""
257
 
258
+ #: includes/admin/builder/class-builder.php:379
259
  #: pro/includes/admin/entries/class-entries.php:511
260
  msgid "Preview Form"
261
  msgstr ""
262
 
263
+ #: includes/admin/builder/class-builder.php:381
264
  #: includes/admin/overview/class-overview-table.php:159
265
  msgid "Preview"
266
  msgstr ""
267
 
268
+ #: includes/admin/builder/class-builder.php:384
269
  msgid "Embed Form"
270
  msgstr ""
271
 
272
+ #: includes/admin/builder/class-builder.php:386
273
  msgid "Embed"
274
  msgstr ""
275
 
276
+ #: includes/admin/builder/class-builder.php:389
277
  msgid "Save Form"
278
  msgstr ""
279
 
280
+ #: includes/admin/builder/class-builder.php:391
281
  #: pro/includes/admin/class-settings.php:441
282
  msgid "Save"
283
  msgstr ""
325
  msgid "You don't have any fields yet."
326
  msgstr ""
327
 
328
+ #: includes/admin/builder/panels/class-fields.php:232
329
  msgid "You don't have any fields yet. Add some!"
330
  msgstr ""
331
 
332
+ #: includes/admin/builder/panels/class-fields.php:252
333
  #: includes/fields/class-base.php:703
334
  msgid "Duplicate Field"
335
  msgstr ""
336
 
337
+ #: includes/admin/builder/panels/class-fields.php:254
338
  #: includes/fields/class-base.php:704
339
  msgid "Delete Field"
340
  msgstr ""
341
 
342
+ #: includes/admin/builder/panels/class-fields.php:256
343
  #: includes/fields/class-base.php:705
344
  msgid "Click to edit. Drag to reorder."
345
  msgstr ""
393
  #: includes/admin/builder/panels/class-settings.php:117
394
  msgid ""
395
  "Enter CSS class names for the form wrapper. Multiple class names should be "
396
+ "separated with spaces."
397
  msgstr ""
398
 
399
  #: includes/admin/builder/panels/class-settings.php:124
417
  #: includes/admin/builder/panels/class-settings.php:141
418
  msgid ""
419
  "Enter CSS class names for the form submit button. Multiple names should be "
420
+ "separated with spaces."
421
  msgstr ""
422
 
423
  #: includes/admin/builder/panels/class-settings.php:148
531
  "a>?"
532
  msgstr ""
533
 
534
+ #. #-#-#-#-# wpforms.pot (WPForms 1.3.0) #-#-#-#-#
535
  #. Plugin Name of the plugin/theme
536
+ #. #-#-#-#-# wpforms.pot (WPForms 1.3.0) #-#-#-#-#
537
  #. Author of the plugin/theme
538
  #: includes/admin/class-menu.php:39 includes/admin/class-menu.php:40
539
+ #: includes/admin/class-menu.php:51 includes/integrations.php:34
540
  msgid "WPForms"
541
  msgstr ""
542
 
732
  msgid "Forms Overview"
733
  msgstr ""
734
 
735
+ #: includes/class-frontend.php:294
736
  msgid "Step"
737
  msgstr ""
738
 
739
+ #: includes/class-frontend.php:295
740
  msgid "of"
741
  msgstr ""
742
 
843
  #: includes/class-smart-tags.php:40
844
  #: pro/includes/admin/entries/class-entries-export.php:172
845
  #: pro/includes/admin/entries/class-entries-table.php:129
846
+ #: pro/includes/fields/class-date-time.php:69
847
+ #: pro/includes/fields/class-date-time.php:117
848
+ #: pro/includes/fields/class-date-time.php:244
849
+ #: pro/includes/fields/class-date-time.php:252
850
+ #: pro/includes/fields/class-date-time.php:338
851
  msgid "Date"
852
  msgstr ""
853
 
909
  "reached"
910
  msgstr ""
911
 
912
+ #: includes/emails/class-emails.php:375 includes/emails/class-emails.php:397
913
  msgid "Field ID #"
914
  msgstr ""
915
 
1018
  #: includes/fields/class-base.php:475
1019
  msgid ""
1020
  "Enter CSS class names for the form field container. Class names should be "
1021
+ "separated with spaces."
1022
  msgstr ""
1023
 
1024
  #: includes/fields/class-base.php:477
1093
  msgid "No field type found"
1094
  msgstr ""
1095
 
1096
+ #: includes/fields/class-base.php:751 includes/fields/class-name.php:311
1097
+ #: includes/fields/class-number.php:127
1098
  #: pro/includes/fields/class-address.php:624
1099
+ #: pro/includes/fields/class-date-time.php:532
1100
+ #: pro/includes/fields/class-file-upload.php:359
1101
+ #: pro/includes/fields/class-password.php:296
1102
+ #: pro/includes/fields/class-password.php:304
1103
+ #: pro/includes/fields/class-password.php:309
1104
  #: pro/includes/fields/class-payment-multiple.php:177
1105
  #: pro/includes/fields/class-payment-single.php:189
1106
  #: pro/includes/fields/class-url.php:126
1146
  "viewing the form."
1147
  msgstr ""
1148
 
1149
+ #: includes/fields/class-email.php:21 includes/fields/class-email.php:161
1150
+ #: includes/fields/class-email.php:241
1151
  #: lite/includes/admin/class-settings.php:235
1152
  #: pro/includes/admin/class-settings.php:300
1153
  #: pro/includes/templates/class-donation.php:42
1157
  msgid "Email"
1158
  msgstr ""
1159
 
1160
+ #: includes/fields/class-email.php:64
1161
+ msgid "Enable Email Confirmation"
1162
+ msgstr ""
1163
+
1164
+ #: includes/fields/class-email.php:65
1165
+ msgid "Check this option ask the user to provide their email address twice."
1166
+ msgstr ""
1167
+
1168
+ #: includes/fields/class-email.php:93
1169
+ #: pro/includes/fields/class-password.php:91
1170
+ msgid "Confirmation Placeholder Text"
1171
+ msgstr ""
1172
+
1173
+ #: includes/fields/class-email.php:94
1174
+ #: pro/includes/fields/class-password.php:92
1175
+ msgid "Enter text for the confirmation field placeholder."
1176
+ msgstr ""
1177
+
1178
+ #: includes/fields/class-email.php:166 includes/fields/class-email.php:267
1179
+ msgid "Confirm Email"
1180
+ msgstr ""
1181
+
1182
+ #: includes/fields/class-email.php:258
1183
+ msgid "Email does not match."
1184
  msgstr ""
1185
 
1186
  #: includes/fields/class-name.php:47
1200
  msgstr ""
1201
 
1202
  #: includes/fields/class-name.php:53
1203
+ #: pro/includes/fields/class-date-time.php:56
1204
+ #: pro/includes/fields/class-date-time.php:132
1205
+ #: pro/includes/fields/class-date-time.php:168
1206
  #: pro/includes/fields/class-phone.php:50
1207
  msgid "Format"
1208
  msgstr ""
1219
  #: pro/includes/fields/class-address.php:162
1220
  #: pro/includes/fields/class-address.php:177
1221
  #: pro/includes/fields/class-address.php:194
1222
+ #: pro/includes/fields/class-date-time.php:120
1223
+ #: pro/includes/fields/class-date-time.php:160
1224
  msgid "Placeholder"
1225
  msgstr ""
1226
 
1291
  msgid "Paragraph Text"
1292
  msgstr ""
1293
 
1294
+ #: includes/integrations.php:25
1295
+ msgid "Select a form to display"
1296
+ msgstr ""
1297
+
1298
+ #: includes/integrations.php:30
1299
+ msgid "No forms found"
1300
+ msgstr ""
1301
+
1302
+ #: includes/integrations.php:37
1303
+ msgid "Content"
1304
+ msgstr ""
1305
+
1306
+ #: includes/integrations.php:38
1307
+ msgid "Add your form"
1308
+ msgstr ""
1309
+
1310
+ #: includes/integrations.php:42
1311
+ msgid "Form"
1312
+ msgstr ""
1313
+
1314
+ #: includes/integrations.php:46
1315
+ msgid "Select a form to add it to your post or page."
1316
+ msgstr ""
1317
+
1318
+ #: includes/integrations.php:51
1319
+ msgid "Display Form Title"
1320
+ msgstr ""
1321
+
1322
+ #: includes/integrations.php:54 includes/integrations.php:69
1323
+ msgid "No"
1324
+ msgstr ""
1325
+
1326
+ #: includes/integrations.php:55 includes/integrations.php:70
1327
+ msgid "Yes"
1328
+ msgstr ""
1329
+
1330
+ #: includes/integrations.php:58
1331
+ msgid "Would you like to display the forms title?"
1332
+ msgstr ""
1333
+
1334
+ #: includes/integrations.php:66
1335
+ msgid "Display Form Description"
1336
+ msgstr ""
1337
+
1338
+ #: includes/integrations.php:73
1339
+ msgid "Would you like to display the forms description?"
1340
+ msgstr ""
1341
+
1342
  #: includes/templates/class-blank.php:20
1343
  msgid "Blank Form"
1344
  msgstr ""
1583
  #: lite/wpforms-lite.php:94 pro/wpforms-pro.php:283
1584
  msgid ""
1585
  "Enter the email address to receive form entry notifications. For multiple "
1586
+ "notifications, separate email addresses with a comma."
1587
  msgstr ""
1588
 
1589
  #: lite/wpforms-lite.php:109 pro/wpforms-pro.php:298
2481
  msgid "Date / Time"
2482
  msgstr ""
2483
 
2484
+ #: pro/includes/fields/class-date-time.php:57
2485
  msgid "Select format for the date field."
2486
  msgstr ""
2487
 
2488
+ #: pro/includes/fields/class-date-time.php:68
2489
  msgid "Date and Time"
2490
  msgstr ""
2491
 
2492
+ #: pro/includes/fields/class-date-time.php:70
2493
+ #: pro/includes/fields/class-date-time.php:157
2494
+ #: pro/includes/fields/class-date-time.php:259
2495
+ #: pro/includes/fields/class-date-time.php:364
2496
  msgid "Time"
2497
  msgstr ""
2498
 
2499
+ #: pro/includes/fields/class-date-time.php:117
2500
  msgid "Advanced date options."
2501
  msgstr ""
2502
 
2503
+ #: pro/includes/fields/class-date-time.php:136
2504
+ msgid "Date Picker"
2505
+ msgstr ""
2506
+
2507
+ #: pro/includes/fields/class-date-time.php:137
2508
+ msgid "Date Dropdown"
2509
+ msgstr ""
2510
+
2511
+ #: pro/includes/fields/class-date-time.php:139
2512
+ msgid "Type"
2513
  msgstr ""
2514
 
2515
+ #: pro/includes/fields/class-date-time.php:152
2516
  msgid "15 minutes"
2517
  msgstr ""
2518
 
2519
+ #: pro/includes/fields/class-date-time.php:153
2520
  msgid "30 minute"
2521
  msgstr ""
2522
 
2523
+ #: pro/includes/fields/class-date-time.php:154
2524
  msgid "1 hour"
2525
  msgstr ""
2526
 
2527
+ #: pro/includes/fields/class-date-time.php:157
2528
  msgid "Advanced time options"
2529
  msgstr ""
2530
 
2531
+ #: pro/includes/fields/class-date-time.php:176
2532
  msgid "Interval"
2533
  msgstr ""
2534
 
2535
+ #: pro/includes/fields/class-date-time.php:510
2536
+ msgid "YYYY"
2537
+ msgstr ""
2538
+
2539
  #: pro/includes/fields/class-divider.php:21
2540
  msgid "Section Divider"
2541
  msgstr ""
2544
  msgid "File Upload"
2545
  msgstr ""
2546
 
2547
+ #: pro/includes/fields/class-file-upload.php:141
2548
  msgid "Allowed File Extensions"
2549
  msgstr ""
2550
 
2551
+ #: pro/includes/fields/class-file-upload.php:142
2552
  msgid "Enter the extensions you would like to allow, comma separated."
2553
  msgstr ""
2554
 
2555
+ #: pro/includes/fields/class-file-upload.php:163
2556
  msgid "Max File Size"
2557
  msgstr ""
2558
 
2559
+ #: pro/includes/fields/class-file-upload.php:164
2560
  msgid ""
2561
  "Enter the max file size, in megabytyes, to allow. If left blank, the value "
2562
  "defaults to the maximum size the server allows which is "
2563
  msgstr ""
2564
 
2565
+ #: pro/includes/fields/class-file-upload.php:208
2566
  msgid "Store file in WordPress Media Library"
2567
  msgstr ""
2568
 
2569
+ #: pro/includes/fields/class-file-upload.php:209
2570
  msgid ""
2571
  "Check this option to store the final uploaded file in the WordPress Media "
2572
  "Library"
2573
  msgstr ""
2574
 
2575
+ #: pro/includes/fields/class-file-upload.php:341
2576
  msgid "The uploaded file exceeds the upload_max_filesize directive in php.ini."
2577
  msgstr ""
2578
 
2579
+ #: pro/includes/fields/class-file-upload.php:342
2580
  msgid ""
2581
  "The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in "
2582
  "the HTML form."
2583
  msgstr ""
2584
 
2585
+ #: pro/includes/fields/class-file-upload.php:343
2586
  msgid "The uploaded file was only partially uploaded."
2587
  msgstr ""
2588
 
2589
+ #: pro/includes/fields/class-file-upload.php:344
2590
  msgid "No file was uploaded."
2591
  msgstr ""
2592
 
2593
+ #: pro/includes/fields/class-file-upload.php:346
2594
  msgid "Missing a temporary folder."
2595
  msgstr ""
2596
 
2597
+ #: pro/includes/fields/class-file-upload.php:347
2598
  msgid "Failed to write file to disk."
2599
  msgstr ""
2600
 
2601
+ #: pro/includes/fields/class-file-upload.php:348
2602
  msgid "File upload stopped by extension."
2603
  msgstr ""
2604
 
2605
+ #: pro/includes/fields/class-file-upload.php:350
2606
  msgid "File upload error. "
2607
  msgstr ""
2608
 
2609
+ #: pro/includes/fields/class-file-upload.php:369
2610
  msgid "File exceeds max size allowed"
2611
  msgstr ""
2612
 
2613
+ #: pro/includes/fields/class-file-upload.php:387
2614
  msgid "File must have an extension."
2615
  msgstr ""
2616
 
2617
+ #: pro/includes/fields/class-file-upload.php:397
2618
+ #: pro/includes/fields/class-file-upload.php:416
2619
+ #: pro/includes/fields/class-file-upload.php:434
2620
  msgid "File type is not allowed."
2621
  msgstr ""
2622
 
2733
  msgstr ""
2734
 
2735
  #: pro/includes/fields/class-password.php:21
2736
+ #: pro/includes/fields/class-password.php:162
2737
+ #: pro/includes/fields/class-password.php:244
2738
  msgid "Password"
2739
  msgstr ""
2740
 
2741
+ #: pro/includes/fields/class-password.php:62
2742
+ msgid "Enable Password Confirmation"
2743
+ msgstr ""
2744
+
2745
+ #: pro/includes/fields/class-password.php:63
2746
+ msgid "Check this option ask the user to provide their password twice."
2747
+ msgstr ""
2748
+
2749
+ #: pro/includes/fields/class-password.php:167
2750
+ #: pro/includes/fields/class-password.php:270
2751
+ msgid "Confirm Password"
2752
+ msgstr ""
2753
+
2754
+ #: pro/includes/fields/class-password.php:261
2755
+ msgid "Password does not match."
2756
+ msgstr ""
2757
+
2758
+ #: pro/includes/fields/class-password.php:314
2759
+ msgid "Email does not match"
2760
+ msgstr ""
2761
+
2762
  #: pro/includes/fields/class-payment-credit-card.php:21
2763
  msgid "Credit Card"
2764
  msgstr ""
2801
  "only."
2802
  msgstr ""
2803
 
 
 
 
 
2804
  #: pro/includes/fields/class-payment-credit-card.php:284
2805
  msgid "YY"
2806
  msgstr ""
3106
  msgid "Please deactivate WPForms Lite before activating WPForms"
3107
  msgstr ""
3108
 
3109
+ #. #-#-#-#-# wpforms.pot (WPForms 1.3.0) #-#-#-#-#
3110
  #. Plugin URI of the plugin/theme
3111
+ #. #-#-#-#-# wpforms.pot (WPForms 1.3.0) #-#-#-#-#
3112
  #. Author URI of the plugin/theme
3113
  msgid "https://wpforms.com"
3114
  msgstr ""
lite/wpforms-lite.php CHANGED
@@ -91,7 +91,7 @@ class WPForms_Lite {
91
  __( 'Send To Email Address', 'wpforms' ),
92
  array(
93
  'default' => '{admin_email}',
94
- 'tooltip' => __( 'Enter the email address to receive form entry notifications. For multiple notifications, seperate email addresses with a comma.', 'wpforms' ),
95
  'smarttags' => array(
96
  'type' => 'fields',
97
  'fields' => 'name,email,text',
@@ -480,106 +480,88 @@ class WPForms_Lite {
480
  if ( !isset( $_GET['page'] ) || 'wpforms-addons' != $_GET['page'] ) {
481
  return;
482
  }
 
483
  $upgrade = $this->upgrade_link();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
484
  ?>
485
-
486
  <div id="wpforms-addons" class="wrap">
487
- <h1 class="page-title">
488
- Addons
489
- </h1>
490
  <div class="notice notice-info below-h2">
491
  <p><strong>Form Addons are a PRO feature.</strong></p>
492
  <p>Please upgrade to the PRO plan to unlock them and more awesome features.</p>
493
  <p><a href="<?php echo $upgrade; ?>" class="button button-primary">Upgrade Now</a></p>
494
  </div>
495
- <div class="wpforms-addon-item wpforms-addon-status-upgrade wpforms-first">
496
- <div class="wpforms-addon-image"><img src="https://wpforms.com/images/addon-icon-aweber.png"></div>
497
- <div class="wpforms-addon-text">
498
- <h4>AWeber Addon</h4>
499
- <p class="desc">WPForms AWeber addon allows you to create AWeber newsletter signup forms in WordPress, so you can grow your email list. </p>
500
- </div>
501
- <div class="wpforms-addon-action"><a href="<?php echo $upgrade; ?>" target="_blank">Upgrade Now</a></div>
502
- </div>
503
- <div class="wpforms-addon-item wpforms-addon-status-upgrade wpforms-second">
504
- <div class="wpforms-addon-image"><img src="https://wpforms.com/images/addon-icon-campaign-monitor.png"></div>
505
- <div class="wpforms-addon-text">
506
- <h4>Campaign Monitor Addon</h4>
507
- <p class="desc">WPForms Campaign Monitor addon allows you to create Campaign Monitor newsletter signup forms in WordPress, so you can grow your email list.</p>
508
- </div>
509
- <div class="wpforms-addon-action"><a href="<?php echo $upgrade; ?>" target="_blank">Upgrade Now</a></div>
510
- </div>
511
- <div class="wpforms-addon-item wpforms-addon-status-upgrade wpforms-first">
512
- <div class="wpforms-addon-image"><img src="https://wpforms.com/images/addon-icon-conditional-logic.png"></div>
513
- <div class="wpforms-addon-text">
514
- <h4>Conditional Logic Addon</h4>
515
- <p class="desc">WPForms' smart conditional logic addon allows you to show or hide fields, sections, and send specific notifications based on user selections, so you can collect the most relevant information.</p>
516
- </div>
517
- <div class="wpforms-addon-action"><a href="<?php echo $upgrade; ?>" target="_blank">Upgrade Now</a></div>
518
- </div>
519
- <div class="wpforms-addon-item wpforms-addon-status-upgrade wpforms-second">
520
- <div class="wpforms-addon-image"><img src="https://wpforms.com/images/addon-icon-getresponse.png"></div>
521
- <div class="wpforms-addon-text">
522
- <h4>GetResponse Addon</h4>
523
- <p class="desc">WPForms GetResponse addon allows you to create GetResponse newsletter signup forms in WordPress, so you can grow your email list.</p>
524
- </div>
525
- <div class="wpforms-addon-action"><a href="<?php echo $upgrade; ?>" target="_blank">Upgrade Now</a></div>
526
- </div>
527
- <div class="wpforms-addon-item wpforms-addon-status-upgrade wpforms-first">
528
- <div class="wpforms-addon-image"><img src="https://wpforms.com/images/addon-icon-mailchimp.png"></div>
529
- <div class="wpforms-addon-text">
530
- <h4>MailChimp Addon</h4>
531
- <p class="desc">WPForms MailChimp addon allows you to create MailChimp newsletter signup forms in WordPress, so you can grow your email list. </p>
532
- </div>
533
- <div class="wpforms-addon-action"><a href="<?php echo $upgrade; ?>" target="_blank">Upgrade Now</a></div>
534
- </div>
535
- <div class="wpforms-addon-item wpforms-addon-status-upgrade wpforms-second">
536
- <div class="wpforms-addon-image"><img src="https://wpforms.com/images/addon-icon-paypal.png"></div>
537
- <div class="wpforms-addon-text">
538
- <h4>PayPal Standard Addon</h4>
539
- <p class="desc">WPForms' PayPal addon allows you to connect your WordPress site with PayPal to easily collect payments, donations, and online orders.</p>
540
- </div>
541
- <div class="wpforms-addon-action"><a href="<?php echo $upgrade; ?>" target="_blank">Upgrade Now</a></div>
542
- </div>
543
- <div class="wpforms-addon-item wpforms-addon-status-upgrade wpforms-first">
544
- <div class="wpforms-addon-image"><img src="https://wpforms.com/images/addon-icon-stripe.png"></div>
545
- <div class="wpforms-addon-text">
546
- <h4>Stripe Addon</h4>
547
- <p class="desc">WPForms' Stripe addon allows you to connect your WordPress site with Stripe to easily collect payments, donations, and online orders.</p>
548
- </div>
549
- <div class="wpforms-addon-action"><a href="<?php echo $upgrade; ?>" target="_blank">Upgrade Now</a></div>
550
- </div>
551
- <div class="wpforms-addon-item wpforms-addon-status-upgrade wpforms-second">
552
- <div class="wpforms-addon-image"><img src="https://wpforms.com/images/addon-icon-user-registration.png"></div>
553
- <div class="wpforms-addon-text">
554
- <h4>User Registration Addon</h4>
555
- <p class="desc">WPForms user registration addon allows you to create custom WordPress user registration forms for your website.</p>
556
- </div>
557
- <div class="wpforms-addon-action"><a href="<?php echo $upgrade; ?>" target="_blank">Upgrade Now</a></div>
558
- </div>
559
- <div class="wpforms-addon-item wpforms-addon-status-upgrade wpforms-first">
560
- <div class="wpforms-addon-image"><img src="https://wpforms.com/images/addon-icon-captcha.png"></div>
561
- <div class="wpforms-addon-text">
562
- <h4>Custom Captcha Addon</h4>
563
- <p class="desc">WPForms custom captcha addon allows you to define custom questions or use random math questions as captcha to combat spam form submissions.</p>
564
- </div>
565
- <div class="wpforms-addon-action"><a href="<?php echo $upgrade; ?>" target="_blank">Upgrade Now</a></div>
566
- </div>
567
- <div class="wpforms-addon-item wpforms-addon-status-upgrade wpforms-second">
568
- <div class="wpforms-addon-image"><img src="https://wpforms.com/images/addon-icon-geolocation.png"></div>
569
- <div class="wpforms-addon-text">
570
- <h4>Geolocation Addon</h4>
571
- <p class="desc">WPForms geolocation addon allows you to collect and store your website visitors geolocation data along with their form submission.</p>
572
- </div>
573
- <div class="wpforms-addon-action"><a href="<?php echo $upgrade; ?>" target="_blank">Upgrade Now</a></div>
574
- </div>
575
- <div class="wpforms-addon-item wpforms-addon-status-upgrade wpforms-second">
576
- <div class="wpforms-addon-image"><img src="https://wpforms.com/images/addon-icon-zapier.png"></div>
577
  <div class="wpforms-addon-text">
578
- <h4>Zapier Addon</h4>
579
- <p class="desc">WPForms Zapier addon allows you to connect your forms with over 500+ web applications using Zapier.</p>
580
  </div>
581
  <div class="wpforms-addon-action"><a href="<?php echo $upgrade; ?>" target="_blank">Upgrade Now</a></div>
582
  </div>
 
583
  <div style="clear:both"></div>
584
  </div>
585
  <?php
91
  __( 'Send To Email Address', 'wpforms' ),
92
  array(
93
  'default' => '{admin_email}',
94
+ 'tooltip' => __( 'Enter the email address to receive form entry notifications. For multiple notifications, separate email addresses with a comma.', 'wpforms' ),
95
  'smarttags' => array(
96
  'type' => 'fields',
97
  'fields' => 'name,email,text',
480
  if ( !isset( $_GET['page'] ) || 'wpforms-addons' != $_GET['page'] ) {
481
  return;
482
  }
483
+
484
  $upgrade = $this->upgrade_link();
485
+ $addons = array(
486
+ array(
487
+ 'name' => 'Aweber',
488
+ 'desc' => 'WPForms AWeber addon allows you to create AWeber newsletter signup forms in WordPress, so you can grow your email list.',
489
+ 'icon' => 'addon-icon-aweber.png'
490
+ ),
491
+ array(
492
+ 'name' => 'Campaign Monitor',
493
+ 'desc' => 'WPForms Campaign Monitor addon allows you to create Campaign Monitor newsletter signup forms in WordPress, so you can grow your email list.',
494
+ 'icon' => 'addon-icon-campaign-monitor.png'
495
+ ),
496
+ array(
497
+ 'name' => 'Conditional Logic',
498
+ 'desc' => 'WPForms\' smart conditional logic addon allows you to show or hide fields, sections, and subscribe to newsletters based on user selections, so you can collect the most relevant information.',
499
+ 'icon' => 'addon-icon-conditional-logic.png'
500
+ ),
501
+ array(
502
+ 'name' => 'Custom Captcha',
503
+ 'desc' => 'WPForms custom captcha addon allows you to define custom questions or use random math questions as captcha to combat spam form submissions.',
504
+ 'icon' => 'addon-icon-captcha.png'
505
+ ),
506
+ array(
507
+ 'name' => 'Geolocation',
508
+ 'desc' => 'WPForms geolocation addon allows you to collect and store your website visitors geolocation data along with their form submission.',
509
+ 'icon' => 'addon-icon-geolocation.png'
510
+ ),
511
+ array(
512
+ 'name' => 'GetResponse',
513
+ 'desc' => 'WPForms GetResponse addon allows you to create GetResponse newsletter signup forms in WordPress, so you can grow your email list.',
514
+ 'icon' => 'addon-icon-getresponse.png'
515
+ ),
516
+ array(
517
+ 'name' => 'MailChimp',
518
+ 'desc' => 'WPForms MailChimp addon allows you to create MailChimp newsletter signup forms in WordPress, so you can grow your email list.',
519
+ 'icon' => 'addon-icon-mailchimp.png'
520
+ ),
521
+ array(
522
+ 'name' => 'PayPal Standard',
523
+ 'desc' => 'WPForms\' PayPal addon allows you to connect your WordPress site with PayPal to easily collect payments, donations, and online orders.',
524
+ 'icon' => 'addon-icon-paypal.png'
525
+ ),
526
+ array(
527
+ 'name' => 'Post Submissions',
528
+ 'desc' => 'WPForms Post Submissions addon makes it easy to have user-submitted content in WordPress. This front-end post submission form allow your users to submit blog posts without logging into the admin area.',
529
+ 'icon' => 'addon-icon-post-submissions.png'
530
+ ),
531
+ array(
532
+ 'name' => 'Stripe',
533
+ 'desc' => 'WPForms\' Stripe addon allows you to connect your WordPress site with Stripe to easily collect payments, donations, and online orders.',
534
+ 'icon' => 'addon-icon-stripe.png'
535
+ ),
536
+ array(
537
+ 'name' => 'User Registration',
538
+ 'desc' => 'WPForms\' Stripe addon allows you to connect your WordPress site with Stripe to easily collect payments, donations, and online orders.',
539
+ 'icon' => 'addon-icon-user-registration.png'
540
+ ),
541
+ array(
542
+ 'name' => 'Zapier',
543
+ 'desc' => 'WPForms\' Zapier addon allows you to connect your WordPress forms with over 500+ web apps. The integration possibilities here are just endless..',
544
+ 'icon' => 'addon-icon-zapier.png'
545
+ ),
546
+ )
547
  ?>
 
548
  <div id="wpforms-addons" class="wrap">
549
+ <h1 class="page-title">Addons</h1>
 
 
550
  <div class="notice notice-info below-h2">
551
  <p><strong>Form Addons are a PRO feature.</strong></p>
552
  <p>Please upgrade to the PRO plan to unlock them and more awesome features.</p>
553
  <p><a href="<?php echo $upgrade; ?>" class="button button-primary">Upgrade Now</a></p>
554
  </div>
555
+ <?php foreach( $addons as $addon ) : ?>
556
+ <div class="wpforms-addon-item wpforms-addon-status-upgrade">
557
+ <div class="wpforms-addon-image"><img src="https://wpforms.com/images/<?php echo $addon['icon']; ?>"></div>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
558
  <div class="wpforms-addon-text">
559
+ <h4><?php echo $addon['name']; ?> Addon</h4>
560
+ <p class="desc"><?php echo $addon['desc']; ?></p>
561
  </div>
562
  <div class="wpforms-addon-action"><a href="<?php echo $upgrade; ?>" target="_blank">Upgrade Now</a></div>
563
  </div>
564
+ <?php endforeach; ?>
565
  <div style="clear:both"></div>
566
  </div>
567
  <?php
readme.txt CHANGED
@@ -163,6 +163,20 @@ Syed Balkhi
163
 
164
  == Changelog ==
165
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
166
  = 1.2.9 =
167
  - Added: Individual fields can be duplicated in the form builder
168
  - Changed: How data is stored for fields using Dynanic Choices
163
 
164
  == Changelog ==
165
 
166
+ = 1.3.0 =
167
+ ## [1.3.0] - 2016-10-07
168
+ ### Added
169
+ - Added: Email field confirmantion
170
+ - Added: Support for Visual Composer
171
+ - Added: Field class to force elements to full-width on mobile devices, `wpforms-mobile-full`
172
+ - Changed: Placeholders are added/updated in real-time for Dropdown fields in the form builder
173
+ - Changed: Add empty value to select element placeholders when displaying form for better markup validation
174
+ - Fixed: Multiple instances of reCAPTCHA on a page not correctly loading
175
+ - Fixed: Field choice defaults not restoring in form builder
176
+ - Fixed: Field alignment issues in the form builder when dragging field more than once
177
+ - Fixed: PHP fatal erroring if form notification email address provided is not valid upon sending
178
+ - Fixed: Compatibility issuses when network activated on a Multisite install
179
+
180
  = 1.2.9 =
181
  - Added: Individual fields can be duplicated in the form builder
182
  - Changed: How data is stored for fields using Dynanic Choices
wpforms.php CHANGED
@@ -5,7 +5,7 @@
5
  * Description: Beginner friendly WordPress contact form plugin. Use our Drag & Drop form builder to create your WordPress forms.
6
  * Author: WPForms
7
  * Author URI: https://wpforms.com
8
- * Version: 1.2.9
9
  * Text Domain: wpforms
10
  * Domain Path: languages
11
  *
@@ -81,7 +81,7 @@ final class WPForms {
81
  * @since 1.0.0
82
  * @var sting
83
  */
84
- public $version = '1.2.9';
85
 
86
  /**
87
  * The form data handler instance.
@@ -205,6 +205,7 @@ final class WPForms {
205
  require_once WPFORMS_PLUGIN_DIR . 'includes/class-widget.php';
206
  require_once WPFORMS_PLUGIN_DIR . 'includes/class-preview.php';
207
  require_once WPFORMS_PLUGIN_DIR . 'includes/emails/class-emails.php';
 
208
 
209
  // Admin/Dashboard only includes
210
  if ( is_admin() ) {
5
  * Description: Beginner friendly WordPress contact form plugin. Use our Drag & Drop form builder to create your WordPress forms.
6
  * Author: WPForms
7
  * Author URI: https://wpforms.com
8
+ * Version: 1.3.0
9
  * Text Domain: wpforms
10
  * Domain Path: languages
11
  *
81
  * @since 1.0.0
82
  * @var sting
83
  */
84
+ public $version = '1.3.0';
85
 
86
  /**
87
  * The form data handler instance.
205
  require_once WPFORMS_PLUGIN_DIR . 'includes/class-widget.php';
206
  require_once WPFORMS_PLUGIN_DIR . 'includes/class-preview.php';
207
  require_once WPFORMS_PLUGIN_DIR . 'includes/emails/class-emails.php';
208
+ require_once WPFORMS_PLUGIN_DIR . 'includes/integrations.php';
209
 
210
  // Admin/Dashboard only includes
211
  if ( is_admin() ) {