Strong Testimonials - Version 2.51.0

Version Description

Download this release

Release Info

Developer giucu91
Plugin Icon 128x128 Strong Testimonials
Version 2.51.0
Comparing to
See all releases

Code changes from version 2.50.4 to 2.51.0

Files changed (42) hide show
  1. admin/about/class-strong-testimonials-welcome.php +24 -53
  2. admin/class-strong-testimonials-addons.php +1 -1
  3. admin/class-strong-testimonials-defaults.php +12 -2
  4. admin/class-strong-testimonials-post-editor.php +2 -1
  5. admin/class-strong-testimonials-review.php +1 -1
  6. admin/class-strong-testimonials-upsell.php +20 -20
  7. admin/custom-fields.php +3 -5
  8. admin/js/admin-compat.js +6 -6
  9. admin/js/admin-fields.js +21 -21
  10. admin/js/admin-form.js +9 -9
  11. admin/js/admin-order.js +1 -1
  12. admin/js/custom-spinner.js +2 -2
  13. admin/js/help.js +2 -2
  14. admin/js/lib/autosize/autosize.min.js +2 -2
  15. admin/js/rating-edit.js +2 -2
  16. admin/js/selectize.js +3852 -3806
  17. admin/js/view-category-filter.js +1 -1
  18. admin/js/views.js +30 -26
  19. admin/partials/views/option-pagination.php +6 -6
  20. admin/views.php +4 -3
  21. assets/css/admin-global.css +4 -0
  22. assets/css/admin-welcome.css +1 -3
  23. assets/css/admin.css +26 -0
  24. assets/js/admin-js.js +5 -5
  25. assets/js/blocks-js.js +11 -12
  26. assets/src/js/admin.js +9 -9
  27. assets/src/js/components/edit.js +1 -1
  28. assets/src/js/components/inspector.js +1 -1
  29. changelog.txt +10 -0
  30. includes/class-strong-view-display.php +13 -2
  31. includes/functions-content.php +21 -23
  32. public/js/controller.js +1 -1
  33. public/js/lib/actual/jquery-actual.js +2 -2
  34. public/js/lib/actual/jquery-actual.min.js +14 -1
  35. public/js/lib/actual/jquery.actual.min.js +0 -14
  36. public/js/lib/form-validation/form-validation.js +3 -3
  37. public/js/lib/strongpager/jquery-strongpager.js +1 -1
  38. public/js/lib/strongslider/jquery-strongslider.js +11 -3
  39. public/js/lib/validate/jquery-validate.js +162 -79
  40. public/js/lib/validate/jquery-validate.min.js +4 -1
  41. readme.txt +2 -2
  42. strong-testimonials.php +2 -2
admin/about/class-strong-testimonials-welcome.php CHANGED
@@ -78,8 +78,8 @@ class Strong_Testimonials_Welcome {
78
  </a>
79
  </div>
80
  <div class="right">
81
- <a href="https://strongtestimonials.com/docs"
82
- class="wpmtst-btn wpmtst-btn-block wpmtst-btn-lg wpmtst-btn-orange" target="_blank">
83
  <?php esc_html_e( 'Read the Docs', 'strong-testimonials' ); ?>
84
  </a>
85
  </div>
@@ -101,85 +101,85 @@ class Strong_Testimonials_Welcome {
101
  <div class="feature-block first">
102
  <img src="<?php echo esc_attr( WPMTST_ADMIN_URL ); ?>/img/features/1.svg">
103
  <h5><?php esc_html_e( 'Pro Templates', 'strong-testimonials' ); ?><div class="pro-label">PRO</div></h5>
104
- <p><?php esc_html_e( 'Create beautiful testimonial designs with a number of predesigned and easy-to-use premium templates.', 'strong-testimonials' ); ?><br/><a target="_blank" href="https://strongtestimonials.com/extensions/pro-templates"><?php esc_html_e( 'Learn More', 'strong-testimonials' ); ?></a></p>
105
  </div>
106
 
107
  <div class="feature-block last">
108
  <img src="<?php echo esc_attr( WPMTST_ADMIN_URL ); ?>/img/features/infinitescroll.svg">
109
  <h5><?php esc_html_e( 'Infinite Scroll', 'strong-testimonials' ); ?><div class="pro-label">PRO</div></h5>
110
- <p><?php esc_html_e( 'Change properties of the testimonial post type: labels, permalink structure, admin options and post editor features.', 'strong-testimonials' ); ?><br/><a target="_blank" href="https://strongtestimonials.com/extensions/infinite-scroll/"><?php esc_html_e( 'Learn More', 'strong-testimonials' ); ?></a></p>
111
  </div>
112
 
113
  <div class="feature-block first">
114
  <img src="<?php echo esc_attr( WPMTST_ADMIN_URL ); ?>/img/features/12.svg">
115
  <h5><?php esc_html_e( 'Testimonial Assignment', 'strong-testimonials' ); ?><div class="pro-label">PRO</div></h5>
116
- <p><?php esc_html_e( 'Assign testimonials to custom post types for easy management and filtering.', 'strong-testimonials' ); ?><br/><a target="_blank" href="https://strongtestimonials.com/extensions/assignment"><?php esc_html_e( 'Learn More', 'strong-testimonials' ); ?></a></p>
117
  </div>
118
 
119
  <div class="feature-block last">
120
  <img src="<?php echo esc_attr( WPMTST_ADMIN_URL ); ?>/img/features/11.svg">
121
  <h5><?php esc_html_e( 'Custom Properties', 'strong-testimonials' ); ?><div class="pro-label">PRO</div></h5>
122
- <p><?php esc_html_e( 'Change properties of the testimonial post type: labels, permalink structure, admin options and post editor features.', 'strong-testimonials' ); ?><br/><a target="_blank" href="https://strongtestimonials.com/extensions/properties"><?php esc_html_e( 'Learn More', 'strong-testimonials' ); ?></a></p>
123
  </div>
124
 
125
  <div class="feature-block first">
126
  <img src="<?php echo esc_attr( WPMTST_ADMIN_URL ); ?>/img/features/6.svg">
127
  <h5><?php esc_html_e( 'Advanced View Settings', 'strong-testimonials' ); ?><div class="pro-label">PRO</div></h5>
128
- <p><?php esc_html_e( 'Customize your testimonials beyond star ratings, reorder fields and more.', 'strong-testimonials' ); ?><br/><a target="_blank" href="https://strongtestimonials.com/extensions/advanced-views"><?php esc_html_e( 'Learn More', 'strong-testimonials' ); ?></a></p>
129
  </div>
130
 
131
  <div class="feature-block last">
132
  <img src="<?php echo esc_attr( WPMTST_ADMIN_URL ); ?>/img/features/9.svg">
133
  <h5><?php esc_html_e( 'Multiple Submission Forms', 'strong-testimonials' ); ?><div class="pro-label">PRO</div></h5>
134
- <p><?php esc_html_e( 'Easily collect testimonials from customers by creating and customizing multiple forms at once.', 'strong-testimonials' ); ?><br/><a target="_blank" href="https://strongtestimonials.com/extensions/multiple-forms"><?php esc_html_e( 'Learn More', 'strong-testimonials' ); ?></a></p>
135
  </div>
136
 
137
  <div class="feature-block first">
138
  <img src="<?php echo esc_attr( WPMTST_ADMIN_URL ); ?>/img/features/10.svg">
139
  <h5><?php esc_html_e( 'Custom Form Fields', 'strong-testimonials' ); ?><div class="pro-label">PRO</div></h5>
140
- <p><?php esc_html_e( 'Enhance your submission forms to both collect and display additional information.', 'strong-testimonials' ); ?><br/><a target="_blank" href="https://strongtestimonials.com/extensions/custom-fields"><?php esc_html_e( 'Learn More', 'strong-testimonials' ); ?></a></p>
141
  </div>
142
 
143
  <div class="feature-block last">
144
  <img src="<?php echo esc_attr( WPMTST_ADMIN_URL ); ?>/img/features/14.svg">
145
  <h5><?php esc_html_e( 'SEO-friendly Testimonials', 'strong-testimonials' ); ?><div class="pro-label">PRO</div></h5>
146
- <p><?php esc_html_e( 'Take full advantage of your testimonials with our Schema.org Markup extension.', 'strong-testimonials' ); ?><br/><a target="_blank" href="https://strongtestimonials.com/extensions/review-markup"><?php esc_html_e( 'Learn More', 'strong-testimonials' ); ?></a></p>
147
  </div>
148
 
149
  <div class="feature-block first">
150
  <img src="<?php echo esc_attr( WPMTST_ADMIN_URL ); ?>/img/features/13.svg">
151
  <h5><?php esc_html_e( 'Spam Control', 'strong-testimonials' ); ?><div class="pro-label">PRO</div></h5>
152
- <p><?php esc_html_e( 'Protect your testimonial submission forms from spam and other types of automated abuse.', 'strong-testimonials' ); ?><br/><a target="_blank" href="https://strongtestimonials.com/extensions/captcha"><?php esc_html_e( 'Learn More', 'strong-testimonials' ); ?></a></p>
153
  </div>
154
 
155
  <div class="feature-block last">
156
  <img src="<?php echo esc_attr( WPMTST_ADMIN_URL ); ?>/img/features/15.svg">
157
  <h5><?php esc_html_e( 'Testimonial Importer', 'strong-testimonials' ); ?><div class="pro-label">PRO</div></h5>
158
- <p><?php esc_html_e( 'Import reviews from 3rd party sites like: Facebook, Google, Yelp, Zomato & WooCommerce', 'strong-testimonials' ); ?><br/><a target="_blank" href="https://strongtestimonials.com/extensions/importer"><?php esc_html_e( 'Learn More', 'strong-testimonials' ); ?></a></p>
159
  </div>
160
 
161
  <div class="feature-block first">
162
  <img src="<?php echo esc_attr( WPMTST_ADMIN_URL ); ?>/img/features/email.svg">
163
  <h5><?php esc_html_e( 'Enhanced Emails', 'strong-testimonials' ); ?><div class="pro-label">PRO</div></h5>
164
- <p><?php esc_html_e( 'We added the option to send an email to the customer upon new testimonial submission. Also, to send an email to the customer when the testimonial is approved.', 'strong-testimonials' ); ?><br/><a target="_blank" href="https://strongtestimonials.com/extensions/enhanced-emails/"><?php esc_html_e( 'Learn More', 'strong-testimonials' ); ?></a></p>
165
  </div>
166
 
167
  <div class="feature-block last">
168
  <img src="<?php echo esc_attr( WPMTST_ADMIN_URL ); ?>/img/features/filter.svg">
169
  <h5><?php esc_html_e( 'Filters', 'strong-testimonials' ); ?><div class="pro-label">PRO</div></h5>
170
- <p><?php esc_html_e( 'Now you can use categories to group your testimonials and have your clients read reviews grouped by service/product type.', 'strong-testimonials' ); ?><br/><a target="_blank" href="https://strongtestimonials.com/extensions/filters/"><?php esc_html_e( 'Learn More', 'strong-testimonials' ); ?></a></p>
171
  </div>
172
 
173
  <div class="feature-block first">
174
  <img src="<?php echo esc_attr( WPMTST_ADMIN_URL ); ?>/img/features/rolemanagement.svg">
175
  <h5><?php esc_html_e( 'Role Management', 'strong-testimonials' ); ?><div class="pro-label">PRO</div></h5>
176
- <p><?php esc_html_e( 'We’re giving power back to the users and admins can decide which user roles are worthy of adding, editing, or removing testimonials.', 'strong-testimonials' ); ?><br/><a target="_blank" href="https://strongtestimonials.com/extensions/role-management/"><?php esc_html_e( 'Learn More', 'strong-testimonials' ); ?></a></p>
177
  </div>
178
 
179
  <div class="feature-block last">
180
  <img src="<?php echo esc_attr( WPMTST_ADMIN_URL ); ?>/img/features/mailchimp.svg">
181
  <h5><?php esc_html_e( 'Mailchimp integration', 'strong-testimonials' ); ?><div class="pro-label">PRO</div></h5>
182
- <p><?php esc_html_e( 'Now you can subscribe your customers to a Mailchimp list.', 'strong-testimonials' ); ?><br/><a target="_blank" href="https://strongtestimonials.com/extensions/importer"><?php esc_html_e( 'Learn More', 'strong-testimonials' ); ?></a></p>
183
  </div>
184
 
185
  </div><!-- feature-list -->
@@ -188,51 +188,22 @@ class Strong_Testimonials_Welcome {
188
 
189
  </div><!-- features -->
190
 
 
191
  <div class="upgrade">
192
-
193
- <div class="block clear">
194
-
195
- <h1><?php esc_html_e( 'Upgrade to PRO', 'strong-testimonials' ); ?></h1>
196
-
197
- <div class="left">
198
- <ul>
199
- <li><span class="dashicons dashicons-yes"></span> <?php esc_html_e( '1 Year of Free Updates', 'strong-testimonials' ); ?></li>
200
- <li><span class="dashicons dashicons-yes"></span> <?php esc_html_e( 'Pro Templates', 'strong-testimonials' ); ?></li>
201
- <li><span class="dashicons dashicons-yes"></span> <?php esc_html_e( 'Testimonial Assignment', 'strong-testimonials' ); ?></li>
202
- <li><span class="dashicons dashicons-yes"></span> <?php esc_html_e( 'Testimonial Importer', 'strong-testimonials' ); ?></li>
203
- <li><span class="dashicons dashicons-yes"></span> <?php esc_html_e( 'SEO-friendly Testimonials', 'strong-testimonials' ); ?></li>
204
- <li><span class="dashicons dashicons-yes"></span> <?php esc_html_e( 'Country Selector', 'strong-testimonials' ); ?></li>
205
- <li><span class="dashicons dashicons-yes"></span> <?php esc_html_e( 'Infinite Scroll', 'strong-testimonials' ); ?></li>
206
- <li><span class="dashicons dashicons-yes"></span> <?php esc_html_e( 'Filters', 'strong-testimonials' ); ?></li>
207
- </ul>
208
- </div>
209
-
210
- <div class="right">
211
- <ul>
212
- <li><span class="dashicons dashicons-yes"></span> <?php esc_html_e( '1 Year of Support', 'strong-testimonials' ); ?></li>
213
- <li><span class="dashicons dashicons-yes"></span> <?php esc_html_e( 'Spam Control', 'strong-testimonials' ); ?></li>
214
- <li><span class="dashicons dashicons-yes"></span> <?php esc_html_e( 'Advanced View Settings', 'strong-testimonials' ); ?></li>
215
- <li><span class="dashicons dashicons-yes"></span> <?php esc_html_e( 'Multiple Submission Forms', 'strong-testimonials' ); ?></li>
216
- <li><span class="dashicons dashicons-yes"></span> <?php esc_html_e( 'Custom Form Fields', 'strong-testimonials' ); ?></li>
217
- <li><span class="dashicons dashicons-yes"></span> <?php esc_html_e( 'Custom properties', 'strong-testimonials' ); ?></li>
218
- <li><span class="dashicons dashicons-yes"></span> <?php esc_html_e( 'Enhanced Emails', 'strong-testimonials' ); ?></li>
219
- <li><span class="dashicons dashicons-yes"></span> <?php esc_html_e( 'Role Management', 'strong-testimonials' ); ?></li>
220
- </ul>
221
- </div>
222
-
223
- <a href="https://strongtestimonials.com/pricing/" target="_blank"
224
- class="wpmtst-btn wpmtst-btn-lg wpmtst-btn-white">
225
  <?php esc_html_e( 'Upgrade Now', 'strong-testimonials' ); ?>
226
  </a>
227
 
228
  </div>
 
229
 
230
- </div><!-- upgrade -->
231
 
232
  <div class="testimonials">
233
 
234
  <div class="block clear">
235
-
236
  <div class="testimonial-block left">
237
  <img src="<?php echo esc_attr( WPMTST_ADMIN_URL ); ?>/img/testimonial-image-1.jpg">
238
  <p><?php esc_html_e( 'Strong Testimonials is my new, go-to resource for creating pages with multiple staff bios or testimonials. It’s extremely easy to use, update, and customize, and that makes it an invaluable asset. Highly recommend!', 'strong-testimonials' ); ?>
@@ -258,14 +229,14 @@ class Strong_Testimonials_Welcome {
258
  <div class="button-wrap clear">
259
  <div class="left">
260
  <a href="<?php echo esc_url( admin_url( 'edit.php?post_type=wpm-testimonial' ) ); ?>"
261
- class="wpmtst-btn wpmtst-btn-block wpmtst-btn-lg wpmtst-btn-orange">
262
  <?php esc_html_e( 'Start Adding Testimonials', 'strong-testimonials' ); ?>
263
  </a>
264
  </div>
265
  <div class="right">
266
  <a href="https://strongtestimonials.com/pricing/" target="_blank"
267
  class="wpmtst-btn wpmtst-btn-block wpmtst-btn-lg wpmtst-btn-purple">
268
- <?php esc_html_e( 'Upgrade to Pro', 'strong-testimonials' ); ?>
269
  </a>
270
  </div>
271
  </div>
78
  </a>
79
  </div>
80
  <div class="right">
81
+ <a href="https://strongtestimonials.com/docs?utm_source=welcome_banner&utm_medium=backend&utm_campaign=welcome_banner"
82
+ class="wpmtst-btn wpmtst-btn-block wpmtst-btn-lg" target="_blank">
83
  <?php esc_html_e( 'Read the Docs', 'strong-testimonials' ); ?>
84
  </a>
85
  </div>
101
  <div class="feature-block first">
102
  <img src="<?php echo esc_attr( WPMTST_ADMIN_URL ); ?>/img/features/1.svg">
103
  <h5><?php esc_html_e( 'Pro Templates', 'strong-testimonials' ); ?><div class="pro-label">PRO</div></h5>
104
+ <p><?php esc_html_e( 'Create beautiful testimonial designs with a number of predesigned and easy-to-use premium templates.', 'strong-testimonials' ); ?><br/><a target="_blank" href="https://strongtestimonials.com/extensions/pro-templates?utm_source=welcome_banner&utm_medium=backend&utm_campaign=welcome_banner"><?php esc_html_e( 'Learn More', 'strong-testimonials' ); ?></a></p>
105
  </div>
106
 
107
  <div class="feature-block last">
108
  <img src="<?php echo esc_attr( WPMTST_ADMIN_URL ); ?>/img/features/infinitescroll.svg">
109
  <h5><?php esc_html_e( 'Infinite Scroll', 'strong-testimonials' ); ?><div class="pro-label">PRO</div></h5>
110
+ <p><?php esc_html_e( 'Change properties of the testimonial post type: labels, permalink structure, admin options and post editor features.', 'strong-testimonials' ); ?><br/><a target="_blank" href="https://strongtestimonials.com/extensions/infinite-scroll/?utm_source=welcome_banner&utm_medium=backend&utm_campaign=welcome_banner"><?php esc_html_e( 'Learn More', 'strong-testimonials' ); ?></a></p>
111
  </div>
112
 
113
  <div class="feature-block first">
114
  <img src="<?php echo esc_attr( WPMTST_ADMIN_URL ); ?>/img/features/12.svg">
115
  <h5><?php esc_html_e( 'Testimonial Assignment', 'strong-testimonials' ); ?><div class="pro-label">PRO</div></h5>
116
+ <p><?php esc_html_e( 'Assign testimonials to custom post types for easy management and filtering.', 'strong-testimonials' ); ?><br/><a target="_blank" href="https://strongtestimonials.com/extensions/assignment?utm_source=welcome_banner&utm_medium=backend&utm_campaign=welcome_banner"><?php esc_html_e( 'Learn More', 'strong-testimonials' ); ?></a></p>
117
  </div>
118
 
119
  <div class="feature-block last">
120
  <img src="<?php echo esc_attr( WPMTST_ADMIN_URL ); ?>/img/features/11.svg">
121
  <h5><?php esc_html_e( 'Custom Properties', 'strong-testimonials' ); ?><div class="pro-label">PRO</div></h5>
122
+ <p><?php esc_html_e( 'Change properties of the testimonial post type: labels, permalink structure, admin options and post editor features.', 'strong-testimonials' ); ?><br/><a target="_blank" href="https://strongtestimonials.com/extensions/properties?utm_source=welcome_banner&utm_medium=backend&utm_campaign=welcome_banner"><?php esc_html_e( 'Learn More', 'strong-testimonials' ); ?></a></p>
123
  </div>
124
 
125
  <div class="feature-block first">
126
  <img src="<?php echo esc_attr( WPMTST_ADMIN_URL ); ?>/img/features/6.svg">
127
  <h5><?php esc_html_e( 'Advanced View Settings', 'strong-testimonials' ); ?><div class="pro-label">PRO</div></h5>
128
+ <p><?php esc_html_e( 'Customize your testimonials beyond star ratings, reorder fields and more.', 'strong-testimonials' ); ?><br/><a target="_blank" href="https://strongtestimonials.com/extensions/advanced-views?utm_source=welcome_banner&utm_medium=backend&utm_campaign=welcome_banner"><?php esc_html_e( 'Learn More', 'strong-testimonials' ); ?></a></p>
129
  </div>
130
 
131
  <div class="feature-block last">
132
  <img src="<?php echo esc_attr( WPMTST_ADMIN_URL ); ?>/img/features/9.svg">
133
  <h5><?php esc_html_e( 'Multiple Submission Forms', 'strong-testimonials' ); ?><div class="pro-label">PRO</div></h5>
134
+ <p><?php esc_html_e( 'Easily collect testimonials from customers by creating and customizing multiple forms at once.', 'strong-testimonials' ); ?><br/><a target="_blank" href="https://strongtestimonials.com/extensions/multiple-forms?utm_source=welcome_banner&utm_medium=backend&utm_campaign=welcome_banner"><?php esc_html_e( 'Learn More', 'strong-testimonials' ); ?></a></p>
135
  </div>
136
 
137
  <div class="feature-block first">
138
  <img src="<?php echo esc_attr( WPMTST_ADMIN_URL ); ?>/img/features/10.svg">
139
  <h5><?php esc_html_e( 'Custom Form Fields', 'strong-testimonials' ); ?><div class="pro-label">PRO</div></h5>
140
+ <p><?php esc_html_e( 'Enhance your submission forms to both collect and display additional information.', 'strong-testimonials' ); ?><br/><a target="_blank" href="https://strongtestimonials.com/extensions/custom-fields?utm_source=welcome_banner&utm_medium=backend&utm_campaign=welcome_banner"><?php esc_html_e( 'Learn More', 'strong-testimonials' ); ?></a></p>
141
  </div>
142
 
143
  <div class="feature-block last">
144
  <img src="<?php echo esc_attr( WPMTST_ADMIN_URL ); ?>/img/features/14.svg">
145
  <h5><?php esc_html_e( 'SEO-friendly Testimonials', 'strong-testimonials' ); ?><div class="pro-label">PRO</div></h5>
146
+ <p><?php esc_html_e( 'Take full advantage of your testimonials with our Schema.org Markup extension.', 'strong-testimonials' ); ?><br/><a target="_blank" href="https://strongtestimonials.com/extensions/review-markup?utm_source=welcome_banner&utm_medium=backend&utm_campaign=welcome_banner"><?php esc_html_e( 'Learn More', 'strong-testimonials' ); ?></a></p>
147
  </div>
148
 
149
  <div class="feature-block first">
150
  <img src="<?php echo esc_attr( WPMTST_ADMIN_URL ); ?>/img/features/13.svg">
151
  <h5><?php esc_html_e( 'Spam Control', 'strong-testimonials' ); ?><div class="pro-label">PRO</div></h5>
152
+ <p><?php esc_html_e( 'Protect your testimonial submission forms from spam and other types of automated abuse.', 'strong-testimonials' ); ?><br/><a target="_blank" href="https://strongtestimonials.com/extensions/captcha?utm_source=welcome_banner&utm_medium=backend&utm_campaign=welcome_banner"><?php esc_html_e( 'Learn More', 'strong-testimonials' ); ?></a></p>
153
  </div>
154
 
155
  <div class="feature-block last">
156
  <img src="<?php echo esc_attr( WPMTST_ADMIN_URL ); ?>/img/features/15.svg">
157
  <h5><?php esc_html_e( 'Testimonial Importer', 'strong-testimonials' ); ?><div class="pro-label">PRO</div></h5>
158
+ <p><?php esc_html_e( 'Import reviews from 3rd party sites like: Facebook, Google, Yelp, Zomato & WooCommerce', 'strong-testimonials' ); ?><br/><a target="_blank" href="https://strongtestimonials.com/extensions/importer?utm_source=welcome_banner&utm_medium=backend&utm_campaign=welcome_banner"><?php esc_html_e( 'Learn More', 'strong-testimonials' ); ?></a></p>
159
  </div>
160
 
161
  <div class="feature-block first">
162
  <img src="<?php echo esc_attr( WPMTST_ADMIN_URL ); ?>/img/features/email.svg">
163
  <h5><?php esc_html_e( 'Enhanced Emails', 'strong-testimonials' ); ?><div class="pro-label">PRO</div></h5>
164
+ <p><?php esc_html_e( 'We added the option to send an email to the customer upon new testimonial submission. Also, to send an email to the customer when the testimonial is approved.', 'strong-testimonials' ); ?><br/><a target="_blank" href="https://strongtestimonials.com/extensions/enhanced-emails/?utm_source=welcome_banner&utm_medium=backend&utm_campaign=welcome_banner"><?php esc_html_e( 'Learn More', 'strong-testimonials' ); ?></a></p>
165
  </div>
166
 
167
  <div class="feature-block last">
168
  <img src="<?php echo esc_attr( WPMTST_ADMIN_URL ); ?>/img/features/filter.svg">
169
  <h5><?php esc_html_e( 'Filters', 'strong-testimonials' ); ?><div class="pro-label">PRO</div></h5>
170
+ <p><?php esc_html_e( 'Now you can use categories to group your testimonials and have your clients read reviews grouped by service/product type.', 'strong-testimonials' ); ?><br/><a target="_blank" href="https://strongtestimonials.com/extensions/filters/?utm_source=welcome_banner&utm_medium=backend&utm_campaign=welcome_banner"><?php esc_html_e( 'Learn More', 'strong-testimonials' ); ?></a></p>
171
  </div>
172
 
173
  <div class="feature-block first">
174
  <img src="<?php echo esc_attr( WPMTST_ADMIN_URL ); ?>/img/features/rolemanagement.svg">
175
  <h5><?php esc_html_e( 'Role Management', 'strong-testimonials' ); ?><div class="pro-label">PRO</div></h5>
176
+ <p><?php esc_html_e( 'We’re giving power back to the users and admins can decide which user roles are worthy of adding, editing, or removing testimonials.', 'strong-testimonials' ); ?><br/><a target="_blank" href="https://strongtestimonials.com/extensions/role-management/?utm_source=welcome_banner&utm_medium=backend&utm_campaign=welcome_banner"><?php esc_html_e( 'Learn More', 'strong-testimonials' ); ?></a></p>
177
  </div>
178
 
179
  <div class="feature-block last">
180
  <img src="<?php echo esc_attr( WPMTST_ADMIN_URL ); ?>/img/features/mailchimp.svg">
181
  <h5><?php esc_html_e( 'Mailchimp integration', 'strong-testimonials' ); ?><div class="pro-label">PRO</div></h5>
182
+ <p><?php esc_html_e( 'Now you can subscribe your customers to a Mailchimp list.', 'strong-testimonials' ); ?><br/><a target="_blank" href="https://strongtestimonials.com/extensions/importer?utm_source=welcome_banner&utm_medium=backend&utm_campaign=welcome_banner"><?php esc_html_e( 'Learn More', 'strong-testimonials' ); ?></a></p>
183
  </div>
184
 
185
  </div><!-- feature-list -->
188
 
189
  </div><!-- features -->
190
 
191
+
192
  <div class="upgrade">
193
+ <div class="block">
194
+ <a href="https://strongtestimonials.com/pricing/?utm_source=welcome_banner&utm_medium=backend&utm_campaign=welcome_banner" target="_blank"
195
+ class="wpmtst-btn wpmtst-btn-lg wpmtst-btn-orange">
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
196
  <?php esc_html_e( 'Upgrade Now', 'strong-testimonials' ); ?>
197
  </a>
198
 
199
  </div>
200
+ </div><!--/.upgrade-->
201
 
 
202
 
203
  <div class="testimonials">
204
 
205
  <div class="block clear">
206
+ <h1>Happy users of the Strong Testimonials - premium version</h1>
207
  <div class="testimonial-block left">
208
  <img src="<?php echo esc_attr( WPMTST_ADMIN_URL ); ?>/img/testimonial-image-1.jpg">
209
  <p><?php esc_html_e( 'Strong Testimonials is my new, go-to resource for creating pages with multiple staff bios or testimonials. It’s extremely easy to use, update, and customize, and that makes it an invaluable asset. Highly recommend!', 'strong-testimonials' ); ?>
229
  <div class="button-wrap clear">
230
  <div class="left">
231
  <a href="<?php echo esc_url( admin_url( 'edit.php?post_type=wpm-testimonial' ) ); ?>"
232
+ class="wpmtst-btn wpmtst-btn-block wpmtst-btn-lg wpmtst-btn-purple">
233
  <?php esc_html_e( 'Start Adding Testimonials', 'strong-testimonials' ); ?>
234
  </a>
235
  </div>
236
  <div class="right">
237
  <a href="https://strongtestimonials.com/pricing/" target="_blank"
238
  class="wpmtst-btn wpmtst-btn-block wpmtst-btn-lg wpmtst-btn-purple">
239
+ <?php esc_html_e( 'Upgrade now', 'strong-testimonials' ); ?>
240
  </a>
241
  </div>
242
  </div>
admin/class-strong-testimonials-addons.php CHANGED
@@ -60,7 +60,7 @@ class Strong_Testimonials_Addons {
60
  echo '</div>';
61
  echo '</div>';
62
  echo '<div class="wpmtst-addon-actions">';
63
- echo apply_filters( 'wpmtst_addon_button_action', '<a href="' . esc_url( WPMTST_STORE_UPGRADE_URL . '?utm_source=st-lite&utm_campaign=upsell&utm_medium=' . esc_attr( $addon['slug'] ) ) . '" target="_blank" class="button primary-button">' . esc_html__( 'Upgrade to PRO', 'strong-testimonials' ) . '</a>', $addon );
64
  echo '</div>';
65
  echo '</div>';
66
  }
60
  echo '</div>';
61
  echo '</div>';
62
  echo '<div class="wpmtst-addon-actions">';
63
+ echo apply_filters( 'wpmtst_addon_button_action', '<a href="' . esc_url( WPMTST_STORE_UPGRADE_URL . '?utm_source=st-lite&utm_campaign=upsell&utm_medium=' . esc_attr( $addon['slug'] ) ) . '" target="_blank" class="button primary-button">' . esc_html__( 'Upgrade now', 'strong-testimonials' ) . '</a>', $addon );
64
  echo '</div>';
65
  echo '</div>';
66
  }
admin/class-strong-testimonials-defaults.php CHANGED
@@ -310,6 +310,14 @@ class Strong_Testimonials_Defaults {
310
  'after' => __( 'Would you like to include a photo?', 'strong-testimonials' ),
311
  'admin_table' => 1,
312
  ),
 
 
 
 
 
 
 
 
313
  ),
314
  ),
315
  );
@@ -357,9 +365,11 @@ class Strong_Testimonials_Defaults {
357
  foreach ( $form['fields'] as $key => $array ) {
358
  if ( 'post' == $array['record_type'] ) {
359
  $forms[ $form_name ]['fields'][ $key ] = array_merge( $default_fields['field_types']['post'][ $array['name'] ], $array );
360
- } else {
361
  $forms[ $form_name ]['fields'][ $key ] = array_merge( $default_fields['field_types']['custom'][ $array['input_type'] ], $array );
362
- }
 
 
363
  }
364
  }
365
 
310
  'after' => __( 'Would you like to include a photo?', 'strong-testimonials' ),
311
  'admin_table' => 1,
312
  ),
313
+ 8 => array(
314
+ 'record_type' => 'optional',
315
+ 'name' => 'star_rating',
316
+ 'label' => __( 'Star rating', 'strong-testimonials' ),
317
+ 'input_type' => 'rating',
318
+ 'required' => 0,
319
+ 'after' => __( 'Would you like to include star rating?', 'strong-testimonials' )
320
+ ),
321
  ),
322
  ),
323
  );
365
  foreach ( $form['fields'] as $key => $array ) {
366
  if ( 'post' == $array['record_type'] ) {
367
  $forms[ $form_name ]['fields'][ $key ] = array_merge( $default_fields['field_types']['post'][ $array['name'] ], $array );
368
+ } elseif ( 'custom' == $array['record_type']) {
369
  $forms[ $form_name ]['fields'][ $key ] = array_merge( $default_fields['field_types']['custom'][ $array['input_type'] ], $array );
370
+ } else {
371
+ $forms[ $form_name ]['fields'][ $key ] = array_merge( $default_fields['field_types']['optional'][ $array['input_type'] ], $array );
372
+ }
373
  }
374
  }
375
 
admin/class-strong-testimonials-post-editor.php CHANGED
@@ -52,6 +52,7 @@ class Strong_Testimonials_Post_Editor {
52
  $post = wpmtst_get_post( $post );
53
  $fields = wpmtst_get_custom_fields();
54
  $is_new = ( 'post-new.php' == $pagenow );
 
55
  ?>
56
  <?php do_action( 'wpmtst_before_client_fields_table' ); ?>
57
  <table class="options">
@@ -294,7 +295,7 @@ class Strong_Testimonials_Post_Editor {
294
  * @since 2.23.2 Delete meta record when rating is zero to allow default display value.
295
  */
296
  public static function save_details() {
297
- if ( ! isset( $_POST['custom'] ) ) {
298
  return;
299
  }
300
 
52
  $post = wpmtst_get_post( $post );
53
  $fields = wpmtst_get_custom_fields();
54
  $is_new = ( 'post-new.php' == $pagenow );
55
+ wp_nonce_field ( plugin_basename(__FILE__), 'wpmtst_metabox_nonce');
56
  ?>
57
  <?php do_action( 'wpmtst_before_client_fields_table' ); ?>
58
  <table class="options">
295
  * @since 2.23.2 Delete meta record when rating is zero to allow default display value.
296
  */
297
  public static function save_details() {
298
+ if ( ! isset( $_POST['custom'] ) || !wp_verify_nonce( $_POST['wpmtst_metabox_nonce'], plugin_basename(__FILE__))) {
299
  return;
300
  }
301
 
admin/class-strong-testimonials-review.php CHANGED
@@ -118,7 +118,7 @@ class Strong_Review {
118
  <script type="text/javascript">
119
  jQuery( document ).ready( function( $ ){
120
 
121
- $( '.strong-testimonials-review-button' ).click( function( evt ){
122
  var href = $(this).attr('href'),
123
  id = $(this).attr('id');
124
 
118
  <script type="text/javascript">
119
  jQuery( document ).ready( function( $ ){
120
 
121
+ $( '.strong-testimonials-review-button' ).on('click', function( evt ){
122
  var href = $(this).attr('href'),
123
  id = $(this).attr('id');
124
 
admin/class-strong-testimonials-upsell.php CHANGED
@@ -155,7 +155,7 @@ class Strong_Testimonials_Upsell {
155
 
156
  <div class="wpmtst-settings-upsell">
157
  <div class="wpmtst-alert">
158
- <h3>Upgrade to PRO</h3>
159
  <ul>
160
  <?php foreach ( $general_upsells as $general_upsell ) { ?>
161
  <li>
@@ -167,7 +167,7 @@ class Strong_Testimonials_Upsell {
167
  <?php } ?>
168
  </ul>
169
 
170
- <a href="<?php echo esc_url( WPMTST_STORE_URL . '/pricing?utm_source=st-lite&utm_campaign=upsell&utm_medium=general-settings-upsell' ) ?>" target="_blank" class="button button-primary button-hero" style="width:100%;display:block;margin-top:20px;text-align:center;">Upgrade to PRO</a>
171
 
172
  </div>
173
  </div>
@@ -374,7 +374,7 @@ class Strong_Testimonials_Upsell {
374
  );
375
  ?>
376
  <ul>
377
- <li><?php esc_html_e( 'With this extensions, search engines will display star ratings in search results for your site.', 'strong-testimonials' ); ?></li>
378
  </ul>
379
  <p>
380
  <a class="button button-primary" target="_blank" href="<?php echo esc_url( $this->store_upgrade_url . '&utm_medium=views-review-markup-upsell' ); ?>"><?php esc_html_e( 'Upgrade', 'strong-testimonials' ); ?></a>
@@ -415,9 +415,9 @@ class Strong_Testimonials_Upsell {
415
 
416
  ?>
417
  <ul>
418
- <li><?php esc_html_e( 'filter & display testimonials based on their rating or on a pre-defined condition.', 'strong-testimonials' ); ?></li>
419
- <li><?php esc_html_e( 'easily define the display order of your testimonial fields. Re-order the name, image, url and testimonial content fields through drag & drop.', 'strong-testimonials' ); ?></li>
420
- <li><?php esc_html_e( 'edit, in real time, the way your testimonials will look on your site. Stop loosing clients because of poor design.', 'strong-testimonials' ); ?></li>
421
 
422
  </ul>
423
  <p>
@@ -583,9 +583,9 @@ class Strong_Testimonials_Upsell {
583
  );
584
  ?>
585
  <ul>
586
- <li><?php esc_html_e( 'send a thank you email to your client once his testimonial\'s approved', 'strong-testimonials' ); ?></li>
587
- <li><?php esc_html_e( 'increase brand loyalty by showing you really care about your clients', 'strong-testimonials' ); ?></li>
588
- <li><?php esc_html_e( 'keep your clients engaged and increase your chances of selling more', 'strong-testimonials' ); ?></li>
589
  </ul>
590
  <p>
591
  <a class="button button-primary" target="_blank" href="<?php echo esc_url( $this->store_upgrade_url . '&utm_medium=enhanced-emails-upsell' ); ?>"><?php esc_html_e( 'Upgrade', 'strong-testimonials' ); ?></a>
@@ -626,8 +626,8 @@ class Strong_Testimonials_Upsell {
626
  );
627
  ?>
628
  <ul>
629
- <li><?php esc_html_e( 'display a fixed number of testimonials on first view and have more of them load when the user starts scrolling', 'strong-testimonials' ); ?></li>
630
- <li><?php esc_html_e( 'reduce your page\'s initial load time, making your site faster in the process and not driving clients away because of a slow loading website', 'strong-testimonials' ); ?></li>
631
  </ul>
632
  <p>
633
  <a class="button button-primary" target="_blank" href="<?php echo esc_url( $this->store_upgrade_url . '&utm_medium=infinite-scroll-upsell' ); ?>"><?php esc_html_e( 'Upgrade', 'strong-testimonials' ); ?></a>
@@ -668,9 +668,9 @@ class Strong_Testimonials_Upsell {
668
  );
669
  ?>
670
  <ul>
671
- <li><?php esc_html_e( 'create category-like filters for your testimonials', 'strong-testimonials' ); ?></li>
672
- <li><?php esc_html_e( 'group testimonials by associated product or service', 'strong-testimonials' ); ?></li>
673
- <li><?php esc_html_e( 'help potential clients appreciate the great work you do by showcasing reviews from other clients', 'strong-testimonials' ); ?></li>
674
  </ul>
675
  <p>
676
  <a class="button button-primary" target="_blank" href="<?php echo esc_url( $this->store_upgrade_url . '&utm_medium=filters-upsell' ); ?>"><?php esc_html_e( 'Upgrade', 'strong-testimonials' ); ?></a>
@@ -761,12 +761,12 @@ class Strong_Testimonials_Upsell {
761
  );
762
  ?>
763
  <ul>
764
- <li><?php esc_html_e( 'Display a default image when no image has been provided for the testimonial;', 'strong-testimonials' ); ?></li>
765
- <li><?php esc_html_e( 'Use author initials as the testimonial image;', 'strong-testimonials' ); ?></li>
766
- <li><?php esc_html_e( 'Choose the HTML tag you’d like to use for your testimonial titles;', 'strong-testimonials' ); ?></li>
767
- <li><?php esc_html_e( 'Choose the Single Testimonial Template settings;', 'strong-testimonials' ); ?></li>
768
- <li><?php esc_html_e( 'Prefill testimonial forms from $_GET parameters;', 'strong-testimonials' ); ?></li>
769
- <li><?php esc_html_e( 'Show testimonial form only for logged-in users.', 'strong-testimonials' ); ?></li>
770
  </ul>
771
  <p>
772
  <a class="button button-primary" target="_blank" href="<?php echo esc_url( $this->store_upgrade_url . '&utm_medium=setting-tab-st-pro-upsell' ); ?>"><?php esc_html_e( 'Upgrade', 'strong-testimonials' ); ?></a>
155
 
156
  <div class="wpmtst-settings-upsell">
157
  <div class="wpmtst-alert">
158
+ <h3>Upgrade now</h3>
159
  <ul>
160
  <?php foreach ( $general_upsells as $general_upsell ) { ?>
161
  <li>
167
  <?php } ?>
168
  </ul>
169
 
170
+ <a href="<?php echo esc_url( WPMTST_STORE_URL . '/pricing?utm_source=st-lite&utm_campaign=upsell&utm_medium=general-settings-upsell' ) ?>" target="_blank" class="button button-primary button-hero" style="width:100%;display:block;margin-top:20px;text-align:center;">Upgrade now</a>
171
 
172
  </div>
173
  </div>
374
  );
375
  ?>
376
  <ul>
377
+ <li class="wpmtst-upsell-checkmark"><?php esc_html_e( 'With this extensions, search engines will display star ratings in search results for your site.', 'strong-testimonials' ); ?></li>
378
  </ul>
379
  <p>
380
  <a class="button button-primary" target="_blank" href="<?php echo esc_url( $this->store_upgrade_url . '&utm_medium=views-review-markup-upsell' ); ?>"><?php esc_html_e( 'Upgrade', 'strong-testimonials' ); ?></a>
415
 
416
  ?>
417
  <ul>
418
+ <li class="wpmtst-upsell-checkmark"><?php esc_html_e( 'filter & display testimonials based on their rating or on a pre-defined condition.', 'strong-testimonials' ); ?></li>
419
+ <li class="wpmtst-upsell-checkmark"><?php esc_html_e( 'easily define the display order of your testimonial fields. Re-order the name, image, url and testimonial content fields through drag & drop.', 'strong-testimonials' ); ?></li>
420
+ <li class="wpmtst-upsell-checkmark"><?php esc_html_e( 'edit, in real time, the way your testimonials will look on your site. Stop loosing clients because of poor design.', 'strong-testimonials' ); ?></li>
421
 
422
  </ul>
423
  <p>
583
  );
584
  ?>
585
  <ul>
586
+ <li class="wpmtst-upsell-checkmark"><?php esc_html_e( 'send a thank you email to your client once his testimonial\'s approved', 'strong-testimonials' ); ?></li>
587
+ <li class="wpmtst-upsell-checkmark"><?php esc_html_e( 'increase brand loyalty by showing you really care about your clients', 'strong-testimonials' ); ?></li>
588
+ <li class="wpmtst-upsell-checkmark"><?php esc_html_e( 'keep your clients engaged and increase your chances of selling more', 'strong-testimonials' ); ?></li>
589
  </ul>
590
  <p>
591
  <a class="button button-primary" target="_blank" href="<?php echo esc_url( $this->store_upgrade_url . '&utm_medium=enhanced-emails-upsell' ); ?>"><?php esc_html_e( 'Upgrade', 'strong-testimonials' ); ?></a>
626
  );
627
  ?>
628
  <ul>
629
+ <li class="wpmtst-upsell-checkmark"><?php esc_html_e( 'display a fixed number of testimonials on first view and have more of them load when the user starts scrolling', 'strong-testimonials' ); ?></li>
630
+ <li class="wpmtst-upsell-checkmark"><?php esc_html_e( 'reduce your page\'s initial load time, making your site faster in the process and not driving clients away because of a slow loading website', 'strong-testimonials' ); ?></li>
631
  </ul>
632
  <p>
633
  <a class="button button-primary" target="_blank" href="<?php echo esc_url( $this->store_upgrade_url . '&utm_medium=infinite-scroll-upsell' ); ?>"><?php esc_html_e( 'Upgrade', 'strong-testimonials' ); ?></a>
668
  );
669
  ?>
670
  <ul>
671
+ <li class="wpmtst-upsell-checkmark"><?php esc_html_e( 'create category-like filters for your testimonials', 'strong-testimonials' ); ?></li>
672
+ <li class="wpmtst-upsell-checkmark"><?php esc_html_e( 'group testimonials by associated product or service', 'strong-testimonials' ); ?></li>
673
+ <li class="wpmtst-upsell-checkmark"><?php esc_html_e( 'help potential clients appreciate the great work you do by showcasing reviews from other clients', 'strong-testimonials' ); ?></li>
674
  </ul>
675
  <p>
676
  <a class="button button-primary" target="_blank" href="<?php echo esc_url( $this->store_upgrade_url . '&utm_medium=filters-upsell' ); ?>"><?php esc_html_e( 'Upgrade', 'strong-testimonials' ); ?></a>
761
  );
762
  ?>
763
  <ul>
764
+ <li class="wpmtst-upsell-checkmark"><?php esc_html_e( 'Display a default image when no image has been provided for the testimonial;', 'strong-testimonials' ); ?></li>
765
+ <li class="wpmtst-upsell-checkmark"><?php esc_html_e( 'Use author initials as the testimonial image;', 'strong-testimonials' ); ?></li>
766
+ <li class="wpmtst-upsell-checkmark"><?php esc_html_e( 'Choose the HTML tag you’d like to use for your testimonial titles;', 'strong-testimonials' ); ?></li>
767
+ <li class="wpmtst-upsell-checkmark"><?php esc_html_e( 'Choose the Single Testimonial Template settings;', 'strong-testimonials' ); ?></li>
768
+ <li class="wpmtst-upsell-checkmark"><?php esc_html_e( 'Prefill testimonial forms from $_GET parameters;', 'strong-testimonials' ); ?></li>
769
+ <li class="wpmtst-upsell-checkmark"><?php esc_html_e( 'Show testimonial form only for logged-in users.', 'strong-testimonials' ); ?></li>
770
  </ul>
771
  <p>
772
  <a class="button button-primary" target="_blank" href="<?php echo esc_url( $this->store_upgrade_url . '&utm_medium=setting-tab-st-pro-upsell' ); ?>"><?php esc_html_e( 'Upgrade', 'strong-testimonials' ); ?></a>
admin/custom-fields.php CHANGED
@@ -82,6 +82,7 @@ function wpmtst_update_custom_fields() {
82
 
83
  $field['name'] = sanitize_text_field( $field['name'] );
84
  $field['label'] = sanitize_text_field( $field['label'] );
 
85
 
86
  // TODO Replace this special handling
87
  if ( 'checkbox' == $field['input_type'] ) {
@@ -96,11 +97,8 @@ function wpmtst_update_custom_fields() {
96
 
97
  $field['placeholder'] = sanitize_text_field( $field['placeholder'] );
98
 
99
- if ( isset( $field['text'] ) ) {
100
- $field['text'] = wp_filter_post_kses( $field['text'] );
101
- }
102
- $field['before'] = sanitize_text_field( $field['before'] );
103
- $field['after'] = sanitize_text_field( $field['after'] );
104
 
105
  $field['shortcode_on_form'] = sanitize_text_field( $field['shortcode_on_form'] );
106
  $field['shortcode_on_display'] = sanitize_text_field( $field['shortcode_on_display'] );
82
 
83
  $field['name'] = sanitize_text_field( $field['name'] );
84
  $field['label'] = sanitize_text_field( $field['label'] );
85
+ $field['text'] = sanitize_text_field( $field['text'] );
86
 
87
  // TODO Replace this special handling
88
  if ( 'checkbox' == $field['input_type'] ) {
97
 
98
  $field['placeholder'] = sanitize_text_field( $field['placeholder'] );
99
 
100
+ $field['before'] = sanitize_text_field( $field['before'] );
101
+ $field['after'] = sanitize_text_field( $field['after'] );
 
 
 
102
 
103
  $field['shortcode_on_form'] = sanitize_text_field( $field['shortcode_on_form'] );
104
  $field['shortcode_on_display'] = sanitize_text_field( $field['shortcode_on_display'] );
admin/js/admin-compat.js CHANGED
@@ -77,14 +77,14 @@
77
 
78
  // Presets
79
  function setScenario1() {
80
- $('#page-loading-general').click()
81
- $('#prerender-all').click().prop('checked', true)
82
- $('#method-universal').click().prop('checked', true)
83
  }
84
 
85
  function setScenarioDefault() {
86
- $('#prerender-current').click()
87
- $('#method-none').click()
88
  }
89
 
90
  // Listen for change
@@ -104,7 +104,7 @@
104
 
105
  // Listen for presets
106
  $('#set-scenario-1').on('click', function(e) {
107
- $(this).blur()
108
  setScenario1()
109
  e.preventDefault()
110
  })
77
 
78
  // Presets
79
  function setScenario1() {
80
+ $('#page-loading-general').trigger('click')
81
+ $('#prerender-all').trigger('click').prop('checked', true)
82
+ $('#method-universal').trigger('click').prop('checked', true)
83
  }
84
 
85
  function setScenarioDefault() {
86
+ $('#prerender-current').trigger('click')
87
+ $('#method-none').trigger('click')
88
  }
89
 
90
  // Listen for change
104
 
105
  // Listen for presets
106
  $('#set-scenario-1').on('click', function(e) {
107
+ $(this).trigger('blur')
108
  setScenario1()
109
  e.preventDefault()
110
  })
admin/js/admin-fields.js CHANGED
@@ -97,7 +97,7 @@ function sanitizeName(label) {
97
  * Disable buttons on submit.
98
  * Thanks https://stackoverflow.com/a/25651260/51600
99
  */
100
- $theForm.submit(function(){
101
  $('#field-group-actions').find('.button').each(function (index) {
102
  // Create a disabled clone of the submit button
103
  $(this).clone(false).removeAttr('id').prop('disabled', true).insertBefore($(this));
@@ -118,9 +118,9 @@ function sanitizeName(label) {
118
  $(this).parent().find('.form-error-text').show();
119
  var $parent = $(this).closest("li");
120
  if (!$parent.hasClass("open")) {
121
- $parent.find("a.field").click();
122
  }
123
- $(this).focus();
124
  e.preventDefault();
125
  } else {
126
  $(this).closest('tr').removeClass('form-error');
@@ -135,9 +135,9 @@ function sanitizeName(label) {
135
  $(this).parent().find('.field-name-help.important').addClass('form-error-text');
136
  var $parent = $(this).closest("li");
137
  if (!$parent.hasClass("open")) {
138
- $parent.find("a.field").click();
139
  }
140
- $(this).focus();
141
  e.preventDefault();
142
  } else {
143
  $(this).closest('tr').removeClass('form-error');
@@ -151,7 +151,7 @@ function sanitizeName(label) {
151
  * Cancel Changes
152
  */
153
  $('#reset').on('click',function(e){
154
- $theForm.submit();
155
  });
156
 
157
  /**
@@ -159,9 +159,9 @@ function sanitizeName(label) {
159
  */
160
  $('#restore-defaults').on('click',function(e){
161
  if (confirm("Restore the default fields?")) {
162
- $theForm.submit();
163
  } else {
164
- $(this).blur();
165
  return false;
166
  }
167
  });
@@ -202,7 +202,7 @@ function sanitizeName(label) {
202
  // fill in blank field name
203
  var $fieldName = $parent.find("input.field-name");
204
  if ('new_field' === $fieldName.val()) {
205
- $fieldName.val(getUniqueName(newLabel, fieldIndex)).change();
206
  }
207
  });
208
 
@@ -225,7 +225,7 @@ function sanitizeName(label) {
225
  if ('name' === $(this).val() || 'date' === $(this).val()) {
226
  $(this).closest('tr').addClass('form-error');
227
  $(this).parent().find('.field-name-help.important').addClass('form-error-text');
228
- $(this).focus()
229
  return false;
230
  } else {
231
  $(this).closest('tr').removeClass('form-error');
@@ -237,7 +237,7 @@ function sanitizeName(label) {
237
  * Delete field
238
  */
239
  $fieldList.on("click", ".delete-field", function () {
240
- $(this).blur();
241
  dismissNotice();
242
  var thisField = $(this).closest("li");
243
  var thisLabel = thisField.find(".field").text();
@@ -246,7 +246,7 @@ function sanitizeName(label) {
246
  $.when(thisField.remove()).then(function () {
247
  formPreview();
248
  toggleCategoryFields();
249
- $("#add-field, #submit").removeAttr("disabled");
250
  })
251
  });
252
  }
@@ -263,7 +263,7 @@ function sanitizeName(label) {
263
  /**
264
  * Add new field
265
  */
266
- $("#add-field").click(function () {
267
  dismissNotice();
268
  var keys = $fieldList.find("li").map(function () {
269
  var key_id = $(this).attr("id");
@@ -296,7 +296,7 @@ function sanitizeName(label) {
296
  toggleCategoryFields();
297
 
298
  // click it to open
299
- $li.find("span.link").click();
300
  });
301
  });
302
  });
@@ -380,7 +380,7 @@ function sanitizeName(label) {
380
  // hide help message
381
  $parent.find(".field-name-help").hide();
382
  }
383
- $fieldLabel.val(wpmtstAdmin.newField).focus().select();
384
  break;
385
 
386
  default:
@@ -388,9 +388,9 @@ function sanitizeName(label) {
388
  $parent.find('.field-name-row').show();
389
 
390
  // TODO DRY
391
- $fieldLabel.val(wpmtstAdmin.newField).focus().select();
392
  $fieldName.val(getUniqueName($fieldLabel.val(), fieldIndex));
393
- $fieldName.removeAttr('disabled');
394
  $parent.find(".field-name-help").show();
395
  }
396
 
@@ -443,7 +443,7 @@ function sanitizeName(label) {
443
  ajax3.done(function () {
444
 
445
  formPreview();
446
- $("#add-field, #submit").removeAttr("disabled");
447
 
448
  // Successfully added so show "Close" link
449
  $("span.close-field").show();
@@ -552,7 +552,7 @@ function sanitizeName(label) {
552
  } else {
553
  $options.each(function () {
554
  $(this)
555
- .removeAttr("disabled")
556
  .text($(this).data('origText'));
557
  });
558
  }
@@ -570,7 +570,7 @@ function sanitizeName(label) {
570
  .toggleClass("open")
571
  .slideToggle()
572
  .find(".first-field")
573
- .focus();
574
  }
575
 
576
  // Build a unique name
@@ -597,7 +597,7 @@ function sanitizeName(label) {
597
 
598
  // Dismiss the "Fields saved" notice.
599
  function dismissNotice() {
600
- $('.wpmtst.notice').find(".notice-dismiss").click();
601
  }
602
 
603
  })(jQuery);
97
  * Disable buttons on submit.
98
  * Thanks https://stackoverflow.com/a/25651260/51600
99
  */
100
+ $theForm.on('submit', function(){
101
  $('#field-group-actions').find('.button').each(function (index) {
102
  // Create a disabled clone of the submit button
103
  $(this).clone(false).removeAttr('id').prop('disabled', true).insertBefore($(this));
118
  $(this).parent().find('.form-error-text').show();
119
  var $parent = $(this).closest("li");
120
  if (!$parent.hasClass("open")) {
121
+ $parent.find("a.field").trigger('click');
122
  }
123
+ $(this).trigger('focus');
124
  e.preventDefault();
125
  } else {
126
  $(this).closest('tr').removeClass('form-error');
135
  $(this).parent().find('.field-name-help.important').addClass('form-error-text');
136
  var $parent = $(this).closest("li");
137
  if (!$parent.hasClass("open")) {
138
+ $parent.find("a.field").trigger('click');
139
  }
140
+ $(this).trigger('focus');
141
  e.preventDefault();
142
  } else {
143
  $(this).closest('tr').removeClass('form-error');
151
  * Cancel Changes
152
  */
153
  $('#reset').on('click',function(e){
154
+ $theForm.trigger('submit');
155
  });
156
 
157
  /**
159
  */
160
  $('#restore-defaults').on('click',function(e){
161
  if (confirm("Restore the default fields?")) {
162
+ $theForm.trigger('submit');
163
  } else {
164
+ $(this).trigger("blur");
165
  return false;
166
  }
167
  });
202
  // fill in blank field name
203
  var $fieldName = $parent.find("input.field-name");
204
  if ('new_field' === $fieldName.val()) {
205
+ $fieldName.val(getUniqueName(newLabel, fieldIndex)).trigger( 'change' );
206
  }
207
  });
208
 
225
  if ('name' === $(this).val() || 'date' === $(this).val()) {
226
  $(this).closest('tr').addClass('form-error');
227
  $(this).parent().find('.field-name-help.important').addClass('form-error-text');
228
+ $(this).trigger('focus')
229
  return false;
230
  } else {
231
  $(this).closest('tr').removeClass('form-error');
237
  * Delete field
238
  */
239
  $fieldList.on("click", ".delete-field", function () {
240
+ $(this).trigger("blur");
241
  dismissNotice();
242
  var thisField = $(this).closest("li");
243
  var thisLabel = thisField.find(".field").text();
246
  $.when(thisField.remove()).then(function () {
247
  formPreview();
248
  toggleCategoryFields();
249
+ $("#add-field, #submit").prop("disabled", false);
250
  })
251
  });
252
  }
263
  /**
264
  * Add new field
265
  */
266
+ $("#add-field").on('click', function () {
267
  dismissNotice();
268
  var keys = $fieldList.find("li").map(function () {
269
  var key_id = $(this).attr("id");
296
  toggleCategoryFields();
297
 
298
  // click it to open
299
+ $li.find("span.link").trigger('click');
300
  });
301
  });
302
  });
380
  // hide help message
381
  $parent.find(".field-name-help").hide();
382
  }
383
+ $fieldLabel.val(wpmtstAdmin.newField).trigger('focus').trigger('select');
384
  break;
385
 
386
  default:
388
  $parent.find('.field-name-row').show();
389
 
390
  // TODO DRY
391
+ $fieldLabel.val(wpmtstAdmin.newField).trigger('focus').trigger('select');
392
  $fieldName.val(getUniqueName($fieldLabel.val(), fieldIndex));
393
+ $fieldName.prop('disabled', false);
394
  $parent.find(".field-name-help").show();
395
  }
396
 
443
  ajax3.done(function () {
444
 
445
  formPreview();
446
+ $("#add-field, #submit").prop("disabled", false);
447
 
448
  // Successfully added so show "Close" link
449
  $("span.close-field").show();
552
  } else {
553
  $options.each(function () {
554
  $(this)
555
+ .prop("disabled", false)
556
  .text($(this).data('origText'));
557
  });
558
  }
570
  .toggleClass("open")
571
  .slideToggle()
572
  .find(".first-field")
573
+ .trigger('focus');
574
  }
575
 
576
  // Build a unique name
597
 
598
  // Dismiss the "Fields saved" notice.
599
  function dismissNotice() {
600
+ $('.wpmtst.notice').find(".notice-dismiss").trigger('click');
601
  }
602
 
603
  })(jQuery);
admin/js/admin-form.js CHANGED
@@ -22,14 +22,14 @@ jQuery(document).ready(function ($) {
22
  $notifyAdmin.on( 'change', function (e) {
23
  if ($(this).is(':checked')) {
24
  $notifyFields.slideDown();
25
- $(this).blur();
26
  }
27
  else {
28
  $notifyFields.slideUp();
29
  }
30
  });
31
 
32
- $('#add-recipient').click(function (e) {
33
  var $this = $(this);
34
  var key = $this.parent().siblings('.recipient').length;
35
  var data = {
@@ -37,7 +37,7 @@ jQuery(document).ready(function ($) {
37
  'key': key,
38
  };
39
  $.get(ajaxurl, data, function (response) {
40
- $this.parent().before(response).prev().find('.admin_name').first().focus();
41
  });
42
  });
43
 
@@ -66,10 +66,10 @@ jQuery(document).ready(function ($) {
66
  var sel;
67
  //IE support
68
  if (document.selection) {
69
- this.focus();
70
  sel = document.selection.createRange();
71
  sel.text = myValue;
72
- this.focus();
73
  }
74
  //MOZILLA / NETSCAPE support
75
  else if (this.selectionStart || this.selectionStart === '0') {
@@ -77,13 +77,13 @@ jQuery(document).ready(function ($) {
77
  var endPos = this.selectionEnd;
78
  var scrollTop = this.scrollTop;
79
  this.value = this.value.substring(0, startPos) + myValue + this.value.substring(endPos, this.value.length);
80
- this.focus();
81
  this.selectionStart = startPos + myValue.length;
82
  this.selectionEnd = startPos + myValue.length;
83
  this.scrollTop = scrollTop;
84
  } else {
85
  this.value += myValue;
86
- this.focus();
87
  }
88
  });
89
  };
@@ -103,7 +103,7 @@ jQuery(document).ready(function ($) {
103
  /**
104
  * Restore all default messages
105
  */
106
- $('#restore-default-messages').click(function (e) {
107
  var data = {
108
  'action': 'wpmtst_restore_default_messages'
109
  };
@@ -137,7 +137,7 @@ jQuery(document).ready(function ($) {
137
  /**
138
  * Restore a single default message
139
  */
140
- $('.restore-default-message').click(function (e) {
141
  var targetId = $(e.target).data('targetId');
142
  var data = {
143
  'action': 'wpmtst_restore_default_message',
22
  $notifyAdmin.on( 'change', function (e) {
23
  if ($(this).is(':checked')) {
24
  $notifyFields.slideDown();
25
+ $(this).trigger('blur');
26
  }
27
  else {
28
  $notifyFields.slideUp();
29
  }
30
  });
31
 
32
+ $('#add-recipient').on('click', function (e) {
33
  var $this = $(this);
34
  var key = $this.parent().siblings('.recipient').length;
35
  var data = {
37
  'key': key,
38
  };
39
  $.get(ajaxurl, data, function (response) {
40
+ $this.parent().before(response).prev().find('.admin_name').first().trigger('focus');
41
  });
42
  });
43
 
66
  var sel;
67
  //IE support
68
  if (document.selection) {
69
+ this.trigger('focus');
70
  sel = document.selection.createRange();
71
  sel.text = myValue;
72
+ this.trigger('focus');
73
  }
74
  //MOZILLA / NETSCAPE support
75
  else if (this.selectionStart || this.selectionStart === '0') {
77
  var endPos = this.selectionEnd;
78
  var scrollTop = this.scrollTop;
79
  this.value = this.value.substring(0, startPos) + myValue + this.value.substring(endPos, this.value.length);
80
+ this.trigger('focus');
81
  this.selectionStart = startPos + myValue.length;
82
  this.selectionEnd = startPos + myValue.length;
83
  this.scrollTop = scrollTop;
84
  } else {
85
  this.value += myValue;
86
+ this.trigger('focus');
87
  }
88
  });
89
  };
103
  /**
104
  * Restore all default messages
105
  */
106
+ $('#restore-default-messages').on('click', function (e) {
107
  var data = {
108
  'action': 'wpmtst_restore_default_messages'
109
  };
137
  /**
138
  * Restore a single default message
139
  */
140
+ $('.restore-default-message').on('click', function (e) {
141
  var targetId = $(e.target).data('targetId');
142
  var data = {
143
  'action': 'wpmtst_restore_default_message',
admin/js/admin-order.js CHANGED
@@ -117,7 +117,7 @@ jQuery(document).ready(function ($) {
117
  handles: 'td.column-handle'
118
  });
119
 
120
- $("td.column-handle").hover(
121
  function () {
122
  $(this).closest("tr").addClass("reorder-hover");
123
  },
117
  handles: 'td.column-handle'
118
  });
119
 
120
+ $("td.column-handle").on( 'mouseenter mouseleave',
121
  function () {
122
  $(this).closest("tr").addClass("reorder-hover");
123
  },
admin/js/custom-spinner.js CHANGED
@@ -46,7 +46,7 @@
46
  plus.addClass('disabled')
47
  }
48
 
49
- minus.click(function () {
50
  var input = $(this).parent().find('input')
51
  var value = +round(input.val(),1)
52
  if (+value > +min) {
@@ -62,7 +62,7 @@
62
  }
63
  })
64
 
65
- plus.click(function () {
66
  var input = $(this).parent().find('input')
67
  var value = +round(input.val(),2)
68
  if (+value < +max) {
46
  plus.addClass('disabled')
47
  }
48
 
49
+ minus.on('click', function () {
50
  var input = $(this).parent().find('input')
51
  var value = +round(input.val(),1)
52
  if (+value > +min) {
62
  }
63
  })
64
 
65
+ plus.on('click', function () {
66
  var input = $(this).parent().find('input')
67
  var value = +round(input.val(),2)
68
  if (+value < +max) {
admin/js/help.js CHANGED
@@ -10,8 +10,8 @@
10
 
11
  if ($('#screen-meta').is(':hidden')) {
12
  // If Help container is closed, open it, then select tab
13
- $('#contextual-help-link').click().promise().done(function () {
14
- tabLink.click()
15
  })
16
  }
17
 
10
 
11
  if ($('#screen-meta').is(':hidden')) {
12
  // If Help container is closed, open it, then select tab
13
+ $('#contextual-help-link').trigger('click').promise().done(function () {
14
+ tabLink.trigger('click')
15
  })
16
  }
17
 
admin/js/lib/autosize/autosize.min.js CHANGED
@@ -1,6 +1,6 @@
1
  /*!
2
- autosize 4.0.1
3
  license: MIT
4
  http://www.jacklmoore.com/autosize
5
  */
6
- !function(e,t){if("function"==typeof define&&define.amd)define(["module","exports"],t);else if("undefined"!=typeof exports)t(module,exports);else{var n={exports:{}};t(n,n.exports),e.autosize=n.exports}}(this,function(e,t){"use strict";var n,o,p="function"==typeof Map?new Map:(n=[],o=[],{has:function(e){return-1<n.indexOf(e)},get:function(e){return o[n.indexOf(e)]},set:function(e,t){-1===n.indexOf(e)&&(n.push(e),o.push(t))},delete:function(e){var t=n.indexOf(e);-1<t&&(n.splice(t,1),o.splice(t,1))}}),c=function(e){return new Event(e,{bubbles:!0})};try{new Event("test")}catch(e){c=function(e){var t=document.createEvent("Event");return t.initEvent(e,!0,!1),t}}function r(r){if(r&&r.nodeName&&"TEXTAREA"===r.nodeName&&!p.has(r)){var e,n=null,o=null,i=null,d=function(){r.clientWidth!==o&&a()},l=function(t){window.removeEventListener("resize",d,!1),r.removeEventListener("input",a,!1),r.removeEventListener("keyup",a,!1),r.removeEventListener("autosize:destroy",l,!1),r.removeEventListener("autosize:update",a,!1),Object.keys(t).forEach(function(e){r.style[e]=t[e]}),p.delete(r)}.bind(r,{height:r.style.height,resize:r.style.resize,overflowY:r.style.overflowY,overflowX:r.style.overflowX,wordWrap:r.style.wordWrap});r.addEventListener("autosize:destroy",l,!1),"onpropertychange"in r&&"oninput"in r&&r.addEventListener("keyup",a,!1),window.addEventListener("resize",d,!1),r.addEventListener("input",a,!1),r.addEventListener("autosize:update",a,!1),r.style.overflowX="hidden",r.style.wordWrap="break-word",p.set(r,{destroy:l,update:a}),"vertical"===(e=window.getComputedStyle(r,null)).resize?r.style.resize="none":"both"===e.resize&&(r.style.resize="horizontal"),n="content-box"===e.boxSizing?-(parseFloat(e.paddingTop)+parseFloat(e.paddingBottom)):parseFloat(e.borderTopWidth)+parseFloat(e.borderBottomWidth),isNaN(n)&&(n=0),a()}function s(e){var t=r.style.width;r.style.width="0px",r.offsetWidth,r.style.width=t,r.style.overflowY=e}function u(){if(0!==r.scrollHeight){var e=function(e){for(var t=[];e&&e.parentNode&&e.parentNode instanceof Element;)e.parentNode.scrollTop&&t.push({node:e.parentNode,scrollTop:e.parentNode.scrollTop}),e=e.parentNode;return t}(r),t=document.documentElement&&document.documentElement.scrollTop;r.style.height="",r.style.height=r.scrollHeight+n+"px",o=r.clientWidth,e.forEach(function(e){e.node.scrollTop=e.scrollTop}),t&&(document.documentElement.scrollTop=t)}}function a(){u();var e=Math.round(parseFloat(r.style.height)),t=window.getComputedStyle(r,null),n="content-box"===t.boxSizing?Math.round(parseFloat(t.height)):r.offsetHeight;if(n!==e?"hidden"===t.overflowY&&(s("scroll"),u(),n="content-box"===t.boxSizing?Math.round(parseFloat(window.getComputedStyle(r,null).height)):r.offsetHeight):"hidden"!==t.overflowY&&(s("hidden"),u(),n="content-box"===t.boxSizing?Math.round(parseFloat(window.getComputedStyle(r,null).height)):r.offsetHeight),i!==n){i=n;var o=c("autosize:resized");try{r.dispatchEvent(o)}catch(e){}}}}function i(e){var t=p.get(e);t&&t.destroy()}function d(e){var t=p.get(e);t&&t.update()}var l=null;"undefined"==typeof window||"function"!=typeof window.getComputedStyle?((l=function(e){return e}).destroy=function(e){return e},l.update=function(e){return e}):((l=function(e,t){return e&&Array.prototype.forEach.call(e.length?e:[e],function(e){return r(e)}),e}).destroy=function(e){return e&&Array.prototype.forEach.call(e.length?e:[e],i),e},l.update=function(e){return e&&Array.prototype.forEach.call(e.length?e:[e],d),e}),t.default=l,e.exports=t.default});
1
  /*!
2
+ autosize 4.0.2
3
  license: MIT
4
  http://www.jacklmoore.com/autosize
5
  */
6
+ !function(e,t){if("function"==typeof define&&define.amd)define(["module","exports"],t);else if("undefined"!=typeof exports)t(module,exports);else{var n={exports:{}};t(n,n.exports),e.autosize=n.exports}}(this,function(e,t){"use strict";var n,o,p="function"==typeof Map?new Map:(n=[],o=[],{has:function(e){return-1<n.indexOf(e)},get:function(e){return o[n.indexOf(e)]},set:function(e,t){-1===n.indexOf(e)&&(n.push(e),o.push(t))},delete:function(e){var t=n.indexOf(e);-1<t&&(n.splice(t,1),o.splice(t,1))}}),c=function(e){return new Event(e,{bubbles:!0})};try{new Event("test")}catch(e){c=function(e){var t=document.createEvent("Event");return t.initEvent(e,!0,!1),t}}function r(r){if(r&&r.nodeName&&"TEXTAREA"===r.nodeName&&!p.has(r)){var e,n=null,o=null,i=null,d=function(){r.clientWidth!==o&&a()},l=function(t){window.removeEventListener("resize",d,!1),r.removeEventListener("input",a,!1),r.removeEventListener("keyup",a,!1),r.removeEventListener("autosize:destroy",l,!1),r.removeEventListener("autosize:update",a,!1),Object.keys(t).forEach(function(e){r.style[e]=t[e]}),p.delete(r)}.bind(r,{height:r.style.height,resize:r.style.resize,overflowY:r.style.overflowY,overflowX:r.style.overflowX,wordWrap:r.style.wordWrap});r.addEventListener("autosize:destroy",l,!1),"onpropertychange"in r&&"oninput"in r&&r.addEventListener("keyup",a,!1),window.addEventListener("resize",d,!1),r.addEventListener("input",a,!1),r.addEventListener("autosize:update",a,!1),r.style.overflowX="hidden",r.style.wordWrap="break-word",p.set(r,{destroy:l,update:a}),"vertical"===(e=window.getComputedStyle(r,null)).resize?r.style.resize="none":"both"===e.resize&&(r.style.resize="horizontal"),n="content-box"===e.boxSizing?-(parseFloat(e.paddingTop)+parseFloat(e.paddingBottom)):parseFloat(e.borderTopWidth)+parseFloat(e.borderBottomWidth),isNaN(n)&&(n=0),a()}function s(e){var t=r.style.width;r.style.width="0px",r.offsetWidth,r.style.width=t,r.style.overflowY=e}function u(){if(0!==r.scrollHeight){var e=function(e){for(var t=[];e&&e.parentNode&&e.parentNode instanceof Element;)e.parentNode.scrollTop&&t.push({node:e.parentNode,scrollTop:e.parentNode.scrollTop}),e=e.parentNode;return t}(r),t=document.documentElement&&document.documentElement.scrollTop;r.style.height="",r.style.height=r.scrollHeight+n+"px",o=r.clientWidth,e.forEach(function(e){e.node.scrollTop=e.scrollTop}),t&&(document.documentElement.scrollTop=t)}}function a(){u();var e=Math.round(parseFloat(r.style.height)),t=window.getComputedStyle(r,null),n="content-box"===t.boxSizing?Math.round(parseFloat(t.height)):r.offsetHeight;if(n<e?"hidden"===t.overflowY&&(s("scroll"),u(),n="content-box"===t.boxSizing?Math.round(parseFloat(window.getComputedStyle(r,null).height)):r.offsetHeight):"hidden"!==t.overflowY&&(s("hidden"),u(),n="content-box"===t.boxSizing?Math.round(parseFloat(window.getComputedStyle(r,null).height)):r.offsetHeight),i!==n){i=n;var o=c("autosize:resized");try{r.dispatchEvent(o)}catch(e){}}}}function i(e){var t=p.get(e);t&&t.destroy()}function d(e){var t=p.get(e);t&&t.update()}var l=null;"undefined"==typeof window||"function"!=typeof window.getComputedStyle?((l=function(e){return e}).destroy=function(e){return e},l.update=function(e){return e}):((l=function(e,t){return e&&Array.prototype.forEach.call(e.length?e:[e],function(e){return r(e)}),e}).destroy=function(e){return e&&Array.prototype.forEach.call(e.length?e:[e],i),e},l.update=function(e){return e&&Array.prototype.forEach.call(e.length?e:[e],d),e}),t.default=l,e.exports=t.default});
admin/js/rating-edit.js CHANGED
@@ -31,7 +31,7 @@ jQuery(document).ready(function ($) {
31
  var field_name = name_on_form.match(/\[(.*)\]/).pop();
32
 
33
  if (new_rating === revert_e) {
34
- buttons2.children('.cancel').click();
35
  return;
36
  }
37
 
@@ -74,7 +74,7 @@ jQuery(document).ready(function ($) {
74
 
75
  buttons2.children('.zero').on("click", function () {
76
  ratingForm.find("input[value=0]").prop("checked", true);
77
- $(this).blur();
78
  return false;
79
  });
80
 
31
  var field_name = name_on_form.match(/\[(.*)\]/).pop();
32
 
33
  if (new_rating === revert_e) {
34
+ buttons2.children('.cancel').trigger('click');
35
  return;
36
  }
37
 
74
 
75
  buttons2.children('.zero').on("click", function () {
76
  ratingForm.find("input[value=0]").prop("checked", true);
77
+ $(this).trigger('blur');
78
  return false;
79
  });
80
 
admin/js/selectize.js CHANGED
@@ -1,6 +1,6 @@
1
  /**
2
  * sifter.js
3
- * Copyright (c) 2013 Brian Reavis & contributors
4
  *
5
  * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this
6
  * file except in compliance with the License. You may obtain a copy of the License at:
@@ -15,489 +15,488 @@
15
  */
16
 
17
  (function(root, factory) {
18
- if (typeof define === 'function' && define.amd) {
19
- define('sifter', factory);
20
- } else if (typeof exports === 'object') {
21
- module.exports = factory();
22
- } else {
23
- root.Sifter = factory();
24
- }
25
  }(this, function() {
26
 
27
- /**
28
- * Textually searches arrays and hashes of objects
29
- * by property (or multiple properties). Designed
30
- * specifically for autocomplete.
31
- *
32
- * @constructor
33
- * @param {array|object} items
34
- * @param {object} items
35
- */
36
- var Sifter = function(items, settings) {
37
- this.items = items;
38
- this.settings = settings || {diacritics: true};
39
- };
40
-
41
- /**
42
- * Splits a search string into an array of individual
43
- * regexps to be used to match results.
44
- *
45
- * @param {string} query
46
- * @returns {array}
47
- */
48
- Sifter.prototype.tokenize = function(query) {
49
- query = trim(String(query || '').toLowerCase());
50
- if (!query || !query.length) return [];
51
-
52
- var i, n, regex, letter;
53
- var tokens = [];
54
- var words = query.split(/ +/);
55
-
56
- for (i = 0, n = words.length; i < n; i++) {
57
- regex = escape_regex(words[i]);
58
- if (this.settings.diacritics) {
59
- for (letter in DIACRITICS) {
60
- if (DIACRITICS.hasOwnProperty(letter)) {
61
- regex = regex.replace(new RegExp(letter, 'g'), DIACRITICS[letter]);
62
- }
63
- }
64
- }
65
- tokens.push({
66
- string : words[i],
67
- regex : new RegExp(regex, 'i')
68
- });
69
- }
70
-
71
- return tokens;
72
- };
73
-
74
- /**
75
- * Iterates over arrays and hashes.
76
- *
77
- * ```
78
- * this.iterator(this.items, function(item, id) {
79
- * // invoked for each item
80
- * });
81
- * ```
82
- *
83
- * @param {array|object} object
84
- */
85
- Sifter.prototype.iterator = function(object, callback) {
86
- var iterator;
87
- if (is_array(object)) {
88
- iterator = Array.prototype.forEach || function(callback) {
89
- for (var i = 0, n = this.length; i < n; i++) {
90
- callback(this[i], i, this);
91
- }
92
- };
93
- } else {
94
- iterator = function(callback) {
95
- for (var key in this) {
96
- if (this.hasOwnProperty(key)) {
97
- callback(this[key], key, this);
98
- }
99
- }
100
- };
101
- }
102
-
103
- iterator.apply(object, [callback]);
104
- };
105
-
106
- /**
107
- * Returns a function to be used to score individual results.
108
- *
109
- * Good matches will have a higher score than poor matches.
110
- * If an item is not a match, 0 will be returned by the function.
111
- *
112
- * @param {object|string} search
113
- * @param {object} options (optional)
114
- * @returns {function}
115
- */
116
- Sifter.prototype.getScoreFunction = function(search, options) {
117
- var self, fields, tokens, token_count, nesting;
118
-
119
- self = this;
120
- search = self.prepareSearch(search, options);
121
- tokens = search.tokens;
122
- fields = search.options.fields;
123
- token_count = tokens.length;
124
- nesting = search.options.nesting;
125
-
126
- /**
127
- * Calculates how close of a match the
128
- * given value is against a search token.
129
- *
130
- * @param {mixed} value
131
- * @param {object} token
132
- * @return {number}
133
- */
134
- var scoreValue = function(value, token) {
135
- var score, pos;
136
-
137
- if (!value) return 0;
138
- value = String(value || '');
139
- pos = value.search(token.regex);
140
- if (pos === -1) return 0;
141
- score = token.string.length / value.length;
142
- if (pos === 0) score += 0.5;
143
- return score;
144
- };
145
-
146
- /**
147
- * Calculates the score of an object
148
- * against the search query.
149
- *
150
- * @param {object} token
151
- * @param {object} data
152
- * @return {number}
153
- */
154
- var scoreObject = (function() {
155
- var field_count = fields.length;
156
- if (!field_count) {
157
- return function() { return 0; };
158
- }
159
- if (field_count === 1) {
160
- return function(token, data) {
161
- return scoreValue(getattr(data, fields[0], nesting), token);
162
- };
163
- }
164
- return function(token, data) {
165
- for (var i = 0, sum = 0; i < field_count; i++) {
166
- sum += scoreValue(getattr(data, fields[i], nesting), token);
167
- }
168
- return sum / field_count;
169
- };
170
- })();
171
-
172
- if (!token_count) {
173
- return function() { return 0; };
174
- }
175
- if (token_count === 1) {
176
- return function(data) {
177
- return scoreObject(tokens[0], data);
178
- };
179
- }
180
-
181
- if (search.options.conjunction === 'and') {
182
- return function(data) {
183
- var score;
184
- for (var i = 0, sum = 0; i < token_count; i++) {
185
- score = scoreObject(tokens[i], data);
186
- if (score <= 0) return 0;
187
- sum += score;
188
- }
189
- return sum / token_count;
190
- };
191
- } else {
192
- return function(data) {
193
- for (var i = 0, sum = 0; i < token_count; i++) {
194
- sum += scoreObject(tokens[i], data);
195
- }
196
- return sum / token_count;
197
- };
198
- }
199
- };
200
-
201
- /**
202
- * Returns a function that can be used to compare two
203
- * results, for sorting purposes. If no sorting should
204
- * be performed, `null` will be returned.
205
- *
206
- * @param {string|object} search
207
- * @param {object} options
208
- * @return function(a,b)
209
- */
210
- Sifter.prototype.getSortFunction = function(search, options) {
211
- var i, n, self, field, fields, fields_count, multiplier, multipliers, get_field, implicit_score, sort;
212
-
213
- self = this;
214
- search = self.prepareSearch(search, options);
215
- sort = (!search.query && options.sort_empty) || options.sort;
216
-
217
- /**
218
- * Fetches the specified sort field value
219
- * from a search result item.
220
- *
221
- * @param {string} name
222
- * @param {object} result
223
- * @return {mixed}
224
- */
225
- get_field = function(name, result) {
226
- if (name === '$score') return result.score;
227
- return getattr(self.items[result.id], name, options.nesting);
228
- };
229
-
230
- // parse options
231
- fields = [];
232
- if (sort) {
233
- for (i = 0, n = sort.length; i < n; i++) {
234
- if (search.query || sort[i].field !== '$score') {
235
- fields.push(sort[i]);
236
- }
237
- }
238
- }
239
-
240
- // the "$score" field is implied to be the primary
241
- // sort field, unless it's manually specified
242
- if (search.query) {
243
- implicit_score = true;
244
- for (i = 0, n = fields.length; i < n; i++) {
245
- if (fields[i].field === '$score') {
246
- implicit_score = false;
247
- break;
248
- }
249
- }
250
- if (implicit_score) {
251
- fields.unshift({field: '$score', direction: 'desc'});
252
- }
253
- } else {
254
- for (i = 0, n = fields.length; i < n; i++) {
255
- if (fields[i].field === '$score') {
256
- fields.splice(i, 1);
257
- break;
258
- }
259
- }
260
- }
261
-
262
- multipliers = [];
263
- for (i = 0, n = fields.length; i < n; i++) {
264
- multipliers.push(fields[i].direction === 'desc' ? -1 : 1);
265
- }
266
-
267
- // build function
268
- fields_count = fields.length;
269
- if (!fields_count) {
270
- return null;
271
- } else if (fields_count === 1) {
272
- field = fields[0].field;
273
- multiplier = multipliers[0];
274
- return function(a, b) {
275
- return multiplier * cmp(
276
- get_field(field, a),
277
- get_field(field, b)
278
- );
279
- };
280
- } else {
281
- return function(a, b) {
282
- var i, result, a_value, b_value, field;
283
- for (i = 0; i < fields_count; i++) {
284
- field = fields[i].field;
285
- result = multipliers[i] * cmp(
286
- get_field(field, a),
287
- get_field(field, b)
288
- );
289
- if (result) return result;
290
- }
291
- return 0;
292
- };
293
- }
294
- };
295
-
296
- /**
297
- * Parses a search query and returns an object
298
- * with tokens and fields ready to be populated
299
- * with results.
300
- *
301
- * @param {string} query
302
- * @param {object} options
303
- * @returns {object}
304
- */
305
- Sifter.prototype.prepareSearch = function(query, options) {
306
- if (typeof query === 'object') return query;
307
-
308
- options = extend({}, options);
309
-
310
- var option_fields = options.fields;
311
- var option_sort = options.sort;
312
- var option_sort_empty = options.sort_empty;
313
-
314
- if (option_fields && !is_array(option_fields)) options.fields = [option_fields];
315
- if (option_sort && !is_array(option_sort)) options.sort = [option_sort];
316
- if (option_sort_empty && !is_array(option_sort_empty)) options.sort_empty = [option_sort_empty];
317
-
318
- return {
319
- options : options,
320
- query : String(query || '').toLowerCase(),
321
- tokens : this.tokenize(query),
322
- total : 0,
323
- items : []
324
- };
325
- };
326
-
327
- /**
328
- * Searches through all items and returns a sorted array of matches.
329
- *
330
- * The `options` parameter can contain:
331
- *
332
- * - fields {string|array}
333
- * - sort {array}
334
- * - score {function}
335
- * - filter {bool}
336
- * - limit {integer}
337
- *
338
- * Returns an object containing:
339
- *
340
- * - options {object}
341
- * - query {string}
342
- * - tokens {array}
343
- * - total {int}
344
- * - items {array}
345
- *
346
- * @param {string} query
347
- * @param {object} options
348
- * @returns {object}
349
- */
350
- Sifter.prototype.search = function(query, options) {
351
- var self = this, value, score, search, calculateScore;
352
- var fn_sort;
353
- var fn_score;
354
-
355
- search = this.prepareSearch(query, options);
356
- options = search.options;
357
- query = search.query;
358
-
359
- // generate result scoring function
360
- fn_score = options.score || self.getScoreFunction(search);
361
-
362
- // perform search and sort
363
- if (query.length) {
364
- self.iterator(self.items, function(item, id) {
365
- score = fn_score(item);
366
- if (options.filter === false || score > 0) {
367
- search.items.push({'score': score, 'id': id});
368
- }
369
- });
370
- } else {
371
- self.iterator(self.items, function(item, id) {
372
- search.items.push({'score': 1, 'id': id});
373
- });
374
- }
375
-
376
- fn_sort = self.getSortFunction(search, options);
377
- if (fn_sort) search.items.sort(fn_sort);
378
-
379
- // apply limits
380
- search.total = search.items.length;
381
- if (typeof options.limit === 'number') {
382
- search.items = search.items.slice(0, options.limit);
383
- }
384
-
385
- return search;
386
- };
387
-
388
- // utilities
389
- // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
390
-
391
- var cmp = function(a, b) {
392
- if (typeof a === 'number' && typeof b === 'number') {
393
- return a > b ? 1 : (a < b ? -1 : 0);
394
- }
395
- a = asciifold(String(a || ''));
396
- b = asciifold(String(b || ''));
397
- if (a > b) return 1;
398
- if (b > a) return -1;
399
- return 0;
400
- };
401
-
402
- var extend = function(a, b) {
403
- var i, n, k, object;
404
- for (i = 1, n = arguments.length; i < n; i++) {
405
- object = arguments[i];
406
- if (!object) continue;
407
- for (k in object) {
408
- if (object.hasOwnProperty(k)) {
409
- a[k] = object[k];
410
- }
411
- }
412
- }
413
- return a;
414
- };
415
-
416
- /**
417
- * A property getter resolving dot-notation
418
- * @param {Object} obj The root object to fetch property on
419
- * @param {String} name The optionally dotted property name to fetch
420
- * @param {Boolean} nesting Handle nesting or not
421
- * @return {Object} The resolved property value
422
- */
423
- var getattr = function(obj, name, nesting) {
424
- if (!obj || !name) return;
425
- if (!nesting) return obj[name];
426
- var names = name.split(".");
427
- while(names.length && (obj = obj[names.shift()]));
428
- return obj;
429
- };
430
-
431
- var trim = function(str) {
432
- return (str + '').replace(/^\s+|\s+$|/g, '');
433
- };
434
-
435
- var escape_regex = function(str) {
436
- return (str + '').replace(/([.?*+^$[\]\\(){}|-])/g, '\\$1');
437
- };
438
-
439
- var is_array = Array.isArray || (typeof $ !== 'undefined' && $.isArray) || function(object) {
440
- return Object.prototype.toString.call(object) === '[object Array]';
441
- };
442
-
443
- var DIACRITICS = {
444
- 'a': '[aḀḁĂăÂâǍǎȺⱥȦȧẠạÄäÀàÁáĀāÃãÅåąĄÃąĄ]',
445
- 'b': '[b␢βΒB฿𐌁ᛒ]',
446
- 'c': '[cĆćĈĉČčĊċC̄c̄ÇçḈḉȻȼƇƈɕᴄCc]',
447
- 'd': '[dĎďḊḋḐḑḌḍḒḓḎḏĐđD̦d̦ƉɖƊɗƋƌᵭᶁᶑȡᴅDdð]',
448
- 'e': '[eÉéÈèÊêḘḙĚěĔĕẼẽḚḛẺẻĖėËëĒēȨȩĘęᶒɆɇȄȅẾếỀềỄễỂểḜḝḖḗḔḕȆȇẸẹỆệⱸᴇEeɘǝƏƐε]',
449
- 'f': '[fƑƒḞḟ]',
450
- 'g': '[gɢ₲ǤǥĜĝĞğĢģƓɠĠġ]',
451
- 'h': '[hĤĥĦħḨḩẖẖḤḥḢḣɦʰǶƕ]',
452
- 'i': '[iÍíÌìĬĭÎîǏǐÏïḮḯĨĩĮįĪīỈỉȈȉȊȋỊịḬḭƗɨɨ̆ᵻᶖİiIıɪIi]',
453
- 'j': '[jȷĴĵɈɉʝɟʲ]',
454
- 'k': '[kƘƙꝀꝁḰḱǨǩḲḳḴḵκϰ₭]',
455
- 'l': '[lŁłĽľĻļĹĺḶḷḸḹḼḽḺḻĿŀȽƚⱠⱡⱢɫɬᶅɭȴʟLl]',
456
- 'n': '[nŃńǸǹŇňÑñṄṅŅņṆṇṊṋṈṉN̈n̈ƝɲȠƞᵰᶇɳȵɴNnŊŋ]',
457
- 'o': '[oØøÖöÓóÒòÔôǑǒŐőŎŏȮȯỌọƟɵƠơỎỏŌōÕõǪǫȌȍՕօ]',
458
- 'p': '[pṔṕṖṗⱣᵽƤƥᵱ]',
459
- 'q': '[qꝖꝗʠɊɋꝘꝙq̃]',
460
- 'r': '[rŔŕɌɍŘřŖŗṘṙȐȑȒȓṚṛⱤɽ]',
461
- 's': '[sŚśṠṡṢṣꞨꞩŜŝŠšŞşȘșS̈s̈]',
462
- 't': '[tŤťṪṫŢţṬṭƮʈȚțṰṱṮṯƬƭ]',
463
- 'u': '[uŬŭɄʉỤụÜüÚúÙùÛûǓǔŰűŬŭƯưỦủŪūŨũŲųȔȕ∪]',
464
- 'v': '[vṼṽṾṿƲʋꝞꝟⱱʋ]',
465
- 'w': '[wẂẃẀẁŴŵẄẅẆẇẈẉ]',
466
- 'x': '[xẌẍẊẋχ]',
467
- 'y': '[yÝýỲỳŶŷŸÿỸỹẎẏỴỵɎɏƳƴ]',
468
- 'z': '[zŹźẐẑŽžŻżẒẓẔẕƵƶ]'
469
- };
470
-
471
- var asciifold = (function() {
472
- var i, n, k, chunk;
473
- var foreignletters = '';
474
- var lookup = {};
475
- for (k in DIACRITICS) {
476
- if (DIACRITICS.hasOwnProperty(k)) {
477
- chunk = DIACRITICS[k].substring(2, DIACRITICS[k].length - 1);
478
- foreignletters += chunk;
479
- for (i = 0, n = chunk.length; i < n; i++) {
480
- lookup[chunk.charAt(i)] = k;
481
- }
482
- }
483
- }
484
- var regexp = new RegExp('[' + foreignletters + ']', 'g');
485
- return function(str) {
486
- return str.replace(regexp, function(foreignletter) {
487
- return lookup[foreignletter];
488
- }).toLowerCase();
489
- };
490
- })();
491
-
492
-
493
- // export
494
- // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
495
-
496
- return Sifter;
 
497
  }));
498
 
499
-
500
-
501
  /**
502
  * microplugin.js
503
  * Copyright (c) 2013 Brian Reavis & contributors
@@ -515,128 +514,129 @@
515
  */
516
 
517
  (function(root, factory) {
518
- if (typeof define === 'function' && define.amd) {
519
- define('microplugin', factory);
520
- } else if (typeof exports === 'object') {
521
- module.exports = factory();
522
- } else {
523
- root.MicroPlugin = factory();
524
- }
525
  }(this, function() {
526
- var MicroPlugin = {};
527
-
528
- MicroPlugin.mixin = function(Interface) {
529
- Interface.plugins = {};
530
-
531
- /**
532
- * Initializes the listed plugins (with options).
533
- * Acceptable formats:
534
- *
535
- * List (without options):
536
- * ['a', 'b', 'c']
537
- *
538
- * List (with options):
539
- * [{'name': 'a', options: {}}, {'name': 'b', options: {}}]
540
- *
541
- * Hash (with options):
542
- * {'a': { ... }, 'b': { ... }, 'c': { ... }}
543
- *
544
- * @param {mixed} plugins
545
- */
546
- Interface.prototype.initializePlugins = function(plugins) {
547
- var i, n, key;
548
- var self = this;
549
- var queue = [];
550
-
551
- self.plugins = {
552
- names : [],
553
- settings : {},
554
- requested : {},
555
- loaded : {}
556
- };
557
-
558
- if (utils.isArray(plugins)) {
559
- for (i = 0, n = plugins.length; i < n; i++) {
560
- if (typeof plugins[i] === 'string') {
561
- queue.push(plugins[i]);
562
- } else {
563
- self.plugins.settings[plugins[i].name] = plugins[i].options;
564
- queue.push(plugins[i].name);
565
- }
566
- }
567
- } else if (plugins) {
568
- for (key in plugins) {
569
- if (plugins.hasOwnProperty(key)) {
570
- self.plugins.settings[key] = plugins[key];
571
- queue.push(key);
572
- }
573
- }
574
- }
575
-
576
- while (queue.length) {
577
- self.require(queue.shift());
578
- }
579
- };
580
-
581
- Interface.prototype.loadPlugin = function(name) {
582
- var self = this;
583
- var plugins = self.plugins;
584
- var plugin = Interface.plugins[name];
585
-
586
- if (!Interface.plugins.hasOwnProperty(name)) {
587
- throw new Error('Unable to find "' + name + '" plugin');
588
- }
589
-
590
- plugins.requested[name] = true;
591
- plugins.loaded[name] = plugin.fn.apply(self, [self.plugins.settings[name] || {}]);
592
- plugins.names.push(name);
593
- };
594
-
595
- /**
596
- * Initializes a plugin.
597
- *
598
- * @param {string} name
599
- */
600
- Interface.prototype.require = function(name) {
601
- var self = this;
602
- var plugins = self.plugins;
603
-
604
- if (!self.plugins.loaded.hasOwnProperty(name)) {
605
- if (plugins.requested[name]) {
606
- throw new Error('Plugin has circular dependency ("' + name + '")');
607
- }
608
- self.loadPlugin(name);
609
- }
610
-
611
- return plugins.loaded[name];
612
- };
613
-
614
- /**
615
- * Registers a plugin.
616
- *
617
- * @param {string} name
618
- * @param {function} fn
619
- */
620
- Interface.define = function(name, fn) {
621
- Interface.plugins[name] = {
622
- 'name' : name,
623
- 'fn' : fn
624
- };
625
- };
626
- };
627
-
628
- var utils = {
629
- isArray: Array.isArray || function(vArg) {
630
- return Object.prototype.toString.call(vArg) === '[object Array]';
631
- }
632
- };
633
-
634
- return MicroPlugin;
635
  }));
636
 
637
  /**
638
- * selectize.js (v0.12.6)
639
  * Copyright (c) 2013–2015 Brian Reavis & contributors
 
640
  *
641
  * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this
642
  * file except in compliance with the License. You may obtain a copy of the License at:
@@ -648,2732 +648,2762 @@
648
  * governing permissions and limitations under the License.
649
  *
650
  * @author Brian Reavis <brian@thirdroute.com>
 
651
  */
652
 
653
  /*jshint curly:false */
654
  /*jshint browser:true */
655
 
656
  (function(root, factory) {
657
- if (typeof define === 'function' && define.amd) {
658
- define('selectize', ['jquery','sifter','microplugin'], factory);
659
- } else if (typeof exports === 'object') {
660
- module.exports = factory(require('jquery'), require('sifter'), require('microplugin'));
661
- } else {
662
- root.Selectize = factory(root.jQuery, root.Sifter, root.MicroPlugin);
663
- }
664
  }(this, function($, Sifter, MicroPlugin) {
665
- 'use strict';
666
-
667
- var highlight = function($element, pattern) {
668
- if (typeof pattern === 'string' && !pattern.length) return;
669
- var regex = (typeof pattern === 'string') ? new RegExp(pattern, 'i') : pattern;
670
-
671
- var highlight = function(node) {
672
- var skip = 0;
673
- // Wrap matching part of text node with highlighting <span>, e.g.
674
- // Soccer -> <span class="highlight">Soc</span>cer for regex = /soc/i
675
- if (node.nodeType === 3) {
676
- var pos = node.data.search(regex);
677
- if (pos >= 0 && node.data.length > 0) {
678
- var match = node.data.match(regex);
679
- var spannode = document.createElement('span');
680
- spannode.className = 'highlight';
681
- var middlebit = node.splitText(pos);
682
- var endbit = middlebit.splitText(match[0].length);
683
- var middleclone = middlebit.cloneNode(true);
684
- spannode.appendChild(middleclone);
685
- middlebit.parentNode.replaceChild(spannode, middlebit);
686
- skip = 1;
687
- }
688
- }
689
- // Recurse element node, looking for child text nodes to highlight, unless element
690
- // is childless, <script>, <style>, or already highlighted: <span class="hightlight">
691
- else if (node.nodeType === 1 && node.childNodes && !/(script|style)/i.test(node.tagName) && ( node.className !== 'highlight' || node.tagName !== 'SPAN' )) {
692
- for (var i = 0; i < node.childNodes.length; ++i) {
693
- i += highlight(node.childNodes[i]);
694
- }
695
- }
696
- return skip;
697
- };
698
-
699
- return $element.each(function() {
700
- highlight(this);
701
- });
702
- };
703
-
704
- /**
705
- * removeHighlight fn copied from highlight v5 and
706
- * edited to remove with() and pass js strict mode
707
- */
708
- $.fn.removeHighlight = function() {
709
- return this.find("span.highlight").each(function() {
710
- this.parentNode.firstChild.nodeName;
711
- var parent = this.parentNode;
712
- parent.replaceChild(this.firstChild, this);
713
- parent.normalize();
714
- }).end();
715
- };
716
-
717
-
718
- var MicroEvent = function() {};
719
- MicroEvent.prototype = {
720
- on: function(event, fct){
721
- this._events = this._events || {};
722
- this._events[event] = this._events[event] || [];
723
- this._events[event].push(fct);
724
- },
725
- off: function(event, fct){
726
- var n = arguments.length;
727
- if (n === 0) return delete this._events;
728
- if (n === 1) return delete this._events[event];
729
-
730
- this._events = this._events || {};
731
- if (event in this._events === false) return;
732
- this._events[event].splice(this._events[event].indexOf(fct), 1);
733
- },
734
- trigger: function(event /* , args... */){
735
- this._events = this._events || {};
736
- if (event in this._events === false) return;
737
- for (var i = 0; i < this._events[event].length; i++){
738
- this._events[event][i].apply(this, Array.prototype.slice.call(arguments, 1));
739
- }
740
- }
741
- };
742
-
743
- /**
744
- * Mixin will delegate all MicroEvent.js function in the destination object.
745
- *
746
- * - MicroEvent.mixin(Foobar) will make Foobar able to use MicroEvent
747
- *
748
- * @param {object} the object which will support MicroEvent
749
- */
750
- MicroEvent.mixin = function(destObject){
751
- var props = ['on', 'off', 'trigger'];
752
- for (var i = 0; i < props.length; i++){
753
- destObject.prototype[props[i]] = MicroEvent.prototype[props[i]];
754
- }
755
- };
756
-
757
- var IS_MAC = /Mac/.test(navigator.userAgent);
758
-
759
- var KEY_A = 65;
760
- var KEY_COMMA = 188;
761
- var KEY_RETURN = 13;
762
- var KEY_ESC = 27;
763
- var KEY_LEFT = 37;
764
- var KEY_UP = 38;
765
- var KEY_P = 80;
766
- var KEY_RIGHT = 39;
767
- var KEY_DOWN = 40;
768
- var KEY_N = 78;
769
- var KEY_BACKSPACE = 8;
770
- var KEY_DELETE = 46;
771
- var KEY_SHIFT = 16;
772
- var KEY_CMD = IS_MAC ? 91 : 17;
773
- var KEY_CTRL = IS_MAC ? 18 : 17;
774
- var KEY_TAB = 9;
775
-
776
- var TAG_SELECT = 1;
777
- var TAG_INPUT = 2;
778
-
779
- // for now, android support in general is too spotty to support validity
780
- var SUPPORTS_VALIDITY_API = !/android/i.test(window.navigator.userAgent) && !!document.createElement('input').validity;
781
-
782
-
783
- var isset = function(object) {
784
- return typeof object !== 'undefined';
785
- };
786
-
787
- /**
788
- * Converts a scalar to its best string representation
789
- * for hash keys and HTML attribute values.
790
- *
791
- * Transformations:
792
- * 'str' -> 'str'
793
- * null -> ''
794
- * undefined -> ''
795
- * true -> '1'
796
- * false -> '0'
797
- * 0 -> '0'
798
- * 1 -> '1'
799
- *
800
- * @param {string} value
801
- * @returns {string|null}
802
- */
803
- var hash_key = function(value) {
804
- if (typeof value === 'undefined' || value === null) return null;
805
- if (typeof value === 'boolean') return value ? '1' : '0';
806
- return value + '';
807
- };
808
-
809
- /**
810
- * Escapes a string for use within HTML.
811
- *
812
- * @param {string} str
813
- * @returns {string}
814
- */
815
- var escape_html = function(str) {
816
- return (str + '')
817
- .replace(/&/g, '&amp;')
818
- .replace(/</g, '&lt;')
819
- .replace(/>/g, '&gt;')
820
- .replace(/"/g, '&quot;');
821
- };
822
-
823
- /**
824
- * Escapes "$" characters in replacement strings.
825
- *
826
- * @param {string} str
827
- * @returns {string}
828
- */
829
- var escape_replace = function(str) {
830
- return (str + '').replace(/\$/g, '$$$$');
831
- };
832
-
833
- var hook = {};
834
-
835
- /**
836
- * Wraps `method` on `self` so that `fn`
837
- * is invoked before the original method.
838
- *
839
- * @param {object} self
840
- * @param {string} method
841
- * @param {function} fn
842
- */
843
- hook.before = function(self, method, fn) {
844
- var original = self[method];
845
- self[method] = function() {
846
- fn.apply(self, arguments);
847
- return original.apply(self, arguments);
848
- };
849
- };
850
-
851
- /**
852
- * Wraps `method` on `self` so that `fn`
853
- * is invoked after the original method.
854
- *
855
- * @param {object} self
856
- * @param {string} method
857
- * @param {function} fn
858
- */
859
- hook.after = function(self, method, fn) {
860
- var original = self[method];
861
- self[method] = function() {
862
- var result = original.apply(self, arguments);
863
- fn.apply(self, arguments);
864
- return result;
865
- };
866
- };
867
-
868
- /**
869
- * Wraps `fn` so that it can only be invoked once.
870
- *
871
- * @param {function} fn
872
- * @returns {function}
873
- */
874
- var once = function(fn) {
875
- var called = false;
876
- return function() {
877
- if (called) return;
878
- called = true;
879
- fn.apply(this, arguments);
880
- };
881
- };
882
-
883
- /**
884
- * Wraps `fn` so that it can only be called once
885
- * every `delay` milliseconds (invoked on the falling edge).
886
- *
887
- * @param {function} fn
888
- * @param {int} delay
889
- * @returns {function}
890
- */
891
- var debounce = function(fn, delay) {
892
- var timeout;
893
- return function() {
894
- var self = this;
895
- var args = arguments;
896
- window.clearTimeout(timeout);
897
- timeout = window.setTimeout(function() {
898
- fn.apply(self, args);
899
- }, delay);
900
- };
901
- };
902
-
903
- /**
904
- * Debounce all fired events types listed in `types`
905
- * while executing the provided `fn`.
906
- *
907
- * @param {object} self
908
- * @param {array} types
909
- * @param {function} fn
910
- */
911
- var debounce_events = function(self, types, fn) {
912
- var type;
913
- var trigger = self.trigger;
914
- var event_args = {};
915
-
916
- // override trigger method
917
- self.trigger = function() {
918
- var type = arguments[0];
919
- if (types.indexOf(type) !== -1) {
920
- event_args[type] = arguments;
921
- } else {
922
- return trigger.apply(self, arguments);
923
- }
924
- };
925
-
926
- // invoke provided function
927
- fn.apply(self, []);
928
- self.trigger = trigger;
929
-
930
- // trigger queued events
931
- for (type in event_args) {
932
- if (event_args.hasOwnProperty(type)) {
933
- trigger.apply(self, event_args[type]);
934
- }
935
- }
936
- };
937
-
938
- /**
939
- * A workaround for http://bugs.jquery.com/ticket/6696
940
- *
941
- * @param {object} $parent - Parent element to listen on.
942
- * @param {string} event - Event name.
943
- * @param {string} selector - Descendant selector to filter by.
944
- * @param {function} fn - Event handler.
945
- */
946
- var watchChildEvent = function($parent, event, selector, fn) {
947
- $parent.on(event, selector, function(e) {
948
- var child = e.target;
949
- while (child && child.parentNode !== $parent[0]) {
950
- child = child.parentNode;
951
- }
952
- e.currentTarget = child;
953
- return fn.apply(this, [e]);
954
- });
955
- };
956
-
957
- /**
958
- * Determines the current selection within a text input control.
959
- * Returns an object containing:
960
- * - start
961
- * - length
962
- *
963
- * @param {object} input
964
- * @returns {object}
965
- */
966
- var getSelection = function(input) {
967
- var result = {};
968
- if ('selectionStart' in input) {
969
- result.start = input.selectionStart;
970
- result.length = input.selectionEnd - result.start;
971
- } else if (document.selection) {
972
- input.focus();
973
- var sel = document.selection.createRange();
974
- var selLen = document.selection.createRange().text.length;
975
- sel.moveStart('character', -input.value.length);
976
- result.start = sel.text.length - selLen;
977
- result.length = selLen;
978
- }
979
- return result;
980
- };
981
-
982
- /**
983
- * Copies CSS properties from one element to another.
984
- *
985
- * @param {object} $from
986
- * @param {object} $to
987
- * @param {array} properties
988
- */
989
- var transferStyles = function($from, $to, properties) {
990
- var i, n, styles = {};
991
- if (properties) {
992
- for (i = 0, n = properties.length; i < n; i++) {
993
- styles[properties[i]] = $from.css(properties[i]);
994
- }
995
- } else {
996
- styles = $from.css();
997
- }
998
- $to.css(styles);
999
- };
1000
-
1001
- /**
1002
- * Measures the width of a string within a
1003
- * parent element (in pixels).
1004
- *
1005
- * @param {string} str
1006
- * @param {object} $parent
1007
- * @returns {int}
1008
- */
1009
- var measureString = function(str, $parent) {
1010
- if (!str) {
1011
- return 0;
1012
- }
1013
-
1014
- if (!Selectize.$testInput) {
1015
- Selectize.$testInput = $('<span />').css({
1016
- position: 'absolute',
1017
- top: -99999,
1018
- left: -99999,
1019
- width: 'auto',
1020
- padding: 0,
1021
- whiteSpace: 'pre'
1022
- }).appendTo('body');
1023
- }
1024
-
1025
- Selectize.$testInput.text(str);
1026
-
1027
- transferStyles($parent, Selectize.$testInput, [
1028
- 'letterSpacing',
1029
- 'fontSize',
1030
- 'fontFamily',
1031
- 'fontWeight',
1032
- 'textTransform'
1033
- ]);
1034
-
1035
- return Selectize.$testInput.width();
1036
- };
1037
-
1038
- /**
1039
- * Sets up an input to grow horizontally as the user
1040
- * types. If the value is changed manually, you can
1041
- * trigger the "update" handler to resize:
1042
- *
1043
- * $input.trigger('update');
1044
- *
1045
- * @param {object} $input
1046
- */
1047
- var autoGrow = function($input) {
1048
- var currentWidth = null;
1049
-
1050
- var update = function(e, options) {
1051
- var value, keyCode, printable, placeholder, width;
1052
- var shift, character, selection;
1053
- e = e || window.event || {};
1054
- options = options || {};
1055
-
1056
- if (e.metaKey || e.altKey) return;
1057
- if (!options.force && $input.data('grow') === false) return;
1058
-
1059
- value = $input.val();
1060
- if (e.type && e.type.toLowerCase() === 'keydown') {
1061
- keyCode = e.keyCode;
1062
- printable = (
1063
- (keyCode >= 48 && keyCode <= 57) || // 0-9
1064
- (keyCode >= 65 && keyCode <= 90) || // a-z
1065
- (keyCode >= 96 && keyCode <= 111) || // numpad 0-9, numeric operators
1066
- (keyCode >= 186 && keyCode <= 222) || // semicolon, equal, comma, dash, etc.
1067
- keyCode === 32 // space
1068
- );
1069
-
1070
- if (keyCode === KEY_DELETE || keyCode === KEY_BACKSPACE) {
1071
- selection = getSelection($input[0]);
1072
- if (selection.length) {
1073
- value = value.substring(0, selection.start) + value.substring(selection.start + selection.length);
1074
- } else if (keyCode === KEY_BACKSPACE && selection.start) {
1075
- value = value.substring(0, selection.start - 1) + value.substring(selection.start + 1);
1076
- } else if (keyCode === KEY_DELETE && typeof selection.start !== 'undefined') {
1077
- value = value.substring(0, selection.start) + value.substring(selection.start + 1);
1078
- }
1079
- } else if (printable) {
1080
- shift = e.shiftKey;
1081
- character = String.fromCharCode(e.keyCode);
1082
- if (shift) character = character.toUpperCase();
1083
- else character = character.toLowerCase();
1084
- value += character;
1085
- }
1086
- }
1087
-
1088
- placeholder = $input.attr('placeholder');
1089
- if (!value && placeholder) {
1090
- value = placeholder;
1091
- }
1092
-
1093
- width = measureString(value, $input) + 4;
1094
- if (width !== currentWidth) {
1095
- currentWidth = width;
1096
- $input.width(width);
1097
- $input.triggerHandler('resize');
1098
- }
1099
- };
1100
-
1101
- $input.on('keydown keyup update blur', update);
1102
- update();
1103
- };
1104
-
1105
- var domToString = function(d) {
1106
- var tmp = document.createElement('div');
1107
-
1108
- tmp.appendChild(d.cloneNode(true));
1109
-
1110
- return tmp.innerHTML;
1111
- };
1112
-
1113
- var logError = function(message, options){
1114
- if(!options) options = {};
1115
- var component = "Selectize";
1116
-
1117
- console.error(component + ": " + message)
1118
-
1119
- if(options.explanation){
1120
- // console.group is undefined in <IE11
1121
- if(console.group) console.group();
1122
- console.error(options.explanation);
1123
- if(console.group) console.groupEnd();
1124
- }
1125
- }
1126
-
1127
-
1128
- var Selectize = function($input, settings) {
1129
- var key, i, n, dir, input, self = this;
1130
- input = $input[0];
1131
- input.selectize = self;
1132
-
1133
- // detect rtl environment
1134
- var computedStyle = window.getComputedStyle && window.getComputedStyle(input, null);
1135
- dir = computedStyle ? computedStyle.getPropertyValue('direction') : input.currentStyle && input.currentStyle.direction;
1136
- dir = dir || $input.parents('[dir]:first').attr('dir') || '';
1137
-
1138
- // setup default state
1139
- $.extend(self, {
1140
- order : 0,
1141
- settings : settings,
1142
- $input : $input,
1143
- tabIndex : $input.attr('tabindex') || '',
1144
- tagType : input.tagName.toLowerCase() === 'select' ? TAG_SELECT : TAG_INPUT,
1145
- rtl : /rtl/i.test(dir),
1146
-
1147
- eventNS : '.selectize' + (++Selectize.count),
1148
- highlightedValue : null,
1149
- isBlurring : false,
1150
- isOpen : false,
1151
- isDisabled : false,
1152
- isRequired : $input.is('[required]'),
1153
- isInvalid : false,
1154
- isLocked : false,
1155
- isFocused : false,
1156
- isInputHidden : false,
1157
- isSetup : false,
1158
- isShiftDown : false,
1159
- isCmdDown : false,
1160
- isCtrlDown : false,
1161
- ignoreFocus : false,
1162
- ignoreBlur : false,
1163
- ignoreHover : false,
1164
- hasOptions : false,
1165
- currentResults : null,
1166
- lastValue : '',
1167
- caretPos : 0,
1168
- loading : 0,
1169
- loadedSearches : {},
1170
-
1171
- $activeOption : null,
1172
- $activeItems : [],
1173
-
1174
- optgroups : {},
1175
- options : {},
1176
- userOptions : {},
1177
- items : [],
1178
- renderCache : {},
1179
- onSearchChange : settings.loadThrottle === null ? self.onSearchChange : debounce(self.onSearchChange, settings.loadThrottle)
1180
- });
1181
-
1182
- // search system
1183
- self.sifter = new Sifter(this.options, {diacritics: settings.diacritics});
1184
-
1185
- // build options table
1186
- if (self.settings.options) {
1187
- for (i = 0, n = self.settings.options.length; i < n; i++) {
1188
- self.registerOption(self.settings.options[i]);
1189
- }
1190
- delete self.settings.options;
1191
- }
1192
-
1193
- // build optgroup table
1194
- if (self.settings.optgroups) {
1195
- for (i = 0, n = self.settings.optgroups.length; i < n; i++) {
1196
- self.registerOptionGroup(self.settings.optgroups[i]);
1197
- }
1198
- delete self.settings.optgroups;
1199
- }
1200
-
1201
- // option-dependent defaults
1202
- self.settings.mode = self.settings.mode || (self.settings.maxItems === 1 ? 'single' : 'multi');
1203
- if (typeof self.settings.hideSelected !== 'boolean') {
1204
- self.settings.hideSelected = self.settings.mode === 'multi';
1205
- }
1206
-
1207
- self.initializePlugins(self.settings.plugins);
1208
- self.setupCallbacks();
1209
- self.setupTemplates();
1210
- self.setup();
1211
- };
1212
-
1213
- // mixins
1214
- // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1215
-
1216
- MicroEvent.mixin(Selectize);
1217
-
1218
- if(typeof MicroPlugin !== "undefined"){
1219
- MicroPlugin.mixin(Selectize);
1220
- }else{
1221
- logError("Dependency MicroPlugin is missing",
1222
- {explanation:
1223
- "Make sure you either: (1) are using the \"standalone\" "+
1224
- "version of Selectize, or (2) require MicroPlugin before you "+
1225
- "load Selectize."}
1226
- );
1227
- }
1228
-
1229
-
1230
- // methods
1231
- // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1232
-
1233
- $.extend(Selectize.prototype, {
1234
-
1235
- /**
1236
- * Creates all elements and sets up event bindings.
1237
- */
1238
- setup: function() {
1239
- var self = this;
1240
- var settings = self.settings;
1241
- var eventNS = self.eventNS;
1242
- var $window = $(window);
1243
- var $document = $(document);
1244
- var $input = self.$input;
1245
-
1246
- var $wrapper;
1247
- var $control;
1248
- var $control_input;
1249
- var $dropdown;
1250
- var $dropdown_content;
1251
- var $dropdown_parent;
1252
- var inputMode;
1253
- var timeout_blur;
1254
- var timeout_focus;
1255
- var classes;
1256
- var classes_plugins;
1257
- var inputId;
1258
-
1259
- inputMode = self.settings.mode;
1260
- classes = $input.attr('class') || '';
1261
-
1262
- $wrapper = $('<div>').addClass(settings.wrapperClass).addClass(classes).addClass(inputMode);
1263
- $control = $('<div>').addClass(settings.inputClass).addClass('items').appendTo($wrapper);
1264
- $control_input = $('<input type="text" autocomplete="off" />').appendTo($control).attr('tabindex', $input.is(':disabled') ? '-1' : self.tabIndex);
1265
- $dropdown_parent = $(settings.dropdownParent || $wrapper);
1266
- $dropdown = $('<div>').addClass(settings.dropdownClass).addClass(inputMode).hide().appendTo($dropdown_parent);
1267
- $dropdown_content = $('<div>').addClass(settings.dropdownContentClass).appendTo($dropdown);
1268
-
1269
- if(inputId = $input.attr('id')) {
1270
- $control_input.attr('id', inputId + '-selectized');
1271
- $("label[for='"+inputId+"']").attr('for', inputId + '-selectized');
1272
- }
1273
-
1274
- if(self.settings.copyClassesToDropdown) {
1275
- $dropdown.addClass(classes);
1276
- }
1277
-
1278
- $wrapper.css({
1279
- width: $input[0].style.width
1280
- });
1281
-
1282
- if (self.plugins.names.length) {
1283
- classes_plugins = 'plugin-' + self.plugins.names.join(' plugin-');
1284
- $wrapper.addClass(classes_plugins);
1285
- $dropdown.addClass(classes_plugins);
1286
- }
1287
-
1288
- if ((settings.maxItems === null || settings.maxItems > 1) && self.tagType === TAG_SELECT) {
1289
- $input.attr('multiple', 'multiple');
1290
- }
1291
-
1292
- if (self.settings.placeholder) {
1293
- $control_input.attr('placeholder', settings.placeholder);
1294
- }
1295
-
1296
- // if splitOn was not passed in, construct it from the delimiter to allow pasting universally
1297
- if (!self.settings.splitOn && self.settings.delimiter) {
1298
- var delimiterEscaped = self.settings.delimiter.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&');
1299
- self.settings.splitOn = new RegExp('\\s*' + delimiterEscaped + '+\\s*');
1300
- }
1301
-
1302
- if ($input.attr('autocorrect')) {
1303
- $control_input.attr('autocorrect', $input.attr('autocorrect'));
1304
- }
1305
-
1306
- if ($input.attr('autocapitalize')) {
1307
- $control_input.attr('autocapitalize', $input.attr('autocapitalize'));
1308
- }
1309
- $control_input[0].type = $input[0].type;
1310
-
1311
- self.$wrapper = $wrapper;
1312
- self.$control = $control;
1313
- self.$control_input = $control_input;
1314
- self.$dropdown = $dropdown;
1315
- self.$dropdown_content = $dropdown_content;
1316
-
1317
- $dropdown.on('mouseenter mousedown click', '[data-disabled]>[data-selectable]', function(e) { e.stopImmediatePropagation(); });
1318
- $dropdown.on('mouseenter', '[data-selectable]', function() { return self.onOptionHover.apply(self, arguments); });
1319
- $dropdown.on('mousedown click', '[data-selectable]', function() { return self.onOptionSelect.apply(self, arguments); });
1320
- watchChildEvent($control, 'mousedown', '*:not(input)', function() { return self.onItemSelect.apply(self, arguments); });
1321
- autoGrow($control_input);
1322
-
1323
- $control.on({
1324
- mousedown : function() { return self.onMouseDown.apply(self, arguments); },
1325
- click : function() { return self.onClick.apply(self, arguments); }
1326
- });
1327
-
1328
- $control_input.on({
1329
- mousedown : function(e) { e.stopPropagation(); },
1330
- keydown : function() { return self.onKeyDown.apply(self, arguments); },
1331
- keyup : function() { return self.onKeyUp.apply(self, arguments); },
1332
- keypress : function() { return self.onKeyPress.apply(self, arguments); },
1333
- resize : function() { self.positionDropdown.apply(self, []); },
1334
- blur : function() { return self.onBlur.apply(self, arguments); },
1335
- focus : function() { self.ignoreBlur = false; return self.onFocus.apply(self, arguments); },
1336
- paste : function() { return self.onPaste.apply(self, arguments); }
1337
- });
1338
-
1339
- $document.on('keydown' + eventNS, function(e) {
1340
- self.isCmdDown = e[IS_MAC ? 'metaKey' : 'ctrlKey'];
1341
- self.isCtrlDown = e[IS_MAC ? 'altKey' : 'ctrlKey'];
1342
- self.isShiftDown = e.shiftKey;
1343
- });
1344
-
1345
- $document.on('keyup' + eventNS, function(e) {
1346
- if (e.keyCode === KEY_CTRL) self.isCtrlDown = false;
1347
- if (e.keyCode === KEY_SHIFT) self.isShiftDown = false;
1348
- if (e.keyCode === KEY_CMD) self.isCmdDown = false;
1349
- });
1350
-
1351
- $document.on('mousedown' + eventNS, function(e) {
1352
- if (self.isFocused) {
1353
- // prevent events on the dropdown scrollbar from causing the control to blur
1354
- if (e.target === self.$dropdown[0] || e.target.parentNode === self.$dropdown[0]) {
1355
- return false;
1356
- }
1357
- // blur on click outside
1358
- if (!self.$control.has(e.target).length && e.target !== self.$control[0]) {
1359
- self.blur(e.target);
1360
- }
1361
- }
1362
- });
1363
-
1364
- $window.on(['scroll' + eventNS, 'resize' + eventNS].join(' '), function() {
1365
- if (self.isOpen) {
1366
- self.positionDropdown.apply(self, arguments);
1367
- }
1368
- });
1369
- $window.on('mousemove' + eventNS, function() {
1370
- self.ignoreHover = false;
1371
- });
1372
-
1373
- // store original children and tab index so that they can be
1374
- // restored when the destroy() method is called.
1375
- this.revertSettings = {
1376
- $children : $input.children().detach(),
1377
- tabindex : $input.attr('tabindex')
1378
- };
1379
-
1380
- $input.attr('tabindex', -1).hide().after(self.$wrapper);
1381
-
1382
- if ($.isArray(settings.items)) {
1383
- self.setValue(settings.items);
1384
- delete settings.items;
1385
- }
1386
-
1387
- // feature detect for the validation API
1388
- if (SUPPORTS_VALIDITY_API) {
1389
- $input.on('invalid' + eventNS, function(e) {
1390
- e.preventDefault();
1391
- self.isInvalid = true;
1392
- self.refreshState();
1393
- });
1394
- }
1395
-
1396
- self.updateOriginalInput();
1397
- self.refreshItems();
1398
- self.refreshState();
1399
- self.updatePlaceholder();
1400
- self.isSetup = true;
1401
-
1402
- if ($input.is(':disabled')) {
1403
- self.disable();
1404
- }
1405
-
1406
- self.on('change', this.onChange);
1407
-
1408
- $input.data('selectize', self);
1409
- $input.addClass('selectized');
1410
- self.trigger('initialize');
1411
-
1412
- // preload options
1413
- if (settings.preload === true) {
1414
- self.onSearchChange('');
1415
- }
1416
-
1417
- },
1418
-
1419
- /**
1420
- * Sets up default rendering functions.
1421
- */
1422
- setupTemplates: function() {
1423
- var self = this;
1424
- var field_label = self.settings.labelField;
1425
- var field_optgroup = self.settings.optgroupLabelField;
1426
-
1427
- var templates = {
1428
- 'optgroup': function(data) {
1429
- return '<div class="optgroup">' + data.html + '</div>';
1430
- },
1431
- 'optgroup_header': function(data, escape) {
1432
- return '<div class="optgroup-header">' + escape(data[field_optgroup]) + '</div>';
1433
- },
1434
- 'option': function(data, escape) {
1435
- return '<div class="option">' + escape(data[field_label]) + '</div>';
1436
- },
1437
- 'item': function(data, escape) {
1438
- return '<div class="item">' + escape(data[field_label]) + '</div>';
1439
- },
1440
- 'option_create': function(data, escape) {
1441
- return '<div class="create">Add <strong>' + escape(data.input) + '</strong>&hellip;</div>';
1442
- }
1443
- };
1444
-
1445
- self.settings.render = $.extend({}, templates, self.settings.render);
1446
- },
1447
-
1448
- /**
1449
- * Maps fired events to callbacks provided
1450
- * in the settings used when creating the control.
1451
- */
1452
- setupCallbacks: function() {
1453
- var key, fn, callbacks = {
1454
- 'initialize' : 'onInitialize',
1455
- 'change' : 'onChange',
1456
- 'item_add' : 'onItemAdd',
1457
- 'item_remove' : 'onItemRemove',
1458
- 'clear' : 'onClear',
1459
- 'option_add' : 'onOptionAdd',
1460
- 'option_remove' : 'onOptionRemove',
1461
- 'option_clear' : 'onOptionClear',
1462
- 'optgroup_add' : 'onOptionGroupAdd',
1463
- 'optgroup_remove' : 'onOptionGroupRemove',
1464
- 'optgroup_clear' : 'onOptionGroupClear',
1465
- 'dropdown_open' : 'onDropdownOpen',
1466
- 'dropdown_close' : 'onDropdownClose',
1467
- 'type' : 'onType',
1468
- 'load' : 'onLoad',
1469
- 'focus' : 'onFocus',
1470
- 'blur' : 'onBlur'
1471
- };
1472
-
1473
- for (key in callbacks) {
1474
- if (callbacks.hasOwnProperty(key)) {
1475
- fn = this.settings[callbacks[key]];
1476
- if (fn) this.on(key, fn);
1477
- }
1478
- }
1479
- },
1480
-
1481
- /**
1482
- * Triggered when the main control element
1483
- * has a click event.
1484
- *
1485
- * @param {object} e
1486
- * @return {boolean}
1487
- */
1488
- onClick: function(e) {
1489
- var self = this;
1490
-
1491
- // necessary for mobile webkit devices (manual focus triggering
1492
- // is ignored unless invoked within a click event)
1493
- // also necessary to reopen a dropdown that has been closed by
1494
- // closeAfterSelect
1495
- if (!self.isFocused || !self.isOpen) {
1496
- self.focus();
1497
- e.preventDefault();
1498
- }
1499
- },
1500
-
1501
- /**
1502
- * Triggered when the main control element
1503
- * has a mouse down event.
1504
- *
1505
- * @param {object} e
1506
- * @return {boolean}
1507
- */
1508
- onMouseDown: function(e) {
1509
- var self = this;
1510
- var defaultPrevented = e.isDefaultPrevented();
1511
- var $target = $(e.target);
1512
-
1513
- if (self.isFocused) {
1514
- // retain focus by preventing native handling. if the
1515
- // event target is the input it should not be modified.
1516
-