Version Description
- Updated Bootstrap Multiselect to version 1.1.1, fixing issues with the accessibility of backend multiselect dropdowns for blind users.
- New: Inputs with errors will now add the aria-describedby attribute during JavaScript validation for more accessible errors.
- New: Form errors will now always include the role="alert" attribute for more accessible errors. New fields will now also include role="alert" in custom field HTML.
- New: Added a new frm_entries_column_value filter hook.
Download this release
Release Info
Developer | formidableforms |
Plugin | Formidable Forms – Form Builder for WordPress |
Version | 5.1 |
Comparing to | |
See all releases |
Code changes from version 5.0.17 to 5.1
- classes/controllers/FrmAppController.php +1 -1
- classes/controllers/FrmFieldsController.php +2 -0
- classes/controllers/FrmFormsController.php +1 -1
- classes/helpers/FrmAppHelper.php +4 -2
- classes/helpers/FrmEntriesListHelper.php +10 -0
- classes/models/FrmAntiSpam.php +11 -11
- classes/models/FrmFieldFormHtml.php +30 -0
- classes/models/fields/FrmFieldType.php +1 -1
- classes/views/frm-fields/front-end/combo-field/combo-field.php +1 -1
- classes/views/frm-forms/form.php +0 -1
- classes/views/frm-forms/multiselect-accessibility.php +1 -6
- classes/views/frm-forms/settings.php +0 -3
- classes/views/frm-settings/permissions.php +1 -4
- css/frm_admin.css +12 -45
- formidable.php +1 -1
- js/bootstrap-multiselect.js +585 -335
- js/formidable.js +3 -1
- js/formidable.min.js +25 -24
- js/formidable_admin.js +35 -6
- languages/formidable.pot +10 -22
- readme.txt +8 -11
classes/controllers/FrmAppController.php
CHANGED
@@ -460,7 +460,7 @@ class FrmAppController {
|
|
460 |
|
461 |
// load multselect js
|
462 |
$depends_on = array( 'jquery', 'bootstrap_tooltip' );
|
463 |
-
wp_register_script( 'bootstrap-multiselect', FrmAppHelper::plugin_url() . '/js/bootstrap-multiselect.js', $depends_on, '
|
464 |
|
465 |
$page = FrmAppHelper::simple_get( 'page', 'sanitize_title' );
|
466 |
$post_type = FrmAppHelper::simple_get( 'post_type', 'sanitize_title' );
|
460 |
|
461 |
// load multselect js
|
462 |
$depends_on = array( 'jquery', 'bootstrap_tooltip' );
|
463 |
+
wp_register_script( 'bootstrap-multiselect', FrmAppHelper::plugin_url() . '/js/bootstrap-multiselect.js', $depends_on, '1.1.1', true );
|
464 |
|
465 |
$page = FrmAppHelper::simple_get( 'page', 'sanitize_title' );
|
466 |
$post_type = FrmAppHelper::simple_get( 'post_type', 'sanitize_title' );
|
classes/controllers/FrmFieldsController.php
CHANGED
@@ -743,7 +743,9 @@ class FrmFieldsController {
|
|
743 |
$error_body = substr( $custom_html, $start + 10, $end - $start - 10 );
|
744 |
$default_html = array(
|
745 |
'<div class="frm_error" id="frm_error_field_[key]">[error]</div>',
|
|
|
746 |
'<div class="frm_error">[error]</div>',
|
|
|
747 |
);
|
748 |
|
749 |
if ( in_array( $error_body, $default_html, true ) ) {
|
743 |
$error_body = substr( $custom_html, $start + 10, $end - $start - 10 );
|
744 |
$default_html = array(
|
745 |
'<div class="frm_error" id="frm_error_field_[key]">[error]</div>',
|
746 |
+
'<div class="frm_error" role="alert" id="frm_error_field_[key]">[error]</div>',
|
747 |
'<div class="frm_error">[error]</div>',
|
748 |
+
'<div class="frm_error" role="alert">[error]</div>',
|
749 |
);
|
750 |
|
751 |
if ( in_array( $error_body, $default_html, true ) ) {
|
classes/controllers/FrmFormsController.php
CHANGED
@@ -685,7 +685,7 @@ class FrmFormsController {
|
|
685 |
/**
|
686 |
* Check the page being loaded, determine if this is a page that should include the form popup.
|
687 |
*
|
688 |
-
* @since
|
689 |
*
|
690 |
* @return bool
|
691 |
*/
|
685 |
/**
|
686 |
* Check the page being loaded, determine if this is a page that should include the form popup.
|
687 |
*
|
688 |
+
* @since 5.0.14
|
689 |
*
|
690 |
* @return bool
|
691 |
*/
|
classes/helpers/FrmAppHelper.php
CHANGED
@@ -11,7 +11,7 @@ class FrmAppHelper {
|
|
11 |
/**
|
12 |
* @since 2.0
|
13 |
*/
|
14 |
-
public static $plug_version = '5.
|
15 |
|
16 |
/**
|
17 |
* @since 1.07.02
|
@@ -2934,9 +2934,11 @@ class FrmAppHelper {
|
|
2934 |
|
2935 |
/**
|
2936 |
* Output HTML containing reference text for accessibility
|
|
|
|
|
2937 |
*/
|
2938 |
public static function multiselect_accessibility() {
|
2939 |
-
|
2940 |
}
|
2941 |
|
2942 |
public static function get_menu_icon_class() {
|
11 |
/**
|
12 |
* @since 2.0
|
13 |
*/
|
14 |
+
public static $plug_version = '5.1';
|
15 |
|
16 |
/**
|
17 |
* @since 1.07.02
|
2934 |
|
2935 |
/**
|
2936 |
* Output HTML containing reference text for accessibility
|
2937 |
+
*
|
2938 |
+
* @deprecated 5.1
|
2939 |
*/
|
2940 |
public static function multiselect_accessibility() {
|
2941 |
+
_deprecated_function( __METHOD__, '5.1' );
|
2942 |
}
|
2943 |
|
2944 |
public static function get_menu_icon_class() {
|
classes/helpers/FrmEntriesListHelper.php
CHANGED
@@ -291,6 +291,16 @@ class FrmEntriesListHelper extends FrmListHelper {
|
|
291 |
if ( $val === false ) {
|
292 |
$this->get_column_value( $item, $val );
|
293 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
294 |
}
|
295 |
|
296 |
return $val;
|
291 |
if ( $val === false ) {
|
292 |
$this->get_column_value( $item, $val );
|
293 |
}
|
294 |
+
|
295 |
+
/**
|
296 |
+
* Allows changing entries list column value.
|
297 |
+
*
|
298 |
+
* @since 5.1
|
299 |
+
*
|
300 |
+
* @param mixed $val Column value.
|
301 |
+
* @param array $args Contains `item` and `col_name`.
|
302 |
+
*/
|
303 |
+
$val = apply_filters( 'frm_entries_column_value', $val, compact( 'item', 'col_name' ) );
|
304 |
}
|
305 |
|
306 |
return $val;
|
classes/models/FrmAntiSpam.php
CHANGED
@@ -8,7 +8,7 @@ if ( ! defined( 'ABSPATH' ) ) {
|
|
8 |
*
|
9 |
* This token class generates tokens that are used in our Anti-Spam checking.
|
10 |
*
|
11 |
-
* @since
|
12 |
*/
|
13 |
class FrmAntiSpam extends FrmValidate {
|
14 |
|
@@ -32,7 +32,7 @@ class FrmAntiSpam extends FrmValidate {
|
|
32 |
/**
|
33 |
* Initialise the actions for the Anti-spam.
|
34 |
*
|
35 |
-
* @since
|
36 |
*/
|
37 |
public function init() {
|
38 |
add_filter( 'frm_form_attributes', array( $this, 'add_token_to_form' ), 10, 1 );
|
@@ -42,7 +42,7 @@ class FrmAntiSpam extends FrmValidate {
|
|
42 |
/**
|
43 |
* Return a valid token.
|
44 |
*
|
45 |
-
* @since
|
46 |
*
|
47 |
* @param mixed $current True to use current time, otherwise a timestamp string.
|
48 |
*
|
@@ -91,7 +91,7 @@ class FrmAntiSpam extends FrmValidate {
|
|
91 |
* 'frm_form_token_check_before_today'
|
92 |
* 'frm_form_token_check_after_today'
|
93 |
*
|
94 |
-
* @since
|
95 |
*
|
96 |
* @return array Array of all valid tokens to check against.
|
97 |
*/
|
@@ -143,7 +143,7 @@ class FrmAntiSpam extends FrmValidate {
|
|
143 |
* and frm_token_validity_in_days to extend the validation period).
|
144 |
* By default tokens are valid for day.
|
145 |
*
|
146 |
-
* @since
|
147 |
*
|
148 |
* @param string $token Token to validate.
|
149 |
*
|
@@ -157,7 +157,7 @@ class FrmAntiSpam extends FrmValidate {
|
|
157 |
/**
|
158 |
* Add the token field to the form.
|
159 |
*
|
160 |
-
* @since
|
161 |
*
|
162 |
* @param string $attributes
|
163 |
*
|
@@ -188,7 +188,7 @@ class FrmAntiSpam extends FrmValidate {
|
|
188 |
/**
|
189 |
* Validate Anti-spam if enabled.
|
190 |
*
|
191 |
-
* @since
|
192 |
*
|
193 |
* @return bool|string True or a string with the error.
|
194 |
*/
|
@@ -235,7 +235,7 @@ class FrmAntiSpam extends FrmValidate {
|
|
235 |
/**
|
236 |
* Helper to run our filter on all the responses for the antispam checks.
|
237 |
*
|
238 |
-
* @since
|
239 |
*
|
240 |
* @param bool|string $is_valid Is valid entry or not.
|
241 |
*
|
@@ -248,7 +248,7 @@ class FrmAntiSpam extends FrmValidate {
|
|
248 |
/**
|
249 |
* Helper to get the missing token message.
|
250 |
*
|
251 |
-
* @since
|
252 |
*
|
253 |
* @return string missing token message.
|
254 |
*/
|
@@ -259,7 +259,7 @@ class FrmAntiSpam extends FrmValidate {
|
|
259 |
/**
|
260 |
* Helper to get the invalid token message.
|
261 |
*
|
262 |
-
* @since
|
263 |
*
|
264 |
* @return string Invalid token message.
|
265 |
*/
|
@@ -270,7 +270,7 @@ class FrmAntiSpam extends FrmValidate {
|
|
270 |
/**
|
271 |
* If a user is a super admin, add a support link to the message.
|
272 |
*
|
273 |
-
* @since
|
274 |
*
|
275 |
* @return string Support text if super admin, empty string if not.
|
276 |
*/
|
8 |
*
|
9 |
* This token class generates tokens that are used in our Anti-Spam checking.
|
10 |
*
|
11 |
+
* @since 4.11
|
12 |
*/
|
13 |
class FrmAntiSpam extends FrmValidate {
|
14 |
|
32 |
/**
|
33 |
* Initialise the actions for the Anti-spam.
|
34 |
*
|
35 |
+
* @since 4.11
|
36 |
*/
|
37 |
public function init() {
|
38 |
add_filter( 'frm_form_attributes', array( $this, 'add_token_to_form' ), 10, 1 );
|
42 |
/**
|
43 |
* Return a valid token.
|
44 |
*
|
45 |
+
* @since 4.11
|
46 |
*
|
47 |
* @param mixed $current True to use current time, otherwise a timestamp string.
|
48 |
*
|
91 |
* 'frm_form_token_check_before_today'
|
92 |
* 'frm_form_token_check_after_today'
|
93 |
*
|
94 |
+
* @since 4.11
|
95 |
*
|
96 |
* @return array Array of all valid tokens to check against.
|
97 |
*/
|
143 |
* and frm_token_validity_in_days to extend the validation period).
|
144 |
* By default tokens are valid for day.
|
145 |
*
|
146 |
+
* @since 4.11
|
147 |
*
|
148 |
* @param string $token Token to validate.
|
149 |
*
|
157 |
/**
|
158 |
* Add the token field to the form.
|
159 |
*
|
160 |
+
* @since 4.11
|
161 |
*
|
162 |
* @param string $attributes
|
163 |
*
|
188 |
/**
|
189 |
* Validate Anti-spam if enabled.
|
190 |
*
|
191 |
+
* @since 4.11
|
192 |
*
|
193 |
* @return bool|string True or a string with the error.
|
194 |
*/
|
235 |
/**
|
236 |
* Helper to run our filter on all the responses for the antispam checks.
|
237 |
*
|
238 |
+
* @since 4.11
|
239 |
*
|
240 |
* @param bool|string $is_valid Is valid entry or not.
|
241 |
*
|
248 |
/**
|
249 |
* Helper to get the missing token message.
|
250 |
*
|
251 |
+
* @since 4.11
|
252 |
*
|
253 |
* @return string missing token message.
|
254 |
*/
|
259 |
/**
|
260 |
* Helper to get the invalid token message.
|
261 |
*
|
262 |
+
* @since 4.11
|
263 |
*
|
264 |
* @return string Invalid token message.
|
265 |
*/
|
270 |
/**
|
271 |
* If a user is a super admin, add a support link to the message.
|
272 |
*
|
273 |
+
* @since 4.11
|
274 |
*
|
275 |
* @return string Support text if super admin, empty string if not.
|
276 |
*/
|
classes/models/FrmFieldFormHtml.php
CHANGED
@@ -230,9 +230,39 @@ class FrmFieldFormHtml {
|
|
230 |
private function replace_error_shortcode() {
|
231 |
$this->maybe_add_error_id();
|
232 |
$error = isset( $this->pass_args['errors'][ 'field' . $this->field_id ] ) ? $this->pass_args['errors'][ 'field' . $this->field_id ] : false;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
233 |
FrmShortcodeHelper::remove_inline_conditions( ! empty( $error ), 'error', $error, $this->html );
|
234 |
}
|
235 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
236 |
/**
|
237 |
* Add an ID to the error message for aria-describedby.
|
238 |
* This ID was added to the HTML in v3.06.02.
|
230 |
private function replace_error_shortcode() {
|
231 |
$this->maybe_add_error_id();
|
232 |
$error = isset( $this->pass_args['errors'][ 'field' . $this->field_id ] ) ? $this->pass_args['errors'][ 'field' . $this->field_id ] : false;
|
233 |
+
|
234 |
+
if ( ! empty( $error ) && false === strpos( $this->html, 'role="alert"' ) ) {
|
235 |
+
$error_body = self::get_error_body( $this->html );
|
236 |
+
if ( is_string( $error_body ) && false === strpos( $error_body, 'role=' ) ) {
|
237 |
+
$new_error_body = preg_replace( '/class="frm_error/', 'role="alert" class="frm_error', $error_body, 1 );
|
238 |
+
$this->html = str_replace( '[if error]' . $error_body . '[/if error]', '[if error]' . $new_error_body . '[/if error]', $this->html );
|
239 |
+
}
|
240 |
+
}
|
241 |
+
|
242 |
FrmShortcodeHelper::remove_inline_conditions( ! empty( $error ), 'error', $error, $this->html );
|
243 |
}
|
244 |
|
245 |
+
/**
|
246 |
+
* Pull the HTML between [if error] and [/if error] shortcodes.
|
247 |
+
*
|
248 |
+
* @param string $html
|
249 |
+
* @return string|false
|
250 |
+
*/
|
251 |
+
private static function get_error_body( $html ) {
|
252 |
+
$start = strpos( $html, '[if error]' );
|
253 |
+
if ( false === $start ) {
|
254 |
+
return false;
|
255 |
+
}
|
256 |
+
|
257 |
+
$end = strpos( $html, '[/if error]', $start );
|
258 |
+
if ( false === $end ) {
|
259 |
+
return false;
|
260 |
+
}
|
261 |
+
|
262 |
+
$error_body = substr( $html, $start + 10, $end - $start - 10 );
|
263 |
+
return $error_body;
|
264 |
+
}
|
265 |
+
|
266 |
/**
|
267 |
* Add an ID to the error message for aria-describedby.
|
268 |
* This ID was added to the HTML in v3.06.02.
|
classes/models/fields/FrmFieldType.php
CHANGED
@@ -177,7 +177,7 @@ abstract class FrmFieldType {
|
|
177 |
</$label>
|
178 |
$input
|
179 |
[if description]<div class="frm_description" id="frm_desc_field_[key]">[description]</div>[/if description]
|
180 |
-
[if error]<div class="frm_error" id="frm_error_field_[key]">[error]</div>[/if error]
|
181 |
</div>
|
182 |
DEFAULT_HTML;
|
183 |
|
177 |
</$label>
|
178 |
$input
|
179 |
[if description]<div class="frm_description" id="frm_desc_field_[key]">[description]</div>[/if description]
|
180 |
+
[if error]<div class="frm_error" role="alert" id="frm_error_field_[key]">[error]</div>[/if error]
|
181 |
</div>
|
182 |
DEFAULT_HTML;
|
183 |
|
classes/views/frm-fields/front-end/combo-field/combo-field.php
CHANGED
@@ -80,7 +80,7 @@ $inputs_attrs = $this->get_inputs_container_attrs();
|
|
80 |
// Don't show individual field errors when there is a combo field error.
|
81 |
if ( ! empty( $errors ) && isset( $errors[ 'field' . $field_id . '-' . $name ] ) && ! isset( $errors[ 'field' . $field_id ] ) ) {
|
82 |
?>
|
83 |
-
<div class="frm_error"><?php echo esc_html( $errors[ 'field' . $field_id . '-' . $name ] ); ?></div>
|
84 |
<?php } ?>
|
85 |
</div>
|
86 |
<?php } ?>
|
80 |
// Don't show individual field errors when there is a combo field error.
|
81 |
if ( ! empty( $errors ) && isset( $errors[ 'field' . $field_id . '-' . $name ] ) && ! isset( $errors[ 'field' . $field_id ] ) ) {
|
82 |
?>
|
83 |
+
<div class="frm_error" role="alert"><?php echo esc_html( $errors[ 'field' . $field_id . '-' . $name ] ); ?></div>
|
84 |
<?php } ?>
|
85 |
</div>
|
86 |
<?php } ?>
|
classes/views/frm-forms/form.php
CHANGED
@@ -64,4 +64,3 @@ if ( ! defined( 'ABSPATH' ) ) {
|
|
64 |
</div>
|
65 |
<?php
|
66 |
FrmFieldsHelper::bulk_options_overlay();
|
67 |
-
FrmAppHelper::multiselect_accessibility();
|
64 |
</div>
|
65 |
<?php
|
66 |
FrmFieldsHelper::bulk_options_overlay();
|
|
classes/views/frm-forms/multiselect-accessibility.php
CHANGED
@@ -2,9 +2,4 @@
|
|
2 |
if ( ! defined( 'ABSPATH' ) ) {
|
3 |
die( 'You are not allowed to call this page directly.' );
|
4 |
}
|
5 |
-
|
6 |
-
<div class="hidden">
|
7 |
-
<div id="frm_press_space_checked"><?php esc_html_e( 'Checked. To uncheck this option, press Space or Enter', 'formidable' ); ?></div>
|
8 |
-
<div id="frm_press_space_unchecked"><?php esc_html_e( 'Unchecked. To check this option, press Space or Enter', 'formidable' ); ?></div>
|
9 |
-
<div id="frm_multiselect_button"><?php esc_html_e( 'You are on a Custom List of Checkboxes. To open, press Enter. Use Up and Down arrow keys to switch between options', 'formidable' ); ?></div>
|
10 |
-
</div>
|
2 |
if ( ! defined( 'ABSPATH' ) ) {
|
3 |
die( 'You are not allowed to call this page directly.' );
|
4 |
}
|
5 |
+
_deprecated_file( esc_html( basename( __FILE__ ) ), 'x.x' );
|
|
|
|
|
|
|
|
|
|
classes/views/frm-forms/settings.php
CHANGED
@@ -64,6 +64,3 @@ if ( ! defined( 'ABSPATH' ) ) {
|
|
64 |
</div>
|
65 |
</form>
|
66 |
</div>
|
67 |
-
|
68 |
-
<?php
|
69 |
-
FrmAppHelper::multiselect_accessibility();
|
64 |
</div>
|
65 |
</form>
|
66 |
</div>
|
|
|
|
|
|
classes/views/frm-settings/permissions.php
CHANGED
@@ -14,12 +14,9 @@ if ( ! defined( 'ABSPATH' ) ) {
|
|
14 |
?>
|
15 |
<tr>
|
16 |
<td class="frm_left_label">
|
17 |
-
<label id="for_<?php echo esc_attr( str_replace( '[]', '', $role_field_name ) ); ?>"><?php echo esc_html( $frm_role_description ); ?></label>
|
18 |
</td>
|
19 |
<td><?php FrmAppHelper::wp_roles_dropdown( $role_field_name, $frm_settings->$frm_role, 'multiple' ); ?></td>
|
20 |
</tr>
|
21 |
<?php } ?>
|
22 |
</table>
|
23 |
-
|
24 |
-
<?php
|
25 |
-
FrmAppHelper::multiselect_accessibility();
|
14 |
?>
|
15 |
<tr>
|
16 |
<td class="frm_left_label">
|
17 |
+
<label id="for_<?php echo esc_attr( str_replace( '[]', '', $role_field_name ) ); ?>" for="<?php echo esc_attr( $role_field_name ); ?>"><?php echo esc_html( $frm_role_description ); ?></label>
|
18 |
</td>
|
19 |
<td><?php FrmAppHelper::wp_roles_dropdown( $role_field_name, $frm_settings->$frm_role, 'multiple' ); ?></td>
|
20 |
</tr>
|
21 |
<?php } ?>
|
22 |
</table>
|
|
|
|
|
|
css/frm_admin.css
CHANGED
@@ -2883,51 +2883,29 @@ a.frm_option_icon:hover::before {
|
|
2883 |
font-family: "s11-fp" !important;
|
2884 |
}
|
2885 |
|
2886 |
-
.multiselect-container.frm-dropdown-menu input[type=radio] {
|
2887 |
-
display: none;
|
2888 |
-
}
|
2889 |
-
|
2890 |
.multiselect-container {
|
2891 |
position: absolute;
|
2892 |
list-style-type: none;
|
2893 |
margin: 0;
|
2894 |
-
padding: 0
|
2895 |
-
}
|
2896 |
-
|
2897 |
-
.multiselect-container .input-group {
|
2898 |
-
margin: 5px
|
2899 |
-
}
|
2900 |
-
|
2901 |
-
.multiselect-container > li {
|
2902 |
padding: 0;
|
2903 |
-
|
2904 |
-
|
2905 |
-
|
2906 |
-
.multiselect-container > li > a.multiselect-all label {
|
2907 |
-
font-weight: 700
|
2908 |
-
}
|
2909 |
-
|
2910 |
-
.multiselect-container > li > label.multiselect-group {
|
2911 |
-
margin: 0;
|
2912 |
-
padding: 3px 20px;
|
2913 |
-
height: 100%;
|
2914 |
-
font-weight: 700
|
2915 |
}
|
2916 |
|
2917 |
-
.
|
2918 |
-
|
|
|
|
|
|
|
|
|
|
|
2919 |
}
|
2920 |
|
2921 |
-
.multiselect-container
|
2922 |
-
margin:
|
2923 |
-
padding: 3px 25px;
|
2924 |
-
height: 100%;
|
2925 |
-
cursor: pointer;
|
2926 |
-
font-weight: 400;
|
2927 |
-
display: block;
|
2928 |
}
|
2929 |
|
2930 |
-
.accordion-container .multiselect-container
|
2931 |
padding: 3px 19px 3px 7px;
|
2932 |
}
|
2933 |
|
@@ -2936,17 +2914,6 @@ a.frm_option_icon:hover::before {
|
|
2936 |
border-bottom-left-radius: 4px
|
2937 |
}
|
2938 |
|
2939 |
-
.form-inline .multiselect-container label.checkbox,
|
2940 |
-
.form-inline .multiselect-container label.radio {
|
2941 |
-
padding: 3px 20px;
|
2942 |
-
}
|
2943 |
-
|
2944 |
-
.form-inline .multiselect-container li a label.checkbox input[type=checkbox],
|
2945 |
-
.form-inline .multiselect-container li a label.radio input[type=radio] {
|
2946 |
-
margin-left: -20px;
|
2947 |
-
margin-right: 0;
|
2948 |
-
}
|
2949 |
-
|
2950 |
.frm-btn-group.btn-group, .frm-btn-group.btn-group-vertical {
|
2951 |
display: block;
|
2952 |
vertical-align: middle;
|
2883 |
font-family: "s11-fp" !important;
|
2884 |
}
|
2885 |
|
|
|
|
|
|
|
|
|
2886 |
.multiselect-container {
|
2887 |
position: absolute;
|
2888 |
list-style-type: none;
|
2889 |
margin: 0;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2890 |
padding: 0;
|
2891 |
+
width: 100%;
|
2892 |
+
max-width: 250px;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2893 |
}
|
2894 |
|
2895 |
+
.multiselect-container button.multiselect-option {
|
2896 |
+
display: block;
|
2897 |
+
width: 100%;
|
2898 |
+
text-align: left;
|
2899 |
+
background: none;
|
2900 |
+
border: none;
|
2901 |
+
padding: 5px 0 5px 15px;
|
2902 |
}
|
2903 |
|
2904 |
+
.multiselect-container button.multiselect-option label {
|
2905 |
+
margin-left: 5px;
|
|
|
|
|
|
|
|
|
|
|
2906 |
}
|
2907 |
|
2908 |
+
.accordion-container .multiselect-container label {
|
2909 |
padding: 3px 19px 3px 7px;
|
2910 |
}
|
2911 |
|
2914 |
border-bottom-left-radius: 4px
|
2915 |
}
|
2916 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2917 |
.frm-btn-group.btn-group, .frm-btn-group.btn-group-vertical {
|
2918 |
display: block;
|
2919 |
vertical-align: middle;
|
formidable.php
CHANGED
@@ -2,7 +2,7 @@
|
|
2 |
/*
|
3 |
Plugin Name: Formidable Forms
|
4 |
Description: Quickly and easily create drag-and-drop forms
|
5 |
-
Version: 5.
|
6 |
Plugin URI: https://formidableforms.com/
|
7 |
Author URI: https://formidableforms.com/
|
8 |
Author: Strategy11
|
2 |
/*
|
3 |
Plugin Name: Formidable Forms
|
4 |
Description: Quickly and easily create drag-and-drop forms
|
5 |
+
Version: 5.1
|
6 |
Plugin URI: https://formidableforms.com/
|
7 |
Author URI: https://formidableforms.com/
|
8 |
Author: Strategy11
|
js/bootstrap-multiselect.js
CHANGED
@@ -2,7 +2,7 @@
|
|
2 |
* Bootstrap Multiselect (http://davidstutz.de/bootstrap-multiselect/)
|
3 |
*
|
4 |
* Apache License, Version 2.0:
|
5 |
-
* Copyright (c) 2012 -
|
6 |
*
|
7 |
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
|
8 |
* use this file except in compliance with the License. You may obtain a
|
@@ -15,7 +15,7 @@
|
|
15 |
* under the License.
|
16 |
*
|
17 |
* BSD 3-Clause License:
|
18 |
-
* Copyright (c) 2012 -
|
19 |
* All rights reserved.
|
20 |
*
|
21 |
* Redistribution and use in source and binary forms, with or without
|
@@ -41,14 +41,25 @@
|
|
41 |
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
42 |
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
43 |
*/
|
44 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
45 |
"use strict";// jshint ;_;
|
46 |
|
47 |
if (typeof ko !== 'undefined' && ko.bindingHandlers && !ko.bindingHandlers.multiselect) {
|
48 |
ko.bindingHandlers.multiselect = {
|
49 |
after: ['options', 'value', 'selectedOptions', 'enable', 'disable'],
|
50 |
|
51 |
-
init: function(element, valueAccessor, allBindings, viewModel, bindingContext) {
|
52 |
var $element = $(element);
|
53 |
var config = ko.toJS(valueAccessor());
|
54 |
|
@@ -58,9 +69,9 @@
|
|
58 |
var options = allBindings.get('options');
|
59 |
if (ko.isObservable(options)) {
|
60 |
ko.computed({
|
61 |
-
read: function() {
|
62 |
options();
|
63 |
-
setTimeout(function() {
|
64 |
var ms = $element.data('multiselect');
|
65 |
if (ms)
|
66 |
ms.updateOriginalOptions();//Not sure how beneficial this is.
|
@@ -79,9 +90,9 @@
|
|
79 |
var value = allBindings.get('value');
|
80 |
if (ko.isObservable(value)) {
|
81 |
ko.computed({
|
82 |
-
read: function() {
|
83 |
value();
|
84 |
-
setTimeout(function() {
|
85 |
$element.multiselect('refresh');
|
86 |
}, 1);
|
87 |
},
|
@@ -96,9 +107,9 @@
|
|
96 |
var selectedOptions = allBindings.get('selectedOptions');
|
97 |
if (ko.isObservable(selectedOptions)) {
|
98 |
ko.computed({
|
99 |
-
read: function() {
|
100 |
selectedOptions();
|
101 |
-
setTimeout(function() {
|
102 |
$element.multiselect('refresh');
|
103 |
}, 1);
|
104 |
},
|
@@ -144,12 +155,12 @@
|
|
144 |
}
|
145 |
}
|
146 |
|
147 |
-
ko.utils.domNodeDisposal.addDisposeCallback(element, function() {
|
148 |
$element.multiselect('destroy');
|
149 |
});
|
150 |
},
|
151 |
|
152 |
-
update: function(element, valueAccessor, allBindings, viewModel, bindingContext) {
|
153 |
var $element = $(element);
|
154 |
var config = ko.toJS(valueAccessor());
|
155 |
|
@@ -208,6 +219,7 @@
|
|
208 |
this.buildSelectAll();
|
209 |
this.buildDropdownOptions();
|
210 |
this.buildFilter();
|
|
|
211 |
|
212 |
this.updateButtonText();
|
213 |
this.updateSelectAll(true);
|
@@ -217,11 +229,17 @@
|
|
217 |
}
|
218 |
|
219 |
this.options.wasDisabled = this.$select.prop('disabled');
|
220 |
-
if (this.options.disableIfEmpty && $('option', this.$select).length <= 0) {
|
221 |
-
this.disable();
|
222 |
}
|
223 |
|
224 |
this.$select.wrap('<span class="multiselect-native-select" />').after(this.$container);
|
|
|
|
|
|
|
|
|
|
|
|
|
225 |
this.options.onInitialized(this.$select, this.$container);
|
226 |
}
|
227 |
|
@@ -237,35 +255,33 @@
|
|
237 |
* @param {jQuery} select
|
238 |
* @returns {String}
|
239 |
*/
|
240 |
-
buttonText: function(
|
241 |
-
if (this.disabledText.length > 0
|
242 |
-
&& (select.prop('disabled') || (options.length == 0 && this.disableIfEmpty))) {
|
243 |
-
|
244 |
return this.disabledText;
|
245 |
}
|
246 |
-
else if (
|
247 |
return this.nonSelectedText;
|
248 |
}
|
249 |
else if (this.allSelectedText
|
250 |
-
|
251 |
-
|
252 |
-
|
253 |
|
254 |
if (this.selectAllNumber) {
|
255 |
-
return this.allSelectedText + ' (' +
|
256 |
}
|
257 |
else {
|
258 |
return this.allSelectedText;
|
259 |
}
|
260 |
}
|
261 |
-
else if (this.numberDisplayed != 0 &&
|
262 |
-
return
|
263 |
}
|
264 |
else {
|
265 |
var selected = '';
|
266 |
var delimiter = this.delimiterText;
|
267 |
|
268 |
-
|
269 |
var label = ($(this).attr('label') !== undefined) ? $(this).attr('label') : $(this).text();
|
270 |
selected += label + delimiter;
|
271 |
});
|
@@ -280,7 +296,7 @@
|
|
280 |
* @param {jQuery} select
|
281 |
* @returns {@exp;selected@call;substr}
|
282 |
*/
|
283 |
-
buttonTitle: function(options, select) {
|
284 |
if (options.length === 0) {
|
285 |
return this.nonSelectedText;
|
286 |
}
|
@@ -295,7 +311,7 @@
|
|
295 |
return selected.substr(0, selected.length - this.delimiterText.length);
|
296 |
}
|
297 |
},
|
298 |
-
checkboxName: function(option) {
|
299 |
return false; // no checkbox name
|
300 |
},
|
301 |
/**
|
@@ -304,7 +320,7 @@
|
|
304 |
* @param {jQuery} element
|
305 |
* @returns {String}
|
306 |
*/
|
307 |
-
optionLabel: function(element){
|
308 |
return $(element).attr('label') || $(element).text();
|
309 |
},
|
310 |
/**
|
@@ -313,7 +329,7 @@
|
|
313 |
* @param {jQuery} element
|
314 |
* @returns {String}
|
315 |
*/
|
316 |
-
optionClass: function(element) {
|
317 |
return $(element).attr('class') || '';
|
318 |
},
|
319 |
/**
|
@@ -324,7 +340,7 @@
|
|
324 |
* @param {jQuery} option
|
325 |
* @param {Boolean} checked
|
326 |
*/
|
327 |
-
onChange
|
328 |
|
329 |
},
|
330 |
/**
|
@@ -332,7 +348,7 @@
|
|
332 |
*
|
333 |
* @param {jQuery} event
|
334 |
*/
|
335 |
-
onDropdownShow: function(event) {
|
336 |
|
337 |
},
|
338 |
/**
|
@@ -340,7 +356,7 @@
|
|
340 |
*
|
341 |
* @param {jQuery} event
|
342 |
*/
|
343 |
-
onDropdownHide: function(event) {
|
344 |
|
345 |
},
|
346 |
/**
|
@@ -348,7 +364,7 @@
|
|
348 |
*
|
349 |
* @param {jQuery} event
|
350 |
*/
|
351 |
-
onDropdownShown: function(event) {
|
352 |
|
353 |
},
|
354 |
/**
|
@@ -356,19 +372,19 @@
|
|
356 |
*
|
357 |
* @param {jQuery} event
|
358 |
*/
|
359 |
-
onDropdownHidden: function(event) {
|
360 |
|
361 |
},
|
362 |
/**
|
363 |
* Triggered on select all.
|
364 |
*/
|
365 |
-
onSelectAll: function() {
|
366 |
|
367 |
},
|
368 |
/**
|
369 |
* Triggered on deselect all.
|
370 |
*/
|
371 |
-
onDeselectAll: function() {
|
372 |
|
373 |
},
|
374 |
/**
|
@@ -377,7 +393,7 @@
|
|
377 |
* @param {jQuery} $select
|
378 |
* @param {jQuery} $container
|
379 |
*/
|
380 |
-
onInitialized: function($select, $container) {
|
381 |
|
382 |
},
|
383 |
/**
|
@@ -385,11 +401,11 @@
|
|
385 |
*
|
386 |
* @param {jQuery} $filter
|
387 |
*/
|
388 |
-
onFiltering: function($filter) {
|
389 |
|
390 |
},
|
391 |
enableHTML: false,
|
392 |
-
buttonClass: '
|
393 |
inheritClass: false,
|
394 |
buttonWidth: 'auto',
|
395 |
buttonContainer: '<div class="btn-group" />',
|
@@ -420,6 +436,7 @@
|
|
420 |
nonSelectedText: 'None selected',
|
421 |
nSelectedText: 'selected',
|
422 |
allSelectedText: 'All selected',
|
|
|
423 |
numberDisplayed: 3,
|
424 |
disableIfEmpty: false,
|
425 |
disabledText: '',
|
@@ -427,15 +444,21 @@
|
|
427 |
includeResetOption: false,
|
428 |
includeResetDivider: false,
|
429 |
resetText: 'Reset',
|
|
|
|
|
|
|
|
|
|
|
430 |
templates: {
|
431 |
-
button: '<button type="button" class="multiselect dropdown-toggle" data-toggle="dropdown"><span class="multiselect-selected-text"></span
|
432 |
-
|
433 |
-
filter: '<
|
434 |
-
|
435 |
-
|
436 |
-
|
437 |
-
|
438 |
-
|
|
|
439 |
}
|
440 |
},
|
441 |
|
@@ -444,9 +467,18 @@
|
|
444 |
/**
|
445 |
* Builds the container of the multiselect.
|
446 |
*/
|
447 |
-
buildContainer: function() {
|
448 |
this.$container = $(this.options.buttonContainer);
|
449 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
450 |
this.$container.on('hide.bs.dropdown', this.options.onDropdownHide);
|
451 |
this.$container.on('shown.bs.dropdown', this.options.onDropdownShown);
|
452 |
this.$container.on('hidden.bs.dropdown', this.options.onDropdownHidden);
|
@@ -455,7 +487,7 @@
|
|
455 |
/**
|
456 |
* Builds the button of the multiselect.
|
457 |
*/
|
458 |
-
buildButton: function() {
|
459 |
this.$button = $(this.options.templates.button).addClass(this.options.buttonClass);
|
460 |
if (this.$select.attr('class') && this.options.inheritClass) {
|
461 |
this.$button.addClass(this.$select.attr('class'));
|
@@ -471,15 +503,27 @@
|
|
471 |
// Manually add button width if set.
|
472 |
if (this.options.buttonWidth && this.options.buttonWidth !== 'auto') {
|
473 |
this.$button.css({
|
474 |
-
'width'
|
475 |
-
'overflow' : 'hidden',
|
476 |
-
'text-overflow' : 'ellipsis'
|
477 |
});
|
478 |
this.$container.css({
|
479 |
'width': this.options.buttonWidth
|
480 |
});
|
481 |
}
|
482 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
483 |
// Keep the tab index from the select.
|
484 |
var tabindex = this.$select.attr('tabindex');
|
485 |
if (tabindex) {
|
@@ -490,41 +534,59 @@
|
|
490 |
},
|
491 |
|
492 |
/**
|
493 |
-
* Builds the
|
494 |
*/
|
495 |
-
buildDropdown: function() {
|
496 |
|
497 |
-
// Build
|
498 |
-
this.$
|
499 |
|
500 |
if (this.options.dropRight) {
|
501 |
-
this.$
|
|
|
|
|
|
|
502 |
}
|
503 |
|
504 |
// Set max height of dropdown menu to activate auto scrollbar.
|
505 |
if (this.options.maxHeight) {
|
506 |
// TODO: Add a class for this option to move the css declarations.
|
507 |
-
this.$
|
508 |
'max-height': this.options.maxHeight + 'px',
|
509 |
'overflow-y': 'auto',
|
510 |
'overflow-x': 'hidden'
|
511 |
});
|
512 |
}
|
513 |
|
514 |
-
if (this.options.
|
|
|
|
|
515 |
|
516 |
-
|
517 |
-
|
|
|
518 |
|
519 |
-
|
520 |
-
|
521 |
-
|
522 |
-
|
523 |
-
|
524 |
-
|
525 |
}
|
526 |
|
527 |
-
this.$
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
528 |
},
|
529 |
|
530 |
/**
|
@@ -532,9 +594,9 @@
|
|
532 |
*
|
533 |
* Uses createDivider and createOptionValue to create the necessary options.
|
534 |
*/
|
535 |
-
buildDropdownOptions: function() {
|
536 |
|
537 |
-
this.$select.children().each($.proxy(function(index, element) {
|
538 |
|
539 |
var $element = $(element);
|
540 |
// Support optgroups and options without a group simultaneously.
|
@@ -554,7 +616,7 @@
|
|
554 |
this.createDivider();
|
555 |
}
|
556 |
else {
|
557 |
-
this.createOptionValue(element);
|
558 |
}
|
559 |
|
560 |
}
|
@@ -563,8 +625,8 @@
|
|
563 |
}, this));
|
564 |
|
565 |
// Bind the change event on the dropdown elements.
|
566 |
-
$(this.$
|
567 |
-
$(this.$
|
568 |
var $target = $(event.target);
|
569 |
|
570 |
var checked = $target.prop('checked') || false;
|
@@ -573,11 +635,11 @@
|
|
573 |
// Apply or unapply the configured selected class.
|
574 |
if (this.options.selectedClass) {
|
575 |
if (checked) {
|
576 |
-
$target.closest('
|
577 |
.addClass(this.options.selectedClass);
|
578 |
}
|
579 |
else {
|
580 |
-
$target.closest('
|
581 |
.removeClass(this.options.selectedClass);
|
582 |
}
|
583 |
}
|
@@ -609,7 +671,7 @@
|
|
609 |
else {
|
610 |
// Unselect all other options and corresponding checkboxes.
|
611 |
if (this.options.selectedClass) {
|
612 |
-
$($checkboxesNotThis).closest('
|
613 |
}
|
614 |
|
615 |
$($checkboxesNotThis).prop('checked', false);
|
@@ -620,7 +682,7 @@
|
|
620 |
}
|
621 |
|
622 |
if (this.options.selectedClass === "active") {
|
623 |
-
$optionsNotThis.closest("
|
624 |
}
|
625 |
}
|
626 |
else {
|
@@ -642,34 +704,36 @@
|
|
642 |
this.$select.change();
|
643 |
this.updateButtonText();
|
644 |
|
645 |
-
if(this.options.preventInputChangeEvent) {
|
646 |
return false;
|
647 |
}
|
648 |
}, this));
|
649 |
|
650 |
-
$('
|
|
|
651 |
if (e.shiftKey) {
|
652 |
// Prevent selecting text by Shift+click
|
653 |
return false;
|
654 |
}
|
655 |
});
|
656 |
|
657 |
-
$(this.$
|
|
|
658 |
event.stopPropagation();
|
659 |
|
660 |
var $target = $(event.target);
|
661 |
|
662 |
if (event.shiftKey && this.options.multiple) {
|
663 |
-
if(
|
664 |
event.preventDefault();
|
665 |
-
$target = $target.find("input");
|
666 |
$target.prop("checked", !$target.prop("checked"));
|
667 |
}
|
668 |
var checked = $target.prop('checked') || false;
|
669 |
|
670 |
if (this.lastToggledInput !== null && this.lastToggledInput !== $target) { // Make sure we actually have a range
|
671 |
-
var from = this.$
|
672 |
-
var to = this.$
|
673 |
|
674 |
if (from > to) { // Swap the indices
|
675 |
var tmp = to;
|
@@ -681,12 +745,12 @@
|
|
681 |
++to;
|
682 |
|
683 |
// Change the checkboxes and underlying options
|
684 |
-
var range = this.$
|
685 |
|
686 |
range.prop('checked', checked);
|
687 |
|
688 |
if (this.options.selectedClass) {
|
689 |
-
range.closest('
|
690 |
.toggleClass(this.options.selectedClass, checked);
|
691 |
}
|
692 |
|
@@ -702,100 +766,124 @@
|
|
702 |
// Trigger the select "change" event
|
703 |
$target.trigger("change");
|
704 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
705 |
|
706 |
// Remembers last clicked option
|
707 |
-
|
|
|
708 |
this.lastToggledInput = $target;
|
709 |
}
|
|
|
|
|
|
|
710 |
|
711 |
-
$target.
|
712 |
}, this));
|
713 |
|
714 |
-
//
|
715 |
-
this.$container.off('keydown.multiselect').on('keydown.multiselect', $.proxy(function(event) {
|
716 |
-
|
717 |
-
|
718 |
-
|
719 |
|
720 |
-
|
|
|
721 |
this.$button.click();
|
722 |
}
|
723 |
-
|
724 |
-
|
725 |
-
|
726 |
-
|
727 |
-
|
728 |
-
}
|
729 |
-
|
730 |
-
|
731 |
-
|
732 |
-
|
733 |
-
|
734 |
-
|
|
|
735 |
}
|
736 |
-
|
737 |
-
|
738 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
739 |
}
|
740 |
-
else if (
|
741 |
-
|
|
|
|
|
742 |
}
|
743 |
-
|
744 |
-
var $current = $items.eq(index);
|
745 |
-
$current.trigger( 'focus' );
|
746 |
-
|
747 |
-
if (event.keyCode === 32 || event.keyCode === 13) {
|
748 |
-
var $checkbox = $current.find('input');
|
749 |
-
|
750 |
-
$checkbox.prop("checked", !$checkbox.prop("checked"));
|
751 |
-
$checkbox.change();
|
752 |
-
}
|
753 |
-
|
754 |
-
event.stopPropagation();
|
755 |
-
event.preventDefault();
|
756 |
}
|
757 |
}, this));
|
758 |
|
759 |
if (this.options.enableClickableOptGroups && this.options.multiple) {
|
760 |
-
$("
|
|
|
761 |
event.stopPropagation();
|
762 |
|
763 |
var $target = $(event.target);
|
764 |
var checked = $target.prop('checked') || false;
|
765 |
|
766 |
-
var $
|
767 |
-
var $group = $
|
768 |
.not('.multiselect-filter-hidden')
|
769 |
.not('.disabled');
|
770 |
|
771 |
var $inputs = $group.find("input");
|
772 |
|
773 |
-
var values = [];
|
774 |
var $options = [];
|
775 |
|
776 |
if (this.options.selectedClass) {
|
777 |
if (checked) {
|
778 |
-
$
|
779 |
}
|
780 |
else {
|
781 |
-
$
|
782 |
}
|
783 |
}
|
784 |
|
785 |
-
$.each($inputs, $.proxy(function(index, input) {
|
786 |
-
var
|
|
|
787 |
var $option = this.getOptionByValue(value);
|
788 |
|
789 |
if (checked) {
|
790 |
-
$
|
791 |
-
$
|
792 |
.addClass(this.options.selectedClass);
|
793 |
|
794 |
$option.prop('selected', true);
|
795 |
}
|
796 |
else {
|
797 |
-
$
|
798 |
-
$
|
799 |
.removeClass(this.options.selectedClass);
|
800 |
|
801 |
$option.prop('selected', false);
|
@@ -815,13 +903,14 @@
|
|
815 |
}
|
816 |
|
817 |
if (this.options.enableCollapsibleOptGroups && this.options.multiple) {
|
818 |
-
$("
|
819 |
-
|
820 |
-
var $
|
821 |
-
|
|
|
822 |
|
823 |
var visible = true;
|
824 |
-
$inputs.each(function() {
|
825 |
visible = visible && !$(this).hasClass('multiselect-collapsible-hidden');
|
826 |
});
|
827 |
|
@@ -834,11 +923,45 @@
|
|
834 |
.removeClass('multiselect-collapsible-hidden');
|
835 |
}
|
836 |
}, this));
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
837 |
|
838 |
-
|
839 |
-
|
840 |
-
|
|
|
|
|
|
|
841 |
}
|
|
|
|
|
|
|
|
|
|
|
842 |
},
|
843 |
|
844 |
/**
|
@@ -846,7 +969,7 @@
|
|
846 |
*
|
847 |
* @param {jQuery} element
|
848 |
*/
|
849 |
-
createOptionValue: function(element) {
|
850 |
var $element = $(element);
|
851 |
if ($element.is(':selected')) {
|
852 |
$element.prop('selected', true);
|
@@ -857,61 +980,46 @@
|
|
857 |
var classes = this.options.optionClass(element);
|
858 |
var value = $element.val();
|
859 |
var inputType = this.options.multiple ? "checkbox" : "radio";
|
|
|
860 |
|
861 |
-
var $
|
862 |
-
|
863 |
-
$label.addClass(inputType);
|
864 |
-
$label.attr("title", label);
|
865 |
-
$li.addClass(classes);
|
866 |
|
867 |
-
|
868 |
-
|
869 |
-
$li.addClass("multiselect-collapsible-hidden");
|
870 |
-
$li.hide();
|
871 |
}
|
872 |
|
873 |
-
|
874 |
-
|
875 |
-
|
876 |
-
|
877 |
-
$label.text(" " + label);
|
878 |
}
|
879 |
|
880 |
-
var $checkbox = $('<input/>').attr('type', inputType);
|
881 |
-
|
882 |
var name = this.options.checkboxName($element);
|
883 |
-
|
884 |
-
$checkbox.attr('name', name);
|
885 |
-
}
|
886 |
-
|
887 |
-
$label.prepend($checkbox);
|
888 |
|
889 |
var selected = $element.prop('selected') || false;
|
890 |
-
$checkbox.val(value);
|
891 |
|
892 |
if (value === this.options.selectAllValue) {
|
893 |
-
$
|
|
|
894 |
$checkbox.parent().parent()
|
895 |
.addClass('multiselect-all');
|
896 |
}
|
897 |
|
898 |
-
|
899 |
-
|
900 |
-
this.$ul.append($li);
|
901 |
|
902 |
if ($element.is(':disabled')) {
|
903 |
$checkbox.attr('disabled', 'disabled')
|
904 |
.prop('disabled', true)
|
905 |
-
.closest('
|
906 |
-
.attr("tabindex", "-1")
|
907 |
-
.closest('li')
|
908 |
.addClass('disabled');
|
909 |
}
|
910 |
|
911 |
$checkbox.prop('checked', selected);
|
912 |
|
913 |
if (selected && this.options.selectedClass) {
|
914 |
-
$checkbox.closest('
|
915 |
.addClass(this.options.selectedClass);
|
916 |
}
|
917 |
},
|
@@ -921,9 +1029,9 @@
|
|
921 |
*
|
922 |
* @param {jQuery} element
|
923 |
*/
|
924 |
-
createDivider: function(element) {
|
925 |
var $divider = $(this.options.templates.divider);
|
926 |
-
this.$
|
927 |
},
|
928 |
|
929 |
/**
|
@@ -931,66 +1039,74 @@
|
|
931 |
*
|
932 |
* @param {jQuery} group
|
933 |
*/
|
934 |
-
createOptgroup: function(group) {
|
935 |
-
var
|
936 |
-
var
|
937 |
-
var
|
|
|
938 |
|
939 |
-
var
|
940 |
-
$li.addClass(classes);
|
941 |
|
942 |
-
if (this.options.
|
943 |
-
$
|
|
|
944 |
}
|
945 |
else {
|
946 |
-
|
|
|
|
|
|
|
|
|
|
|
947 |
}
|
948 |
|
949 |
-
|
950 |
-
|
951 |
-
}
|
952 |
|
953 |
-
if (this.options.
|
954 |
-
$('
|
|
|
955 |
}
|
956 |
|
957 |
-
if ($
|
958 |
-
$
|
959 |
}
|
960 |
|
961 |
-
this.$
|
962 |
|
963 |
-
$("option", group).each($.proxy(function($, group) {
|
964 |
-
this.createOptionValue(group);
|
965 |
-
}, this))
|
966 |
},
|
967 |
|
968 |
/**
|
969 |
* Build the reset.
|
970 |
*
|
971 |
*/
|
972 |
-
buildReset: function() {
|
973 |
if (this.options.includeResetOption) {
|
974 |
|
975 |
// Check whether to add a divider after the reset.
|
976 |
if (this.options.includeResetDivider) {
|
977 |
-
|
|
|
|
|
978 |
}
|
979 |
|
980 |
var $resetButton = $(this.options.templates.resetButton);
|
981 |
|
982 |
if (this.options.enableHTML) {
|
983 |
-
$('
|
984 |
}
|
985 |
else {
|
986 |
-
$('
|
987 |
}
|
988 |
|
989 |
-
$('
|
990 |
this.clearSelection();
|
991 |
}, this));
|
992 |
|
993 |
-
this.$
|
994 |
}
|
995 |
},
|
996 |
|
@@ -999,7 +1115,7 @@
|
|
999 |
*
|
1000 |
* Checks if a select all has already been created.
|
1001 |
*/
|
1002 |
-
buildSelectAll: function() {
|
1003 |
if (typeof this.options.selectAllValue === 'number') {
|
1004 |
this.options.selectAllValue = this.options.selectAllValue.toString();
|
1005 |
}
|
@@ -1007,38 +1123,21 @@
|
|
1007 |
var alreadyHasSelectAll = this.hasSelectAll();
|
1008 |
|
1009 |
if (!alreadyHasSelectAll && this.options.includeSelectAllOption && this.options.multiple
|
1010 |
-
|
1011 |
|
1012 |
// Check whether to add a divider after the select all.
|
1013 |
if (this.options.includeSelectAllDivider) {
|
1014 |
-
this.$
|
1015 |
}
|
1016 |
|
1017 |
-
var $
|
1018 |
-
$(
|
1019 |
-
|
1020 |
-
if (this.options.enableHTML) {
|
1021 |
-
$('label', $li).html(" " + this.options.selectAllText);
|
1022 |
-
}
|
1023 |
-
else {
|
1024 |
-
$('label', $li).text(" " + this.options.selectAllText);
|
1025 |
-
}
|
1026 |
|
1027 |
-
|
1028 |
-
|
1029 |
-
|
1030 |
-
else {
|
1031 |
-
$('label', $li).prepend('<input type="checkbox" />');
|
1032 |
-
}
|
1033 |
|
1034 |
-
|
1035 |
-
$checkbox.val(this.options.selectAllValue);
|
1036 |
-
|
1037 |
-
$li.addClass("multiselect-item multiselect-all");
|
1038 |
-
$checkbox.parent().parent()
|
1039 |
-
.addClass('multiselect-all');
|
1040 |
-
|
1041 |
-
this.$ul.prepend($li);
|
1042 |
|
1043 |
$checkbox.prop('checked', false);
|
1044 |
}
|
@@ -1047,7 +1146,7 @@
|
|
1047 |
/**
|
1048 |
* Builds the filter.
|
1049 |
*/
|
1050 |
-
buildFilter: function() {
|
1051 |
|
1052 |
// Build filter if filtering OR case insensitive filtering is enabled and the number of options exceeds (or equals) enableFilterLength.
|
1053 |
if (this.options.enableFiltering || this.options.enableCaseInsensitiveFiltering) {
|
@@ -1058,15 +1157,25 @@
|
|
1058 |
this.$filter = $(this.options.templates.filter);
|
1059 |
$('input', this.$filter).attr('placeholder', this.options.filterPlaceholder);
|
1060 |
|
1061 |
-
//
|
1062 |
-
if(this.options.includeFilterClearBtn) {
|
1063 |
-
|
1064 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1065 |
clearTimeout(this.searchTimeout);
|
1066 |
|
1067 |
this.query = '';
|
1068 |
this.$filter.find('.multiselect-search').val('');
|
1069 |
-
$('
|
1070 |
|
1071 |
this.updateSelectAll();
|
1072 |
|
@@ -1075,31 +1184,39 @@
|
|
1075 |
}
|
1076 |
|
1077 |
}, this));
|
1078 |
-
this.$filter.find('.input-group').append(clearBtn);
|
1079 |
}
|
1080 |
|
1081 |
-
this.$
|
1082 |
|
1083 |
-
this.$filter.val(this.query).on('click', function(event) {
|
1084 |
event.stopPropagation();
|
1085 |
-
}).on('input keydown', $.proxy(function(event) {
|
1086 |
// Cancel enter key default behaviour
|
1087 |
if (event.which === 13) {
|
1088 |
-
|
1089 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1090 |
|
1091 |
// This is useful to catch "keydown" events after the browser has updated the control.
|
1092 |
clearTimeout(this.searchTimeout);
|
1093 |
|
1094 |
-
this.searchTimeout = this.asyncFunction($.proxy(function() {
|
1095 |
|
1096 |
if (this.query !== event.target.value) {
|
1097 |
this.query = event.target.value;
|
1098 |
|
1099 |
var currentGroup, currentGroupVisible;
|
1100 |
-
$.each($('
|
1101 |
var value = $('input', element).length > 0 ? $('input', element).val() : "";
|
1102 |
-
var text = $('label', element).text();
|
1103 |
|
1104 |
var filterCandidate = '';
|
1105 |
if ((this.options.filterBehavior === 'text')) {
|
@@ -1134,13 +1251,13 @@
|
|
1134 |
}
|
1135 |
|
1136 |
// Toggle current element (group or group item) according to showElement boolean.
|
1137 |
-
if(!showElement){
|
1138 |
-
|
1139 |
-
|
1140 |
}
|
1141 |
-
if(showElement){
|
1142 |
-
|
1143 |
-
|
1144 |
}
|
1145 |
|
1146 |
// Differentiate groups and group items.
|
@@ -1172,6 +1289,8 @@
|
|
1172 |
this.updateOptGroups();
|
1173 |
}
|
1174 |
|
|
|
|
|
1175 |
this.options.onFiltering(event.target);
|
1176 |
|
1177 |
}, this), 300, this);
|
@@ -1180,11 +1299,67 @@
|
|
1180 |
}
|
1181 |
},
|
1182 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1183 |
/**
|
1184 |
* Unbinds the whole plugin.
|
1185 |
*/
|
1186 |
-
destroy: function() {
|
1187 |
this.$container.remove();
|
|
|
1188 |
this.$select.show();
|
1189 |
|
1190 |
// reset original state
|
@@ -1198,8 +1373,8 @@
|
|
1198 |
*/
|
1199 |
refresh: function () {
|
1200 |
var inputs = {};
|
1201 |
-
$('
|
1202 |
-
|
1203 |
});
|
1204 |
|
1205 |
$('option', this.$select).each($.proxy(function (index, element) {
|
@@ -1210,7 +1385,7 @@
|
|
1210 |
$input.prop('checked', true);
|
1211 |
|
1212 |
if (this.options.selectedClass) {
|
1213 |
-
$input.closest('
|
1214 |
.addClass(this.options.selectedClass);
|
1215 |
}
|
1216 |
}
|
@@ -1218,7 +1393,7 @@
|
|
1218 |
$input.prop('checked', false);
|
1219 |
|
1220 |
if (this.options.selectedClass) {
|
1221 |
-
$input.closest('
|
1222 |
.removeClass(this.options.selectedClass);
|
1223 |
}
|
1224 |
}
|
@@ -1226,12 +1401,12 @@
|
|
1226 |
if ($elem.is(":disabled")) {
|
1227 |
$input.attr('disabled', 'disabled')
|
1228 |
.prop('disabled', true)
|
1229 |
-
.closest('
|
1230 |
.addClass('disabled');
|
1231 |
}
|
1232 |
else {
|
1233 |
$input.prop('disabled', false)
|
1234 |
-
.closest('
|
1235 |
.removeClass('disabled');
|
1236 |
}
|
1237 |
}, this));
|
@@ -1253,8 +1428,8 @@
|
|
1253 |
* @param {Array} selectValues
|
1254 |
* @param {Boolean} triggerOnChange
|
1255 |
*/
|
1256 |
-
select: function(selectValues, triggerOnChange) {
|
1257 |
-
if(!$.isArray(selectValues)) {
|
1258 |
selectValues = [selectValues];
|
1259 |
}
|
1260 |
|
@@ -1268,22 +1443,27 @@
|
|
1268 |
var $option = this.getOptionByValue(value);
|
1269 |
var $checkbox = this.getInputByValue(value);
|
1270 |
|
1271 |
-
if($option === undefined || $checkbox === undefined) {
|
1272 |
continue;
|
1273 |
}
|
1274 |
|
1275 |
-
if (!this.options.multiple) {
|
1276 |
-
this.deselectAll(false);
|
1277 |
-
}
|
1278 |
-
|
1279 |
if (this.options.selectedClass) {
|
1280 |
-
$checkbox.closest('
|
1281 |
.addClass(this.options.selectedClass);
|
1282 |
}
|
1283 |
|
1284 |
$checkbox.prop('checked', true);
|
1285 |
$option.prop('selected', true);
|
1286 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1287 |
if (triggerOnChange) {
|
1288 |
this.options.onChange($option, true);
|
1289 |
}
|
@@ -1319,8 +1499,13 @@
|
|
1319 |
* @param {Array} deselectValues
|
1320 |
* @param {Boolean} triggerOnChange
|
1321 |
*/
|
1322 |
-
deselect: function(deselectValues, triggerOnChange) {
|
1323 |
-
if(
|
|
|
|
|
|
|
|
|
|
|
1324 |
deselectValues = [deselectValues];
|
1325 |
}
|
1326 |
|
@@ -1334,12 +1519,12 @@
|
|
1334 |
var $option = this.getOptionByValue(value);
|
1335 |
var $checkbox = this.getInputByValue(value);
|
1336 |
|
1337 |
-
if($option === undefined || $checkbox === undefined) {
|
1338 |
continue;
|
1339 |
}
|
1340 |
|
1341 |
if (this.options.selectedClass) {
|
1342 |
-
$checkbox.closest('
|
1343 |
.removeClass(this.options.selectedClass);
|
1344 |
}
|
1345 |
|
@@ -1368,40 +1553,55 @@
|
|
1368 |
* @param {Boolean} triggerOnSelectAll
|
1369 |
*/
|
1370 |
selectAll: function (justVisible, triggerOnSelectAll) {
|
|
|
|
|
|
|
|
|
1371 |
|
|
|
|
|
1372 |
var justVisible = typeof justVisible === 'undefined' ? true : justVisible;
|
1373 |
-
var allLis = $("li:not(.divider):not(.disabled):not(.multiselect-group)", this.$ul);
|
1374 |
-
var visibleLis = $("li:not(.divider):not(.disabled):not(.multiselect-group):not(.multiselect-filter-hidden):not(.multiselect-collapisble-hidden)", this.$ul).filter(':visible');
|
1375 |
|
1376 |
-
if(justVisible) {
|
1377 |
-
$(
|
1378 |
-
|
|
|
1379 |
|
1380 |
-
$('input:enabled'
|
1381 |
var value = $(element).val();
|
1382 |
var option = this.getOptionByValue(value);
|
|
|
|
|
|
|
1383 |
$(option).prop('selected', true);
|
1384 |
}, this));
|
1385 |
}
|
1386 |
else {
|
1387 |
-
$(
|
1388 |
-
|
|
|
1389 |
|
1390 |
-
$('input:enabled'
|
1391 |
var value = $(element).val();
|
1392 |
var option = this.getOptionByValue(value);
|
|
|
|
|
|
|
1393 |
$(option).prop('selected', true);
|
1394 |
}, this));
|
1395 |
}
|
1396 |
|
1397 |
-
$('
|
1398 |
|
1399 |
if (this.options.enableClickableOptGroups && this.options.multiple) {
|
1400 |
this.updateOptGroups();
|
1401 |
}
|
1402 |
|
|
|
|
|
|
|
1403 |
if (triggerOnSelectAll) {
|
1404 |
-
this.options.onSelectAll();
|
1405 |
}
|
1406 |
},
|
1407 |
|
@@ -1413,40 +1613,55 @@
|
|
1413 |
* @param {Boolean} justVisible
|
1414 |
*/
|
1415 |
deselectAll: function (justVisible, triggerOnDeselectAll) {
|
|
|
|
|
|
|
|
|
1416 |
|
|
|
|
|
1417 |
var justVisible = typeof justVisible === 'undefined' ? true : justVisible;
|
1418 |
-
var allLis = $("li:not(.divider):not(.disabled):not(.multiselect-group)", this.$ul);
|
1419 |
-
var visibleLis = $("li:not(.divider):not(.disabled):not(.multiselect-group):not(.multiselect-filter-hidden):not(.multiselect-collapisble-hidden)", this.$ul).filter(':visible');
|
1420 |
|
1421 |
-
if(justVisible) {
|
1422 |
-
$(
|
1423 |
-
|
|
|
1424 |
|
1425 |
-
$('input[type="checkbox"]:enabled'
|
1426 |
var value = $(element).val();
|
1427 |
var option = this.getOptionByValue(value);
|
|
|
|
|
|
|
1428 |
$(option).prop('selected', false);
|
1429 |
}, this));
|
1430 |
}
|
1431 |
else {
|
1432 |
-
$(
|
1433 |
-
|
|
|
1434 |
|
1435 |
-
$('input[type="checkbox"]:enabled'
|
1436 |
var value = $(element).val();
|
1437 |
var option = this.getOptionByValue(value);
|
|
|
|
|
|
|
1438 |
$(option).prop('selected', false);
|
1439 |
}, this));
|
1440 |
}
|
1441 |
|
1442 |
-
$('
|
1443 |
|
1444 |
if (this.options.enableClickableOptGroups && this.options.multiple) {
|
1445 |
this.updateOptGroups();
|
1446 |
}
|
1447 |
|
|
|
|
|
|
|
1448 |
if (triggerOnDeselectAll) {
|
1449 |
-
this.options.onDeselectAll();
|
1450 |
}
|
1451 |
},
|
1452 |
|
@@ -1455,8 +1670,8 @@
|
|
1455 |
*
|
1456 |
* Rebuilds the dropdown, the filter and the select all option.
|
1457 |
*/
|
1458 |
-
rebuild: function() {
|
1459 |
-
this.$
|
1460 |
|
1461 |
// Important to distinguish between radios and checkboxes.
|
1462 |
this.options.multiple = this.$select.attr('multiple') === "multiple";
|
@@ -1464,6 +1679,7 @@
|
|
1464 |
this.buildSelectAll();
|
1465 |
this.buildDropdownOptions();
|
1466 |
this.buildFilter();
|
|
|
1467 |
|
1468 |
this.updateButtonText();
|
1469 |
this.updateSelectAll(true);
|
@@ -1472,22 +1688,33 @@
|
|
1472 |
this.updateOptGroups();
|
1473 |
}
|
1474 |
|
1475 |
-
if (this.options.disableIfEmpty
|
1476 |
-
this.
|
1477 |
-
|
1478 |
-
|
1479 |
-
|
|
|
|
|
|
|
|
|
1480 |
}
|
1481 |
|
1482 |
if (this.options.dropRight) {
|
1483 |
-
this.$
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1484 |
}
|
1485 |
},
|
1486 |
|
1487 |
/**
|
1488 |
* The provided data will be used to build the dropdown.
|
1489 |
*/
|
1490 |
-
dataprovider: function(dataprovider) {
|
1491 |
|
1492 |
var groupCounter = 0;
|
1493 |
var $select = this.$select.empty();
|
@@ -1504,7 +1731,7 @@
|
|
1504 |
value: option.value
|
1505 |
});
|
1506 |
|
1507 |
-
forEach(option.children, function(subOption) { // add children option tags
|
1508 |
var attributes = {
|
1509 |
value: subOption.value,
|
1510 |
label: subOption.label || subOption.value,
|
@@ -1514,10 +1741,10 @@
|
|
1514 |
};
|
1515 |
|
1516 |
//Loop through attributes object and add key-value for each attribute
|
1517 |
-
|
1518 |
attributes['data-' + key] = subOption.attributes[key];
|
1519 |
-
|
1520 |
-
|
1521 |
$tag.append($('<option/>').attr(attributes));
|
1522 |
});
|
1523 |
}
|
@@ -1533,7 +1760,7 @@
|
|
1533 |
};
|
1534 |
//Loop through attributes object and add key-value for each attribute
|
1535 |
for (var key in option.attributes) {
|
1536 |
-
|
1537 |
}
|
1538 |
//Append original attributes + new data attributes to option
|
1539 |
$tag = $('<option/>').attr(attributes);
|
@@ -1550,19 +1777,30 @@
|
|
1550 |
/**
|
1551 |
* Enable the multiselect.
|
1552 |
*/
|
1553 |
-
enable: function() {
|
1554 |
this.$select.prop('disabled', false);
|
1555 |
this.$button.prop('disabled', false)
|
1556 |
.removeClass('disabled');
|
|
|
|
|
1557 |
},
|
1558 |
|
1559 |
/**
|
1560 |
* Disable the multiselect.
|
1561 |
*/
|
1562 |
-
disable: function() {
|
1563 |
this.$select.prop('disabled', true);
|
1564 |
this.$button.prop('disabled', true)
|
1565 |
.addClass('disabled');
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1566 |
},
|
1567 |
|
1568 |
/**
|
@@ -1570,7 +1808,7 @@
|
|
1570 |
*
|
1571 |
* @param {Array} options
|
1572 |
*/
|
1573 |
-
setOptions: function(options) {
|
1574 |
this.options = this.mergeOptions(options);
|
1575 |
},
|
1576 |
|
@@ -1580,7 +1818,7 @@
|
|
1580 |
* @param {Array} options
|
1581 |
* @returns {Array}
|
1582 |
*/
|
1583 |
-
mergeOptions: function(options) {
|
1584 |
return $.extend(true, {}, this.defaults, this.options, options);
|
1585 |
},
|
1586 |
|
@@ -1589,24 +1827,24 @@
|
|
1589 |
*
|
1590 |
* @returns {Boolean}
|
1591 |
*/
|
1592 |
-
hasSelectAll: function() {
|
1593 |
-
return $('
|
1594 |
},
|
1595 |
|
1596 |
/**
|
1597 |
* Update opt groups.
|
1598 |
*/
|
1599 |
-
updateOptGroups: function() {
|
1600 |
-
var $groups = $('
|
1601 |
var selectedClass = this.options.selectedClass;
|
1602 |
|
1603 |
-
$groups.each(function() {
|
1604 |
-
var $options = $(this).nextUntil('
|
1605 |
.not('.multiselect-filter-hidden')
|
1606 |
.not('.disabled');
|
1607 |
|
1608 |
var checked = true;
|
1609 |
-
$options.each(function() {
|
1610 |
var $input = $('input', this);
|
1611 |
|
1612 |
if (!$input.prop('checked')) {
|
@@ -1630,21 +1868,21 @@
|
|
1630 |
/**
|
1631 |
* Updates the select all checkbox based on the currently displayed and selected checkboxes.
|
1632 |
*/
|
1633 |
-
updateSelectAll: function(notTriggerOnSelectAll) {
|
1634 |
if (this.hasSelectAll()) {
|
1635 |
-
var allBoxes = $("
|
1636 |
var allBoxesLength = allBoxes.length;
|
1637 |
var checkedBoxesLength = allBoxes.filter(":checked").length;
|
1638 |
-
var
|
1639 |
-
var selectAllInput =
|
1640 |
|
1641 |
if (checkedBoxesLength > 0 && checkedBoxesLength === allBoxesLength) {
|
1642 |
selectAllInput.prop("checked", true);
|
1643 |
-
|
1644 |
}
|
1645 |
else {
|
1646 |
selectAllInput.prop("checked", false);
|
1647 |
-
|
1648 |
}
|
1649 |
}
|
1650 |
},
|
@@ -1652,7 +1890,7 @@
|
|
1652 |
/**
|
1653 |
* Update the button text and its title based on the currently selected options.
|
1654 |
*/
|
1655 |
-
updateButtonText: function() {
|
1656 |
var options = this.getSelected();
|
1657 |
|
1658 |
// First update the displayed button text.
|
@@ -1665,6 +1903,7 @@
|
|
1665 |
|
1666 |
// Now update the title attribute of the button.
|
1667 |
$('.multiselect', this.$container).attr('title', this.options.buttonTitle(options, this.$select));
|
|
|
1668 |
},
|
1669 |
|
1670 |
/**
|
@@ -1672,7 +1911,7 @@
|
|
1672 |
*
|
1673 |
* @returns {jQUery}
|
1674 |
*/
|
1675 |
-
getSelected: function() {
|
1676 |
return $('option', this.$select).filter(":selected");
|
1677 |
},
|
1678 |
|
@@ -1703,7 +1942,7 @@
|
|
1703 |
*/
|
1704 |
getInputByValue: function (value) {
|
1705 |
|
1706 |
-
var checkboxes = $('
|
1707 |
var valueToCompare = value.toString();
|
1708 |
|
1709 |
for (var i = 0; i < checkboxes.length; i = i + 1) {
|
@@ -1717,25 +1956,36 @@
|
|
1717 |
/**
|
1718 |
* Used for knockout integration.
|
1719 |
*/
|
1720 |
-
updateOriginalOptions: function() {
|
1721 |
this.originalOptions = this.$select.clone()[0].options;
|
1722 |
},
|
1723 |
|
1724 |
-
asyncFunction: function(callback, timeout, self) {
|
1725 |
var args = Array.prototype.slice.call(arguments, 3);
|
1726 |
-
return setTimeout(function() {
|
1727 |
callback.apply(self || window, args);
|
1728 |
}, timeout);
|
1729 |
},
|
1730 |
|
1731 |
-
setAllSelectedText: function(allSelectedText) {
|
1732 |
this.options.allSelectedText = allSelectedText;
|
1733 |
this.updateButtonText();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1734 |
}
|
1735 |
};
|
1736 |
|
1737 |
-
$.fn.multiselect = function(option, parameter, extraOptions) {
|
1738 |
-
return this.each(function() {
|
1739 |
var data = $(this).data('multiselect');
|
1740 |
var options = typeof option === 'object' && option;
|
1741 |
|
@@ -1758,8 +2008,8 @@
|
|
1758 |
|
1759 |
$.fn.multiselect.Constructor = Multiselect;
|
1760 |
|
1761 |
-
$(function() {
|
1762 |
$("select[data-role=multiselect]").multiselect();
|
1763 |
});
|
1764 |
|
1765 |
-
}
|
2 |
* Bootstrap Multiselect (http://davidstutz.de/bootstrap-multiselect/)
|
3 |
*
|
4 |
* Apache License, Version 2.0:
|
5 |
+
* Copyright (c) 2012 - 2021 David Stutz
|
6 |
*
|
7 |
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
|
8 |
* use this file except in compliance with the License. You may obtain a
|
15 |
* under the License.
|
16 |
*
|
17 |
* BSD 3-Clause License:
|
18 |
+
* Copyright (c) 2012 - 2021 David Stutz
|
19 |
* All rights reserved.
|
20 |
*
|
21 |
* Redistribution and use in source and binary forms, with or without
|
41 |
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
42 |
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
43 |
*/
|
44 |
+
(function (root, factory) {
|
45 |
+
// check to see if 'knockout' AMD module is specified if using requirejs
|
46 |
+
if (typeof define === 'function' && define.amd &&
|
47 |
+
typeof require === 'function' && typeof require.specified === 'function' && require.specified('knockout')) {
|
48 |
+
|
49 |
+
// AMD. Register as an anonymous module.
|
50 |
+
define(['jquery', 'knockout'], factory);
|
51 |
+
} else {
|
52 |
+
// Browser globals
|
53 |
+
factory(root.jQuery, root.ko);
|
54 |
+
}
|
55 |
+
})(this, function ($, ko) {
|
56 |
"use strict";// jshint ;_;
|
57 |
|
58 |
if (typeof ko !== 'undefined' && ko.bindingHandlers && !ko.bindingHandlers.multiselect) {
|
59 |
ko.bindingHandlers.multiselect = {
|
60 |
after: ['options', 'value', 'selectedOptions', 'enable', 'disable'],
|
61 |
|
62 |
+
init: function (element, valueAccessor, allBindings, viewModel, bindingContext) {
|
63 |
var $element = $(element);
|
64 |
var config = ko.toJS(valueAccessor());
|
65 |
|
69 |
var options = allBindings.get('options');
|
70 |
if (ko.isObservable(options)) {
|
71 |
ko.computed({
|
72 |
+
read: function () {
|
73 |
options();
|
74 |
+
setTimeout(function () {
|
75 |
var ms = $element.data('multiselect');
|
76 |
if (ms)
|
77 |
ms.updateOriginalOptions();//Not sure how beneficial this is.
|
90 |
var value = allBindings.get('value');
|
91 |
if (ko.isObservable(value)) {
|
92 |
ko.computed({
|
93 |
+
read: function () {
|
94 |
value();
|
95 |
+
setTimeout(function () {
|
96 |
$element.multiselect('refresh');
|
97 |
}, 1);
|
98 |
},
|
107 |
var selectedOptions = allBindings.get('selectedOptions');
|
108 |
if (ko.isObservable(selectedOptions)) {
|
109 |
ko.computed({
|
110 |
+
read: function () {
|
111 |
selectedOptions();
|
112 |
+
setTimeout(function () {
|
113 |
$element.multiselect('refresh');
|
114 |
}, 1);
|
115 |
},
|
155 |
}
|
156 |
}
|
157 |
|
158 |
+
ko.utils.domNodeDisposal.addDisposeCallback(element, function () {
|
159 |
$element.multiselect('destroy');
|
160 |
});
|
161 |
},
|
162 |
|
163 |
+
update: function (element, valueAccessor, allBindings, viewModel, bindingContext) {
|
164 |
var $element = $(element);
|
165 |
var config = ko.toJS(valueAccessor());
|
166 |
|
219 |
this.buildSelectAll();
|
220 |
this.buildDropdownOptions();
|
221 |
this.buildFilter();
|
222 |
+
this.buildButtons();
|
223 |
|
224 |
this.updateButtonText();
|
225 |
this.updateSelectAll(true);
|
229 |
}
|
230 |
|
231 |
this.options.wasDisabled = this.$select.prop('disabled');
|
232 |
+
if (this.options.disableIfEmpty && $('option', this.$select).length <= 0 && !this.options.wasDisabled) {
|
233 |
+
this.disable(true);
|
234 |
}
|
235 |
|
236 |
this.$select.wrap('<span class="multiselect-native-select" />').after(this.$container);
|
237 |
+
this.$select.prop('tabindex', '-1');
|
238 |
+
|
239 |
+
if (this.options.widthSynchronizationMode !== 'never') {
|
240 |
+
this.synchronizeButtonAndPopupWidth();
|
241 |
+
}
|
242 |
+
|
243 |
this.options.onInitialized(this.$select, this.$container);
|
244 |
}
|
245 |
|
255 |
* @param {jQuery} select
|
256 |
* @returns {String}
|
257 |
*/
|
258 |
+
buttonText: function (selectedOptions, select) {
|
259 |
+
if (this.disabledText.length > 0 && select.prop('disabled')) {
|
|
|
|
|
260 |
return this.disabledText;
|
261 |
}
|
262 |
+
else if (selectedOptions.length === 0) {
|
263 |
return this.nonSelectedText;
|
264 |
}
|
265 |
else if (this.allSelectedText
|
266 |
+
&& selectedOptions.length === $('option', $(select)).length
|
267 |
+
&& $('option', $(select)).length !== 1
|
268 |
+
&& this.multiple) {
|
269 |
|
270 |
if (this.selectAllNumber) {
|
271 |
+
return this.allSelectedText + ' (' + selectedOptions.length + ')';
|
272 |
}
|
273 |
else {
|
274 |
return this.allSelectedText;
|
275 |
}
|
276 |
}
|
277 |
+
else if (this.numberDisplayed != 0 && selectedOptions.length > this.numberDisplayed) {
|
278 |
+
return selectedOptions.length + ' ' + this.nSelectedText;
|
279 |
}
|
280 |
else {
|
281 |
var selected = '';
|
282 |
var delimiter = this.delimiterText;
|
283 |
|
284 |
+
selectedOptions.each(function () {
|
285 |
var label = ($(this).attr('label') !== undefined) ? $(this).attr('label') : $(this).text();
|
286 |
selected += label + delimiter;
|
287 |
});
|
296 |
* @param {jQuery} select
|
297 |
* @returns {@exp;selected@call;substr}
|
298 |
*/
|
299 |
+
buttonTitle: function (options, select) {
|
300 |
if (options.length === 0) {
|
301 |
return this.nonSelectedText;
|
302 |
}
|
311 |
return selected.substr(0, selected.length - this.delimiterText.length);
|
312 |
}
|
313 |
},
|
314 |
+
checkboxName: function (option) {
|
315 |
return false; // no checkbox name
|
316 |
},
|
317 |
/**
|
320 |
* @param {jQuery} element
|
321 |
* @returns {String}
|
322 |
*/
|
323 |
+
optionLabel: function (element) {
|
324 |
return $(element).attr('label') || $(element).text();
|
325 |
},
|
326 |
/**
|
329 |
* @param {jQuery} element
|
330 |
* @returns {String}
|
331 |
*/
|
332 |
+
optionClass: function (element) {
|
333 |
return $(element).attr('class') || '';
|
334 |
},
|
335 |
/**
|
340 |
* @param {jQuery} option
|
341 |
* @param {Boolean} checked
|
342 |
*/
|
343 |
+
onChange: function (option, checked) {
|
344 |
|
345 |
},
|
346 |
/**
|
348 |
*
|
349 |
* @param {jQuery} event
|
350 |
*/
|
351 |
+
onDropdownShow: function (event) {
|
352 |
|
353 |
},
|
354 |
/**
|
356 |
*
|
357 |
* @param {jQuery} event
|
358 |
*/
|
359 |
+
onDropdownHide: function (event) {
|
360 |
|
361 |
},
|
362 |
/**
|
364 |
*
|
365 |
* @param {jQuery} event
|
366 |
*/
|
367 |
+
onDropdownShown: function (event) {
|
368 |
|
369 |
},
|
370 |
/**
|
372 |
*
|
373 |
* @param {jQuery} event
|
374 |
*/
|
375 |
+
onDropdownHidden: function (event) {
|
376 |
|
377 |
},
|
378 |
/**
|
379 |
* Triggered on select all.
|
380 |
*/
|
381 |
+
onSelectAll: function () {
|
382 |
|
383 |
},
|
384 |
/**
|
385 |
* Triggered on deselect all.
|
386 |
*/
|
387 |
+
onDeselectAll: function () {
|
388 |
|
389 |
},
|
390 |
/**
|
393 |
* @param {jQuery} $select
|
394 |
* @param {jQuery} $container
|
395 |
*/
|
396 |
+
onInitialized: function ($select, $container) {
|
397 |
|
398 |
},
|
399 |
/**
|
401 |
*
|
402 |
* @param {jQuery} $filter
|
403 |
*/
|
404 |
+
onFiltering: function ($filter) {
|
405 |
|
406 |
},
|
407 |
enableHTML: false,
|
408 |
+
buttonClass: 'custom-select',
|
409 |
inheritClass: false,
|
410 |
buttonWidth: 'auto',
|
411 |
buttonContainer: '<div class="btn-group" />',
|
436 |
nonSelectedText: 'None selected',
|
437 |
nSelectedText: 'selected',
|
438 |
allSelectedText: 'All selected',
|
439 |
+
resetButtonText: 'Reset',
|
440 |
numberDisplayed: 3,
|
441 |
disableIfEmpty: false,
|
442 |
disabledText: '',
|
444 |
includeResetOption: false,
|
445 |
includeResetDivider: false,
|
446 |
resetText: 'Reset',
|
447 |
+
indentGroupOptions: true,
|
448 |
+
// possible options: 'never', 'always', 'ifPopupIsSmaller', 'ifPopupIsWider'
|
449 |
+
widthSynchronizationMode: 'never',
|
450 |
+
buttonTextAlignment: 'center',
|
451 |
+
enableResetButton: false,
|
452 |
templates: {
|
453 |
+
button: '<button type="button" class="multiselect dropdown-toggle" data-toggle="dropdown"><span class="multiselect-selected-text"></span></button>',
|
454 |
+
popupContainer: '<div class="multiselect-container dropdown-menu"></div>',
|
455 |
+
filter: '<div class="multiselect-filter d-flex align-items-center"><i class="fas fa-sm fa-search text-muted"></i><input type="search" class="multiselect-search form-control" /></div>',
|
456 |
+
buttonGroup: '<div class="multiselect-buttons btn-group" style="display:flex;"></div>',
|
457 |
+
buttonGroupReset: '<button type="button" class="multiselect-reset btn btn-secondary btn-block"></button>',
|
458 |
+
option: '<button type="button" class="multiselect-option dropdown-item"></button>',
|
459 |
+
divider: '<div class="dropdown-divider"></div>',
|
460 |
+
optionGroup: '<button type="button" class="multiselect-group dropdown-item"></button>',
|
461 |
+
resetButton: '<div class="multiselect-reset text-center p-2"><button type="button" class="btn btn-sm btn-block btn-outline-secondary"></button></div>'
|
462 |
}
|
463 |
},
|
464 |
|
467 |
/**
|
468 |
* Builds the container of the multiselect.
|
469 |
*/
|
470 |
+
buildContainer: function () {
|
471 |
this.$container = $(this.options.buttonContainer);
|
472 |
+
if (this.options.widthSynchronizationMode !== 'never') {
|
473 |
+
this.$container.on('show.bs.dropdown', $.proxy(function () {
|
474 |
+
// the width needs to be synchronized again in case the width of the button changed in between
|
475 |
+
this.synchronizeButtonAndPopupWidth();
|
476 |
+
this.options.onDropdownShow();
|
477 |
+
}, this));
|
478 |
+
}
|
479 |
+
else {
|
480 |
+
this.$container.on('show.bs.dropdown', this.options.onDropdownShow);
|
481 |
+
}
|
482 |
this.$container.on('hide.bs.dropdown', this.options.onDropdownHide);
|
483 |
this.$container.on('shown.bs.dropdown', this.options.onDropdownShown);
|
484 |
this.$container.on('hidden.bs.dropdown', this.options.onDropdownHidden);
|
487 |
/**
|
488 |
* Builds the button of the multiselect.
|
489 |
*/
|
490 |
+
buildButton: function () {
|
491 |
this.$button = $(this.options.templates.button).addClass(this.options.buttonClass);
|
492 |
if (this.$select.attr('class') && this.options.inheritClass) {
|
493 |
this.$button.addClass(this.$select.attr('class'));
|
503 |
// Manually add button width if set.
|
504 |
if (this.options.buttonWidth && this.options.buttonWidth !== 'auto') {
|
505 |
this.$button.css({
|
506 |
+
'width': '100%' //this.options.buttonWidth,
|
|
|
|
|
507 |
});
|
508 |
this.$container.css({
|
509 |
'width': this.options.buttonWidth
|
510 |
});
|
511 |
}
|
512 |
|
513 |
+
if (this.options.buttonTextAlignment) {
|
514 |
+
switch (this.options.buttonTextAlignment) {
|
515 |
+
case 'left':
|
516 |
+
this.$button.addClass('text-left');
|
517 |
+
break;
|
518 |
+
case 'center':
|
519 |
+
this.$button.addClass('text-center');
|
520 |
+
break;
|
521 |
+
case 'right':
|
522 |
+
this.$button.addClass('text-right');
|
523 |
+
break;
|
524 |
+
}
|
525 |
+
}
|
526 |
+
|
527 |
// Keep the tab index from the select.
|
528 |
var tabindex = this.$select.attr('tabindex');
|
529 |
if (tabindex) {
|
534 |
},
|
535 |
|
536 |
/**
|
537 |
+
* Builds the popup container representing the dropdown menu.
|
538 |
*/
|
539 |
+
buildDropdown: function () {
|
540 |
|
541 |
+
// Build popup container.
|
542 |
+
this.$popupContainer = $(this.options.templates.popupContainer);
|
543 |
|
544 |
if (this.options.dropRight) {
|
545 |
+
this.$container.addClass('dropright');
|
546 |
+
}
|
547 |
+
else if (this.options.dropUp) {
|
548 |
+
this.$container.addClass("dropup");
|
549 |
}
|
550 |
|
551 |
// Set max height of dropdown menu to activate auto scrollbar.
|
552 |
if (this.options.maxHeight) {
|
553 |
// TODO: Add a class for this option to move the css declarations.
|
554 |
+
this.$popupContainer.css({
|
555 |
'max-height': this.options.maxHeight + 'px',
|
556 |
'overflow-y': 'auto',
|
557 |
'overflow-x': 'hidden'
|
558 |
});
|
559 |
}
|
560 |
|
561 |
+
if (this.options.widthSynchronizationMode !== 'never') {
|
562 |
+
this.$popupContainer.css('overflow-x', 'hidden');
|
563 |
+
}
|
564 |
|
565 |
+
this.$popupContainer.on("touchstart click", function (e) {
|
566 |
+
e.stopPropagation();
|
567 |
+
});
|
568 |
|
569 |
+
this.$container.append(this.$popupContainer);
|
570 |
+
},
|
571 |
+
|
572 |
+
synchronizeButtonAndPopupWidth: function () {
|
573 |
+
if (!this.$popupContainer || this.options.widthSynchronizationMode === 'never') {
|
574 |
+
return;
|
575 |
}
|
576 |
|
577 |
+
var buttonWidth = this.$button.outerWidth();
|
578 |
+
switch (this.options.widthSynchronizationMode) {
|
579 |
+
case 'always':
|
580 |
+
this.$popupContainer.css('min-width', buttonWidth);
|
581 |
+
this.$popupContainer.css('max-width', buttonWidth);
|
582 |
+
break;
|
583 |
+
case 'ifPopupIsSmaller':
|
584 |
+
this.$popupContainer.css('min-width', buttonWidth);
|
585 |
+
break;
|
586 |
+
case 'ifPopupIsWider':
|
587 |
+
this.$popupContainer.css('max-width', buttonWidth);
|
588 |
+
break;
|
589 |
+
}
|
590 |
},
|
591 |
|
592 |
/**
|
594 |
*
|
595 |
* Uses createDivider and createOptionValue to create the necessary options.
|
596 |
*/
|
597 |
+
buildDropdownOptions: function () {
|
598 |
|
599 |
+
this.$select.children().each($.proxy(function (index, element) {
|
600 |
|
601 |
var $element = $(element);
|
602 |
// Support optgroups and options without a group simultaneously.
|
616 |
this.createDivider();
|
617 |
}
|
618 |
else {
|
619 |
+
this.createOptionValue(element, false);
|
620 |
}
|
621 |
|
622 |
}
|
625 |
}, this));
|
626 |
|
627 |
// Bind the change event on the dropdown elements.
|
628 |
+
$(this.$popupContainer).off('change', '> *:not(.multiselect-group) input[type="checkbox"], > *:not(.multiselect-group) input[type="radio"]');
|
629 |
+
$(this.$popupContainer).on('change', '> *:not(.multiselect-group) input[type="checkbox"], > *:not(.multiselect-group) input[type="radio"]', $.proxy(function (event) {
|
630 |
var $target = $(event.target);
|
631 |
|
632 |
var checked = $target.prop('checked') || false;
|
635 |
// Apply or unapply the configured selected class.
|
636 |
if (this.options.selectedClass) {
|
637 |
if (checked) {
|
638 |
+
$target.closest('.multiselect-option')
|
639 |
.addClass(this.options.selectedClass);
|
640 |
}
|
641 |
else {
|
642 |
+
$target.closest('.multiselect-option')
|
643 |
.removeClass(this.options.selectedClass);
|
644 |
}
|
645 |
}
|
671 |
else {
|
672 |
// Unselect all other options and corresponding checkboxes.
|
673 |
if (this.options.selectedClass) {
|
674 |
+
$($checkboxesNotThis).closest('.dropdown-item').removeClass(this.options.selectedClass);
|
675 |
}
|
676 |
|
677 |
$($checkboxesNotThis).prop('checked', false);
|
682 |
}
|
683 |
|
684 |
if (this.options.selectedClass === "active") {
|
685 |
+
$optionsNotThis.closest(".dropdown-item").css("outline", "");
|
686 |
}
|
687 |
}
|
688 |
else {
|
704 |
this.$select.change();
|
705 |
this.updateButtonText();
|
706 |
|
707 |
+
if (this.options.preventInputChangeEvent) {
|
708 |
return false;
|
709 |
}
|
710 |
}, this));
|
711 |
|
712 |
+
$('.multiselect-option', this.$popupContainer).off('mousedown');
|
713 |
+
$('.multiselect-option', this.$popupContainer).on('mousedown', function (e) {
|
714 |
if (e.shiftKey) {
|
715 |
// Prevent selecting text by Shift+click
|
716 |
return false;
|
717 |
}
|
718 |
});
|
719 |
|
720 |
+
$(this.$popupContainer).off('touchstart click', '.multiselect-option, .multiselect-all, .multiselect-group');
|
721 |
+
$(this.$popupContainer).on('touchstart click', '.multiselect-option, .multiselect-all, .multiselect-group', $.proxy(function (event) {
|
722 |
event.stopPropagation();
|
723 |
|
724 |
var $target = $(event.target);
|
725 |
|
726 |
if (event.shiftKey && this.options.multiple) {
|
727 |
+
if (!$target.is("input")) { // Handles checkbox selection manually (see https://github.com/davidstutz/bootstrap-multiselect/issues/431)
|
728 |
event.preventDefault();
|
729 |
+
$target = $target.closest(".multiselect-option").find("input");
|
730 |
$target.prop("checked", !$target.prop("checked"));
|
731 |
}
|
732 |
var checked = $target.prop('checked') || false;
|
733 |
|
734 |
if (this.lastToggledInput !== null && this.lastToggledInput !== $target) { // Make sure we actually have a range
|
735 |
+
var from = this.$popupContainer.find(".multiselect-option:visible").index($target.closest(".multiselect-option"));
|
736 |
+
var to = this.$popupContainer.find(".multiselect-option:visible").index(this.lastToggledInput.closest(".multiselect-option"));
|
737 |
|
738 |
if (from > to) { // Swap the indices
|
739 |
var tmp = to;
|
745 |
++to;
|
746 |
|
747 |
// Change the checkboxes and underlying options
|
748 |
+
var range = this.$popupContainer.find(".multiselect-option:not(.multiselect-filter-hidden)").slice(from, to).find("input");
|
749 |
|
750 |
range.prop('checked', checked);
|
751 |
|
752 |
if (this.options.selectedClass) {
|
753 |
+
range.closest('.multiselect-option')
|
754 |
.toggleClass(this.options.selectedClass, checked);
|
755 |
}
|
756 |
|
766 |
// Trigger the select "change" event
|
767 |
$target.trigger("change");
|
768 |
}
|
769 |
+
else if (!$target.is('input')) {
|
770 |
+
var $checkbox = $target.closest('.multiselect-option, .multiselect-all').find('.form-check-input');
|
771 |
+
if ($checkbox.length > 0) {
|
772 |
+
if (this.options.multiple || !$checkbox.prop('checked')) {
|
773 |
+
$checkbox.prop('checked', !$checkbox.prop('checked'));
|
774 |
+
$checkbox.change();
|
775 |
+
}
|
776 |
+
}
|
777 |
+
else if (this.options.enableClickableOptGroups && this.options.multiple && !$target.hasClass("caret-container")) {
|
778 |
+
var groupItem = $target;
|
779 |
+
if (!groupItem.hasClass("multiselect-group")) {
|
780 |
+
groupItem = $target.closest('.multiselect-group');
|
781 |
+
}
|
782 |
+
$checkbox = groupItem.find(".form-check-input");
|
783 |
+
if ($checkbox.length > 0) {
|
784 |
+
$checkbox.prop('checked', !$checkbox.prop('checked'));
|
785 |
+
$checkbox.change();
|
786 |
+
}
|
787 |
+
}
|
788 |
+
|
789 |
+
event.preventDefault();
|
790 |
+
}
|
791 |
|
792 |
// Remembers last clicked option
|
793 |
+
var $input = $target.closest(".multiselect-option").find("input[type='checkbox'], input[type='radio']");
|
794 |
+
if ($input.length > 0) {
|
795 |
this.lastToggledInput = $target;
|
796 |
}
|
797 |
+
else {
|
798 |
+
this.lastToggledInput = null;
|
799 |
+
}
|
800 |
|
801 |
+
$target.blur();
|
802 |
}, this));
|
803 |
|
804 |
+
//Keyboard support.
|
805 |
+
this.$container.off('keydown.multiselect').on('keydown.multiselect', $.proxy(function (event) {
|
806 |
+
var $items = $(this.$container).find(".multiselect-option:not(.disabled), .multiselect-group:not(.disabled), .multiselect-all").filter(":visible");
|
807 |
+
var index = $items.index($items.filter(':focus'));
|
808 |
+
var $search = $('.multiselect-search', this.$container);
|
809 |
|
810 |
+
// keyCode 9 == Tab
|
811 |
+
if (event.keyCode === 9 && this.$container.hasClass('show')) {
|
812 |
this.$button.click();
|
813 |
}
|
814 |
+
// keyCode 13 = Enter
|
815 |
+
else if (event.keyCode == 13) {
|
816 |
+
var $current = $items.eq(index);
|
817 |
+
setTimeout(function () {
|
818 |
+
$current.focus();
|
819 |
+
}, 1);
|
820 |
+
}
|
821 |
+
// keyCode 38 = Arrow Up
|
822 |
+
else if (event.keyCode == 38) {
|
823 |
+
if (index == 0 && !$search.is(':focus')) {
|
824 |
+
setTimeout(function () {
|
825 |
+
$search.focus();
|
826 |
+
}, 1);
|
827 |
}
|
828 |
+
}
|
829 |
+
// keyCode 40 = Arrow Down
|
830 |
+
else if (event.keyCode == 40) {
|
831 |
+
if ($search.is(':focus')) {
|
832 |
+
var $first = $items.eq(0);
|
833 |
+
setTimeout(function () {
|
834 |
+
$search.blur();
|
835 |
+
$first.focus();
|
836 |
+
}, 1);
|
837 |
}
|
838 |
+
else if (index == -1) {
|
839 |
+
setTimeout(function () {
|
840 |
+
$search.focus();
|
841 |
+
}, 1);
|
842 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
843 |
}
|
844 |
}, this));
|
845 |
|
846 |
if (this.options.enableClickableOptGroups && this.options.multiple) {
|
847 |
+
$(".multiselect-group input", this.$popupContainer).off("change");
|
848 |
+
$(".multiselect-group input", this.$popupContainer).on("change", $.proxy(function (event) {
|
849 |
event.stopPropagation();
|
850 |
|
851 |
var $target = $(event.target);
|
852 |
var checked = $target.prop('checked') || false;
|
853 |
|
854 |
+
var $item = $(event.target).closest('.dropdown-item');
|
855 |
+
var $group = $item.nextUntil(".multiselect-group")
|
856 |
.not('.multiselect-filter-hidden')
|
857 |
.not('.disabled');
|
858 |
|
859 |
var $inputs = $group.find("input");
|
860 |
|
|
|
861 |
var $options = [];
|
862 |
|
863 |
if (this.options.selectedClass) {
|
864 |
if (checked) {
|
865 |
+
$item.addClass(this.options.selectedClass);
|
866 |
}
|
867 |
else {
|
868 |
+
$item.removeClass(this.options.selectedClass);
|
869 |
}
|
870 |
}
|
871 |
|
872 |
+
$.each($inputs, $.proxy(function (index, input) {
|
873 |
+
var $input = $(input);
|
874 |
+
var value = $input.val();
|
875 |
var $option = this.getOptionByValue(value);
|
876 |
|
877 |
if (checked) {
|
878 |
+
$input.prop('checked', true);
|
879 |
+
$input.closest('.dropdown-item')
|
880 |
.addClass(this.options.selectedClass);
|
881 |
|
882 |
$option.prop('selected', true);
|
883 |
}
|
884 |
else {
|
885 |
+
$input.prop('checked', false);
|
886 |
+
$input.closest('.dropdown-item')
|
887 |
.removeClass(this.options.selectedClass);
|
888 |
|
889 |
$option.prop('selected', false);
|
903 |
}
|
904 |
|
905 |
if (this.options.enableCollapsibleOptGroups && this.options.multiple) {
|
906 |
+
$(".multiselect-group .caret-container", this.$popupContainer).off("click");
|
907 |
+
$(".multiselect-group .caret-container", this.$popupContainer).on("click", $.proxy(function (event) {
|
908 |
+
var $group = $(event.target).closest('.multiselect-group');
|
909 |
+
var $inputs = $group.nextUntil(".multiselect-group")
|
910 |
+
.not('.multiselect-filter-hidden');
|
911 |
|
912 |
var visible = true;
|
913 |
+
$inputs.each(function () {
|
914 |
visible = visible && !$(this).hasClass('multiselect-collapsible-hidden');
|
915 |
});
|
916 |
|
923 |
.removeClass('multiselect-collapsible-hidden');
|
924 |
}
|
925 |
}, this));
|
926 |
+
}
|
927 |
+
},
|
928 |
+
|
929 |
+
/**
|
930 |
+
* Create a checkbox container with input and label based on given values
|
931 |
+
* @param {JQuery} $item
|
932 |
+
* @param {String} label
|
933 |
+
* @param {String} name
|
934 |
+
* @param {String} value
|
935 |
+
* @param {String} inputType
|
936 |
+
* @returns {JQuery}
|
937 |
+
*/
|
938 |
+
createCheckbox: function ($item, labelContent, name, value, title, inputType) {
|
939 |
+
var $wrapper = $('<span />');
|
940 |
+
$wrapper.addClass("form-check");
|
941 |
+
|
942 |
+
if (this.options.enableHTML && $(labelContent).length > 0) {
|
943 |
+
var $checkboxLabel = $('<label class="form-check-label" />');
|
944 |
+
$checkboxLabel.html(labelContent);
|
945 |
+
$wrapper.append($checkboxLabel);
|
946 |
+
}
|
947 |
+
else {
|
948 |
+
var $checkboxLabel = $('<label class="form-check-label" />');
|
949 |
+
$checkboxLabel.text(labelContent);
|
950 |
+
$wrapper.append($checkboxLabel);
|
951 |
+
}
|
952 |
|
953 |
+
var $checkbox = $('<input class="form-check-input"/>').attr('type', inputType);
|
954 |
+
$checkbox.val(value);
|
955 |
+
$wrapper.prepend($checkbox);
|
956 |
+
|
957 |
+
if (name) {
|
958 |
+
$checkbox.attr('name', name);
|
959 |
}
|
960 |
+
|
961 |
+
$item.prepend($wrapper);
|
962 |
+
$item.attr("title", title || labelContent);
|
963 |
+
|
964 |
+
return $checkbox;
|
965 |
},
|
966 |
|
967 |
/**
|
969 |
*
|
970 |
* @param {jQuery} element
|
971 |
*/
|
972 |
+
createOptionValue: function (element, isGroupOption) {
|
973 |
var $element = $(element);
|
974 |
if ($element.is(':selected')) {
|
975 |
$element.prop('selected', true);
|
980 |
var classes = this.options.optionClass(element);
|
981 |
var value = $element.val();
|
982 |
var inputType = this.options.multiple ? "checkbox" : "radio";
|
983 |
+
var title = $element.attr('title');
|
984 |
|
985 |
+
var $option = $(this.options.templates.option);
|
986 |
+
$option.addClass(classes);
|
|
|
|
|
|
|
987 |
|
988 |
+
if (isGroupOption && this.options.indentGroupOptions) {
|
989 |
+
$option.addClass("multiselect-group-option-indented")
|
|
|
|
|
990 |
}
|
991 |
|
992 |
+
// Hide all children items when collapseOptGroupsByDefault is true
|
993 |
+
if (this.options.collapseOptGroupsByDefault && $(element).parent().prop("tagName").toLowerCase() === "optgroup") {
|
994 |
+
$option.addClass("multiselect-collapsible-hidden");
|
995 |
+
$option.hide();
|
|
|
996 |
}
|
997 |
|
|
|
|
|
998 |
var name = this.options.checkboxName($element);
|
999 |
+
var $checkbox = this.createCheckbox($option, label, name, value, title, inputType);
|
|
|
|
|
|
|
|
|
1000 |
|
1001 |
var selected = $element.prop('selected') || false;
|
|
|
1002 |
|
1003 |
if (value === this.options.selectAllValue) {
|
1004 |
+
$option.addClass("multiselect-all");
|
1005 |
+
$option.removeClass("multiselect-option");
|
1006 |
$checkbox.parent().parent()
|
1007 |
.addClass('multiselect-all');
|
1008 |
}
|
1009 |
|
1010 |
+
this.$popupContainer.append($option);
|
|
|
|
|
1011 |
|
1012 |
if ($element.is(':disabled')) {
|
1013 |
$checkbox.attr('disabled', 'disabled')
|
1014 |
.prop('disabled', true)
|
1015 |
+
.closest('.dropdown-item')
|
|
|
|
|
1016 |
.addClass('disabled');
|
1017 |
}
|
1018 |
|
1019 |
$checkbox.prop('checked', selected);
|
1020 |
|
1021 |
if (selected && this.options.selectedClass) {
|
1022 |
+
$checkbox.closest('.dropdown-item')
|
1023 |
.addClass(this.options.selectedClass);
|
1024 |
}
|
1025 |
},
|
1029 |
*
|
1030 |
* @param {jQuery} element
|
1031 |
*/
|
1032 |
+
createDivider: function (element) {
|
1033 |
var $divider = $(this.options.templates.divider);
|
1034 |
+
this.$popupContainer.append($divider);
|
1035 |
},
|
1036 |
|
1037 |
/**
|
1039 |
*
|
1040 |
* @param {jQuery} group
|
1041 |
*/
|
1042 |
+
createOptgroup: function (group) {
|
1043 |
+
var $group = $(group);
|
1044 |
+
var label = $group.attr("label");
|
1045 |
+
var value = $group.attr("value");
|
1046 |
+
var title = $group.attr('title');
|
1047 |
|
1048 |
+
var $groupOption = $("<span class='multiselect-group dropdown-item-text'></span>");
|
|
|
1049 |
|
1050 |
+
if (this.options.enableClickableOptGroups && this.options.multiple) {
|
1051 |
+
$groupOption = $(this.options.templates.optionGroup);
|
1052 |
+
var $checkbox = this.createCheckbox($groupOption, label, null, value, title, "checkbox");
|
1053 |
}
|
1054 |
else {
|
1055 |
+
if (this.options.enableHTML) {
|
1056 |
+
$groupOption.html(" " + label);
|
1057 |
+
}
|
1058 |
+
else {
|
1059 |
+
$groupOption.text(" " + label);
|
1060 |
+
}
|
1061 |
}
|
1062 |
|
1063 |
+
var classes = this.options.optionClass(group);
|
1064 |
+
$groupOption.addClass(classes);
|
|
|
1065 |
|
1066 |
+
if (this.options.enableCollapsibleOptGroups && this.options.multiple) {
|
1067 |
+
$groupOption.find('.form-check').addClass('d-inline-block');
|
1068 |
+
$groupOption.append('<span class="caret-container dropdown-toggle pl-1"></span>');
|
1069 |
}
|
1070 |
|
1071 |
+
if ($group.is(':disabled')) {
|
1072 |
+
$groupOption.addClass('disabled');
|
1073 |
}
|
1074 |
|
1075 |
+
this.$popupContainer.append($groupOption);
|
1076 |
|
1077 |
+
$("option", group).each($.proxy(function ($, group) {
|
1078 |
+
this.createOptionValue(group, true);
|
1079 |
+
}, this));
|
1080 |
},
|
1081 |
|
1082 |
/**
|
1083 |
* Build the reset.
|
1084 |
*
|
1085 |
*/
|
1086 |
+
buildReset: function () {
|
1087 |
if (this.options.includeResetOption) {
|
1088 |
|
1089 |
// Check whether to add a divider after the reset.
|
1090 |
if (this.options.includeResetDivider) {
|
1091 |
+
var divider = $(this.options.templates.divider);
|
1092 |
+
divider.addClass("mt-0");
|
1093 |
+
this.$popupContainer.prepend(divider);
|
1094 |
}
|
1095 |
|
1096 |
var $resetButton = $(this.options.templates.resetButton);
|
1097 |
|
1098 |
if (this.options.enableHTML) {
|
1099 |
+
$('button', $resetButton).html(this.options.resetText);
|
1100 |
}
|
1101 |
else {
|
1102 |
+
$('button', $resetButton).text(this.options.resetText);
|
1103 |
}
|
1104 |
|
1105 |
+
$('button', $resetButton).click($.proxy(function () {
|
1106 |
this.clearSelection();
|
1107 |
}, this));
|
1108 |
|
1109 |
+
this.$popupContainer.prepend($resetButton);
|
1110 |
}
|
1111 |
},
|
1112 |
|
1115 |
*
|
1116 |
* Checks if a select all has already been created.
|
1117 |
*/
|
1118 |
+
buildSelectAll: function () {
|
1119 |
if (typeof this.options.selectAllValue === 'number') {
|
1120 |
this.options.selectAllValue = this.options.selectAllValue.toString();
|
1121 |
}
|
1123 |
var alreadyHasSelectAll = this.hasSelectAll();
|
1124 |
|
1125 |
if (!alreadyHasSelectAll && this.options.includeSelectAllOption && this.options.multiple
|
1126 |
+
&& $('option', this.$select).length > this.options.includeSelectAllIfMoreThan) {
|
1127 |
|
1128 |
// Check whether to add a divider after the select all.
|
1129 |
if (this.options.includeSelectAllDivider) {
|
1130 |
+
this.$popupContainer.prepend($(this.options.templates.divider));
|
1131 |
}
|
1132 |
|
1133 |
+
var $option = $(this.options.templates.li || this.options.templates.option);
|
1134 |
+
var $checkbox = this.createCheckbox($option, this.options.selectAllText, this.options.selectAllName, this.options.selectAllValue, this.options.selectAllText, "checkbox");
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1135 |
|
1136 |
+
$option.addClass("multiselect-all");
|
1137 |
+
$option.removeClass("multiselect-option");
|
1138 |
+
$option.find(".form-check-label").addClass("font-weight-bold");
|
|
|
|
|
|
|
1139 |
|
1140 |
+
this.$popupContainer.prepend($option);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1141 |
|
1142 |
$checkbox.prop('checked', false);
|
1143 |
}
|
1146 |
/**
|
1147 |
* Builds the filter.
|
1148 |
*/
|
1149 |
+
buildFilter: function () {
|
1150 |
|
1151 |
// Build filter if filtering OR case insensitive filtering is enabled and the number of options exceeds (or equals) enableFilterLength.
|
1152 |
if (this.options.enableFiltering || this.options.enableCaseInsensitiveFiltering) {
|
1157 |
this.$filter = $(this.options.templates.filter);
|
1158 |
$('input', this.$filter).attr('placeholder', this.options.filterPlaceholder);
|
1159 |
|
1160 |
+
// Handles optional filter clear button
|
1161 |
+
if (!this.options.includeFilterClearBtn) {
|
1162 |
+
this.$filter.find(".multiselect-search").attr("type", "text");
|
1163 |
+
|
1164 |
+
// Remove clear button if the old design of the filter with input groups and separated clear button is used
|
1165 |
+
this.$filter.find(".multiselect-clear-filter").remove();
|
1166 |
+
}
|
1167 |
+
else {
|
1168 |
+
// Firefox does not support a clear button in search inputs right now therefore it must be added manually
|
1169 |
+
if (this.isFirefox() && this.$filter.find(".multiselect-clear-filter").length === 0) {
|
1170 |
+
this.$filter.append("<i class='fas fa-times text-muted multiselect-clear-filter multiselect-moz-clear-filter'></i>");
|
1171 |
+
}
|
1172 |
+
|
1173 |
+
this.$filter.find(".multiselect-clear-filter").on('click', $.proxy(function (event) {
|
1174 |
clearTimeout(this.searchTimeout);
|
1175 |
|
1176 |
this.query = '';
|
1177 |
this.$filter.find('.multiselect-search').val('');
|
1178 |
+
$('.dropdown-item', this.$popupContainer).show().removeClass('multiselect-filter-hidden');
|
1179 |
|
1180 |
this.updateSelectAll();
|
1181 |
|
1184 |
}
|
1185 |
|
1186 |
}, this));
|
|
|
1187 |
}
|
1188 |
|
1189 |
+
this.$popupContainer.prepend(this.$filter);
|
1190 |
|
1191 |
+
this.$filter.val(this.query).on('click', function (event) {
|
1192 |
event.stopPropagation();
|
1193 |
+
}).on('input keydown', $.proxy(function (event) {
|
1194 |
// Cancel enter key default behaviour
|
1195 |
if (event.which === 13) {
|
1196 |
+
event.preventDefault();
|
1197 |
+
}
|
1198 |
+
|
1199 |
+
if (this.isFirefox() && this.options.includeFilterClearBtn) {
|
1200 |
+
if (event.target.value) {
|
1201 |
+
this.$filter.find(".multiselect-moz-clear-filter").show();
|
1202 |
+
}
|
1203 |
+
else {
|
1204 |
+
this.$filter.find(".multiselect-moz-clear-filter").hide();
|
1205 |
+
}
|
1206 |
+
}
|
1207 |
|
1208 |
// This is useful to catch "keydown" events after the browser has updated the control.
|
1209 |
clearTimeout(this.searchTimeout);
|
1210 |
|
1211 |
+
this.searchTimeout = this.asyncFunction($.proxy(function () {
|
1212 |
|
1213 |
if (this.query !== event.target.value) {
|
1214 |
this.query = event.target.value;
|
1215 |
|
1216 |
var currentGroup, currentGroupVisible;
|
1217 |
+
$.each($('.multiselect-option, .multiselect-group', this.$popupContainer), $.proxy(function (index, element) {
|
1218 |
var value = $('input', element).length > 0 ? $('input', element).val() : "";
|
1219 |
+
var text = $('.form-check-label', element).text();
|
1220 |
|
1221 |
var filterCandidate = '';
|
1222 |
if ((this.options.filterBehavior === 'text')) {
|
1251 |
}
|
1252 |
|
1253 |
// Toggle current element (group or group item) according to showElement boolean.
|
1254 |
+
if (!showElement) {
|
1255 |
+
$(element).css('display', 'none');
|
1256 |
+
$(element).addClass('multiselect-filter-hidden');
|
1257 |
}
|
1258 |
+
if (showElement) {
|
1259 |
+
$(element).css('display', 'block');
|
1260 |
+
$(element).removeClass('multiselect-filter-hidden');
|
1261 |
}
|
1262 |
|
1263 |
// Differentiate groups and group items.
|
1289 |
this.updateOptGroups();
|
1290 |
}
|
1291 |
|
1292 |
+
this.updatePopupPosition();
|
1293 |
+
|
1294 |
this.options.onFiltering(event.target);
|
1295 |
|
1296 |
}, this), 300, this);
|
1299 |
}
|
1300 |
},
|
1301 |
|
1302 |
+
/**
|
1303 |
+
* Builds the filter.
|
1304 |
+
*/
|
1305 |
+
buildButtons: function () {
|
1306 |
+
if (this.options.enableResetButton) {
|
1307 |
+
var $buttonGroup = $(this.options.templates.buttonGroup);
|
1308 |
+
this.$buttonGroupReset = $(this.options.templates.buttonGroupReset).text(this.options.resetButtonText);
|
1309 |
+
$buttonGroup.append(this.$buttonGroupReset);
|
1310 |
+
this.$popupContainer.prepend($buttonGroup);
|
1311 |
+
|
1312 |
+
// We save all options that were previously selected.
|
1313 |
+
this.defaultSelection = {};
|
1314 |
+
$('option', this.$select).each($.proxy(function(index, element) {
|
1315 |
+
var $option = $(element);
|
1316 |
+
this.defaultSelection[$option.val()] = $option.prop('selected');
|
1317 |
+
}, this));
|
1318 |
+
|
1319 |
+
this.$buttonGroupReset.on('click', $.proxy(function(event) {
|
1320 |
+
$('option', this.$select).each($.proxy(function(index, element) {
|
1321 |
+
var $option = $(element);
|
1322 |
+
$option.prop('selected', this.defaultSelection[$option.val()]);
|
1323 |
+
}, this));
|
1324 |
+
this.refresh();
|
1325 |
+
|
1326 |
+
if (this.options.enableFiltering) {
|
1327 |
+
this.$filter.trigger('keydown');
|
1328 |
+
$('input', this.$filter).val('');
|
1329 |
+
}
|
1330 |
+
}, this));
|
1331 |
+
}
|
1332 |
+
},
|
1333 |
+
|
1334 |
+
updatePopupPosition: function() {
|
1335 |
+
// prevent gaps between popup and select when filter is used (#1199)
|
1336 |
+
var transformMatrix = this.$popupContainer.css("transform");
|
1337 |
+
var matrixType = transformMatrix.substring(0, transformMatrix.indexOf('('));
|
1338 |
+
var values = transformMatrix.substring(transformMatrix.indexOf('(') + 1, transformMatrix.length - 1);
|
1339 |
+
var valuesArray = values.split(',');
|
1340 |
+
|
1341 |
+
var valueIndex = 5;
|
1342 |
+
if(matrixType === "matrix3d") {
|
1343 |
+
valueIndex = 13;
|
1344 |
+
}
|
1345 |
+
|
1346 |
+
var yTransformation = valuesArray[valueIndex];
|
1347 |
+
// Need to check to avoid errors when testing and in some other situations.
|
1348 |
+
yTransformation = typeof yTransformation === 'undefined' ? 0 : yTransformation.trim();
|
1349 |
+
if (yTransformation < 0) {
|
1350 |
+
yTransformation = this.$popupContainer.css("height").replace('px', '') * -1;
|
1351 |
+
valuesArray[valueIndex] = yTransformation;
|
1352 |
+
transformMatrix = matrixType + '(' + valuesArray.join(',') + ')';
|
1353 |
+
this.$popupContainer.css("transform", transformMatrix);
|
1354 |
+
}
|
1355 |
+
},
|
1356 |
+
|
1357 |
/**
|
1358 |
* Unbinds the whole plugin.
|
1359 |
*/
|
1360 |
+
destroy: function () {
|
1361 |
this.$container.remove();
|
1362 |
+
this.$select.unwrap();
|
1363 |
this.$select.show();
|
1364 |
|
1365 |
// reset original state
|
1373 |
*/
|
1374 |
refresh: function () {
|
1375 |
var inputs = {};
|
1376 |
+
$('.multiselect-option input', this.$popupContainer).each(function () {
|
1377 |
+
inputs[$(this).val()] = $(this);
|
1378 |
});
|
1379 |
|
1380 |
$('option', this.$select).each($.proxy(function (index, element) {
|
1385 |
$input.prop('checked', true);
|
1386 |
|
1387 |
if (this.options.selectedClass) {
|
1388 |
+
$input.closest('.multiselect-option')
|
1389 |
.addClass(this.options.selectedClass);
|
1390 |
}
|
1391 |
}
|
1393 |
$input.prop('checked', false);
|
1394 |
|
1395 |
if (this.options.selectedClass) {
|
1396 |
+
$input.closest('.multiselect-option')
|
1397 |
.removeClass(this.options.selectedClass);
|
1398 |
}
|
1399 |
}
|
1401 |
if ($elem.is(":disabled")) {
|
1402 |
$input.attr('disabled', 'disabled')
|
1403 |
.prop('disabled', true)
|
1404 |
+
.closest('.multiselect-option')
|
1405 |
.addClass('disabled');
|
1406 |
}
|
1407 |
else {
|
1408 |
$input.prop('disabled', false)
|
1409 |
+
.closest('.multiselect-option')
|
1410 |
.removeClass('disabled');
|
1411 |
}
|
1412 |
}, this));
|
1428 |
* @param {Array} selectValues
|
1429 |
* @param {Boolean} triggerOnChange
|
1430 |
*/
|
1431 |
+
select: function (selectValues, triggerOnChange) {
|
1432 |
+
if (!$.isArray(selectValues)) {
|
1433 |
selectValues = [selectValues];
|
1434 |
}
|
1435 |
|
1443 |
var $option = this.getOptionByValue(value);
|
1444 |
var $checkbox = this.getInputByValue(value);
|
1445 |
|
1446 |
+
if ($option === undefined || $checkbox === undefined) {
|
1447 |
continue;
|
1448 |
}
|
1449 |
|
|
|
|
|
|
|
|
|
1450 |
if (this.options.selectedClass) {
|
1451 |
+
$checkbox.closest('.dropdown-item')
|
1452 |
.addClass(this.options.selectedClass);
|
1453 |
}
|
1454 |
|
1455 |
$checkbox.prop('checked', true);
|
1456 |
$option.prop('selected', true);
|
1457 |
|
1458 |
+
if (!this.options.multiple) {
|
1459 |
+
var $checkboxesNotThis = $('input', this.$container).not($checkbox);
|
1460 |
+
$($checkboxesNotThis).prop('checked', false);
|
1461 |
+
$($checkboxesNotThis).closest('.multiselect-option').removeClass("active")
|
1462 |
+
|
1463 |
+
var $optionsNotThis = $('option', this.$select).not($option);
|
1464 |
+
$optionsNotThis.prop('selected', false);
|
1465 |
+
}
|
1466 |
+
|
1467 |
if (triggerOnChange) {
|
1468 |
this.options.onChange($option, true);
|
1469 |
}
|
1499 |
* @param {Array} deselectValues
|
1500 |
* @param {Boolean} triggerOnChange
|
1501 |
*/
|
1502 |
+
deselect: function (deselectValues, triggerOnChange) {
|
1503 |
+
if (!this.options.multiple) {
|
1504 |
+
// In single selection mode at least on option needs to be selected
|
1505 |
+
return;
|
1506 |
+
}
|
1507 |
+
|
1508 |
+
if (!$.isArray(deselectValues)) {
|
1509 |
deselectValues = [deselectValues];
|
1510 |
}
|
1511 |
|
1519 |
var $option = this.getOptionByValue(value);
|
1520 |
var $checkbox = this.getInputByValue(value);
|
1521 |
|
1522 |
+
if ($option === undefined || $checkbox === undefined) {
|
1523 |
continue;
|
1524 |
}
|
1525 |
|
1526 |
if (this.options.selectedClass) {
|
1527 |
+
$checkbox.closest('.dropdown-item')
|
1528 |
.removeClass(this.options.selectedClass);
|
1529 |
}
|
1530 |
|
1553 |
* @param {Boolean} triggerOnSelectAll
|
1554 |
*/
|
1555 |
selectAll: function (justVisible, triggerOnSelectAll) {
|
1556 |
+
if (!this.options.multiple) {
|
1557 |
+
// In single selection mode only one option can be selected at a time
|
1558 |
+
return;
|
1559 |
+
}
|
1560 |
|
1561 |
+
// Record all changes, i.e., options selected that were not selected before.
|
1562 |
+
var selected = [];
|
1563 |
var justVisible = typeof justVisible === 'undefined' ? true : justVisible;
|
|
|
|
|
1564 |
|
1565 |
+
if (justVisible) {
|
1566 |
+
var visibleOptions = $(".multiselect-option:not(.disabled):not(.multiselect-filter-hidden)", this.$popupContainer);
|
1567 |
+
$('input:enabled', visibleOptions).prop('checked', true);
|
1568 |
+
visibleOptions.addClass(this.options.selectedClass);
|
1569 |
|
1570 |
+
$('input:enabled', visibleOptions).each($.proxy(function (index, element) {
|
1571 |
var value = $(element).val();
|
1572 |
var option = this.getOptionByValue(value);
|
1573 |
+
if (!$(option).prop('selected')) {
|
1574 |
+
selected.push(option);
|
1575 |
+
}
|
1576 |
$(option).prop('selected', true);
|
1577 |
}, this));
|
1578 |
}
|
1579 |
else {
|
1580 |
+
var allOptions = $(".multiselect-option:not(.disabled)", this.$popupContainer);
|
1581 |
+
$('input:enabled', allOptions).prop('checked', true);
|
1582 |
+
allOptions.addClass(this.options.selectedClass);
|
1583 |
|
1584 |
+
$('input:enabled', allOptions).each($.proxy(function (index, element) {
|
1585 |
var value = $(element).val();
|
1586 |
var option = this.getOptionByValue(value);
|
1587 |
+
if (!$(option).prop('selected')) {
|
1588 |
+
selected.push(option);
|
1589 |
+
}
|
1590 |
$(option).prop('selected', true);
|
1591 |
}, this));
|
1592 |
}
|
1593 |
|
1594 |
+
$('.multiselect-option input[value="' + this.options.selectAllValue + '"]', this.$popupContainer).prop('checked', true);
|
1595 |
|
1596 |
if (this.options.enableClickableOptGroups && this.options.multiple) {
|
1597 |
this.updateOptGroups();
|
1598 |
}
|
1599 |
|
1600 |
+
this.updateButtonText();
|
1601 |
+
this.updateSelectAll();
|
1602 |
+
|
1603 |
if (triggerOnSelectAll) {
|
1604 |
+
this.options.onSelectAll(selected);
|
1605 |
}
|
1606 |
},
|
1607 |
|
1613 |
* @param {Boolean} justVisible
|
1614 |
*/
|
1615 |
deselectAll: function (justVisible, triggerOnDeselectAll) {
|
1616 |
+
if (!this.options.multiple) {
|
1617 |
+
// In single selection mode at least on option needs to be selected
|
1618 |
+
return;
|
1619 |
+
}
|
1620 |
|
1621 |
+
// Record changes, i.e., those options that are deselected but were not deselected before.
|
1622 |
+
var deselected = [];
|
1623 |
var justVisible = typeof justVisible === 'undefined' ? true : justVisible;
|
|
|
|
|
1624 |
|
1625 |
+
if (justVisible) {
|
1626 |
+
var visibleOptions = $(".multiselect-option:not(.disabled):not(.multiselect-filter-hidden)", this.$popupContainer);
|
1627 |
+
$('input[type="checkbox"]:enabled', visibleOptions).prop('checked', false);
|
1628 |
+
visibleOptions.removeClass(this.options.selectedClass);
|
1629 |
|
1630 |
+
$('input[type="checkbox"]:enabled', visibleOptions).each($.proxy(function (index, element) {
|
1631 |
var value = $(element).val();
|
1632 |
var option = this.getOptionByValue(value);
|
1633 |
+
if ($(option).prop('selected')) {
|
1634 |
+
deselected.push(option);
|
1635 |
+
}
|
1636 |
$(option).prop('selected', false);
|
1637 |
}, this));
|
1638 |
}
|
1639 |
else {
|
1640 |
+
var allOptions = $(".multiselect-option:not(.disabled):not(.multiselect-group)", this.$popupContainer);
|
1641 |
+
$('input[type="checkbox"]:enabled', allOptions).prop('checked', false);
|
1642 |
+
allOptions.removeClass(this.options.selectedClass);
|
1643 |
|
1644 |
+
$('input[type="checkbox"]:enabled', allOptions).each($.proxy(function (index, element) {
|
1645 |
var value = $(element).val();
|
1646 |
var option = this.getOptionByValue(value);
|
1647 |
+
if ($(option).prop('selected')) {
|
1648 |
+
deselected.push(option);
|
1649 |
+
}
|
1650 |
$(option).prop('selected', false);
|
1651 |
}, this));
|
1652 |
}
|
1653 |
|
1654 |
+
$('.multiselect-all input[value="' + this.options.selectAllValue + '"]', this.$popupContainer).prop('checked', false);
|
1655 |
|
1656 |
if (this.options.enableClickableOptGroups && this.options.multiple) {
|
1657 |
this.updateOptGroups();
|
1658 |
}
|
1659 |
|
1660 |
+
this.updateButtonText();
|
1661 |
+
this.updateSelectAll();
|
1662 |
+
|
1663 |
if (triggerOnDeselectAll) {
|
1664 |
+
this.options.onDeselectAll(deselected);
|
1665 |
}
|
1666 |
},
|
1667 |
|
1670 |
*
|
1671 |
* Rebuilds the dropdown, the filter and the select all option.
|
1672 |
*/
|
1673 |
+
rebuild: function () {
|
1674 |
+
this.$popupContainer.html('');
|
1675 |
|
1676 |
// Important to distinguish between radios and checkboxes.
|
1677 |
this.options.multiple = this.$select.attr('multiple') === "multiple";
|
1679 |
this.buildSelectAll();
|
1680 |
this.buildDropdownOptions();
|
1681 |
this.buildFilter();
|
1682 |
+
this.buildButtons();
|
1683 |
|
1684 |
this.updateButtonText();
|
1685 |
this.updateSelectAll(true);
|
1688 |
this.updateOptGroups();
|
1689 |
}
|
1690 |
|
1691 |
+
if (this.options.disableIfEmpty) {
|
1692 |
+
if ($('option', this.$select).length <= 0) {
|
1693 |
+
if (!this.$select.prop('disabled')) {
|
1694 |
+
this.disable(true);
|
1695 |
+
}
|
1696 |
+
}
|
1697 |
+
else if (this.$select.data("disabled-by-option")) {
|
1698 |
+
this.enable();
|
1699 |
+
}
|
1700 |
}
|
1701 |
|
1702 |
if (this.options.dropRight) {
|
1703 |
+
this.$container.addClass('dropright');
|
1704 |
+
}
|
1705 |
+
else if (this.options.dropUp) {
|
1706 |
+
this.$container.addClass('dropup');
|
1707 |
+
}
|
1708 |
+
|
1709 |
+
if (this.options.widthSynchronizationMode !== 'never') {
|
1710 |
+
this.synchronizeButtonAndPopupWidth();
|
1711 |
}
|
1712 |
},
|
1713 |
|
1714 |
/**
|
1715 |
* The provided data will be used to build the dropdown.
|
1716 |
*/
|
1717 |
+
dataprovider: function (dataprovider) {
|
1718 |
|
1719 |
var groupCounter = 0;
|
1720 |
var $select = this.$select.empty();
|
1731 |
value: option.value
|
1732 |
});
|
1733 |
|
1734 |
+
forEach(option.children, function (subOption) { // add children option tags
|
1735 |
var attributes = {
|
1736 |
value: subOption.value,
|
1737 |
label: subOption.label || subOption.value,
|
1741 |
};
|
1742 |
|
1743 |
//Loop through attributes object and add key-value for each attribute
|
1744 |
+
for (var key in subOption.attributes) {
|
1745 |
attributes['data-' + key] = subOption.attributes[key];
|
1746 |
+
}
|
1747 |
+
//Append original attributes + new data attributes to option
|
1748 |
$tag.append($('<option/>').attr(attributes));
|
1749 |
});
|
1750 |
}
|
1760 |
};
|
1761 |
//Loop through attributes object and add key-value for each attribute
|
1762 |
for (var key in option.attributes) {
|
1763 |
+
attributes['data-' + key] = option.attributes[key];
|
1764 |
}
|
1765 |
//Append original attributes + new data attributes to option
|
1766 |
$tag = $('<option/>').attr(attributes);
|
1777 |
/**
|
1778 |
* Enable the multiselect.
|
1779 |
*/
|
1780 |
+
enable: function () {
|
1781 |
this.$select.prop('disabled', false);
|
1782 |
this.$button.prop('disabled', false)
|
1783 |
.removeClass('disabled');
|
1784 |
+
|
1785 |
+
this.updateButtonText();
|
1786 |
},
|
1787 |
|
1788 |
/**
|
1789 |
* Disable the multiselect.
|
1790 |
*/
|
1791 |
+
disable: function (disableByOption) {
|
1792 |
this.$select.prop('disabled', true);
|
1793 |
this.$button.prop('disabled', true)
|
1794 |
.addClass('disabled');
|
1795 |
+
|
1796 |
+
if (disableByOption) {
|
1797 |
+
this.$select.data("disabled-by-option", true);
|
1798 |
+
}
|
1799 |
+
else {
|
1800 |
+
this.$select.data("disabled-by-option", null);
|
1801 |
+
}
|
1802 |
+
|
1803 |
+
this.updateButtonText();
|
1804 |
},
|
1805 |
|
1806 |
/**
|
1808 |
*
|
1809 |
* @param {Array} options
|
1810 |
*/
|
1811 |
+
setOptions: function (options) {
|
1812 |
this.options = this.mergeOptions(options);
|
1813 |
},
|
1814 |
|
1818 |
* @param {Array} options
|
1819 |
* @returns {Array}
|
1820 |
*/
|
1821 |
+
mergeOptions: function (options) {
|
1822 |
return $.extend(true, {}, this.defaults, this.options, options);
|
1823 |
},
|
1824 |
|
1827 |
*
|
1828 |
* @returns {Boolean}
|
1829 |
*/
|
1830 |
+
hasSelectAll: function () {
|
1831 |
+
return $('.multiselect-all', this.$popupContainer).length > 0;
|
1832 |
},
|
1833 |
|
1834 |
/**
|
1835 |
* Update opt groups.
|
1836 |
*/
|
1837 |
+
updateOptGroups: function () {
|
1838 |
+
var $groups = $('.multiselect-group', this.$popupContainer)
|
1839 |
var selectedClass = this.options.selectedClass;
|
1840 |
|
1841 |
+
$groups.each(function () {
|
1842 |
+
var $options = $(this).nextUntil('.multiselect-group')
|
1843 |
.not('.multiselect-filter-hidden')
|
1844 |
.not('.disabled');
|
1845 |
|
1846 |
var checked = true;
|
1847 |
+
$options.each(function () {
|
1848 |
var $input = $('input', this);
|
1849 |
|
1850 |
if (!$input.prop('checked')) {
|
1868 |
/**
|
1869 |
* Updates the select all checkbox based on the currently displayed and selected checkboxes.
|
1870 |
*/
|
1871 |
+
updateSelectAll: function (notTriggerOnSelectAll) {
|
1872 |
if (this.hasSelectAll()) {
|
1873 |
+
var allBoxes = $(".multiselect-option:not(.multiselect-filter-hidden):not(.multiselect-group):not(.disabled) input:enabled", this.$popupContainer);
|
1874 |
var allBoxesLength = allBoxes.length;
|
1875 |
var checkedBoxesLength = allBoxes.filter(":checked").length;
|
1876 |
+
var selectAllItem = $(".multiselect-all", this.$popupContainer);
|
1877 |
+
var selectAllInput = selectAllItem.find("input");
|
1878 |
|
1879 |
if (checkedBoxesLength > 0 && checkedBoxesLength === allBoxesLength) {
|
1880 |
selectAllInput.prop("checked", true);
|
1881 |
+
selectAllItem.addClass(this.options.selectedClass);
|
1882 |
}
|
1883 |
else {
|
1884 |
selectAllInput.prop("checked", false);
|
1885 |
+
selectAllItem.removeClass(this.options.selectedClass);
|
1886 |
}
|
1887 |
}
|
1888 |
},
|
1890 |
/**
|
1891 |
* Update the button text and its title based on the currently selected options.
|
1892 |
*/
|
1893 |
+
updateButtonText: function () {
|
1894 |
var options = this.getSelected();
|
1895 |
|
1896 |
// First update the displayed button text.
|
1903 |
|
1904 |
// Now update the title attribute of the button.
|
1905 |
$('.multiselect', this.$container).attr('title', this.options.buttonTitle(options, this.$select));
|
1906 |
+
this.$button.trigger('change');
|
1907 |
},
|
1908 |
|
1909 |
/**
|
1911 |
*
|
1912 |
* @returns {jQUery}
|
1913 |
*/
|
1914 |
+
getSelected: function () {
|
1915 |
return $('option', this.$select).filter(":selected");
|
1916 |
},
|
1917 |
|
1942 |
*/
|
1943 |
getInputByValue: function (value) {
|
1944 |
|
1945 |
+
var checkboxes = $('.multiselect-option input:not(.multiselect-search)', this.$popupContainer);
|
1946 |
var valueToCompare = value.toString();
|
1947 |
|
1948 |
for (var i = 0; i < checkboxes.length; i = i + 1) {
|
1956 |
/**
|
1957 |
* Used for knockout integration.
|
1958 |
*/
|
1959 |
+
updateOriginalOptions: function () {
|
1960 |
this.originalOptions = this.$select.clone()[0].options;
|
1961 |
},
|
1962 |
|
1963 |
+
asyncFunction: function (callback, timeout, self) {
|
1964 |
var args = Array.prototype.slice.call(arguments, 3);
|
1965 |
+
return setTimeout(function () {
|
1966 |
callback.apply(self || window, args);
|
1967 |
}, timeout);
|
1968 |
},
|
1969 |
|
1970 |
+
setAllSelectedText: function (allSelectedText) {
|
1971 |
this.options.allSelectedText = allSelectedText;
|
1972 |
this.updateButtonText();
|
1973 |
+
},
|
1974 |
+
|
1975 |
+
isFirefox: function () {
|
1976 |
+
var firefoxIdentifier = 'firefox';
|
1977 |
+
var valueNotFoundIndex = -1;
|
1978 |
+
|
1979 |
+
if (navigator && navigator.userAgent) {
|
1980 |
+
return navigator.userAgent.toLocaleLowerCase().indexOf(firefoxIdentifier) > valueNotFoundIndex;
|
1981 |
+
}
|
1982 |
+
|
1983 |
+
return false;
|
1984 |
}
|
1985 |
};
|
1986 |
|
1987 |
+
$.fn.multiselect = function (option, parameter, extraOptions) {
|
1988 |
+
return this.each(function () {
|
1989 |
var data = $(this).data('multiselect');
|
1990 |
var options = typeof option === 'object' && option;
|
1991 |
|
2008 |
|
2009 |
$.fn.multiselect.Constructor = Multiselect;
|
2010 |
|
2011 |
+
$(function () {
|
2012 |
$("select[data-role=multiselect]").multiselect();
|
2013 |
});
|
2014 |
|
2015 |
+
});
|
js/formidable.js
CHANGED
@@ -760,7 +760,7 @@ function frmFrontFormJS() {
|
|
760 |
jsErrors[key]
|
761 |
);
|
762 |
} else {
|
763 |
-
$fieldCont.append( '<div class="frm_error" id="' + id + '">' + jsErrors[key] + '</div>' );
|
764 |
}
|
765 |
|
766 |
if ( typeof describedBy === 'undefined' ) {
|
@@ -771,6 +771,7 @@ function frmFrontFormJS() {
|
|
771 |
input.attr( 'aria-describedby', describedBy );
|
772 |
}
|
773 |
input.attr( 'aria-invalid', true );
|
|
|
774 |
|
775 |
jQuery( document ).trigger( 'frmAddFieldError', [ $fieldCont, key, jsErrors ]);
|
776 |
}
|
@@ -785,6 +786,7 @@ function frmFrontFormJS() {
|
|
785 |
$fieldCont.removeClass( 'frm_blank_field has-error' );
|
786 |
errorMessage.remove();
|
787 |
input.attr( 'aria-invalid', false );
|
|
|
788 |
|
789 |
if ( typeof describedBy !== 'undefined' ) {
|
790 |
describedBy = describedBy.replace( errorId, '' );
|
760 |
jsErrors[key]
|
761 |
);
|
762 |
} else {
|
763 |
+
$fieldCont.append( '<div class="frm_error" role="alert" id="' + id + '">' + jsErrors[key] + '</div>' );
|
764 |
}
|
765 |
|
766 |
if ( typeof describedBy === 'undefined' ) {
|
771 |
input.attr( 'aria-describedby', describedBy );
|
772 |
}
|
773 |
input.attr( 'aria-invalid', true );
|
774 |
+
input.attr( 'aria-describedby', id );
|
775 |
|
776 |
jQuery( document ).trigger( 'frmAddFieldError', [ $fieldCont, key, jsErrors ]);
|
777 |
}
|
786 |
$fieldCont.removeClass( 'frm_blank_field has-error' );
|
787 |
errorMessage.remove();
|
788 |
input.attr( 'aria-invalid', false );
|
789 |
+
input.removeAttr( 'aria-describedby' );
|
790 |
|
791 |
if ( typeof describedBy !== 'undefined' ) {
|
792 |
describedBy = describedBy.replace( errorId, '' );
|
js/formidable.min.js
CHANGED
@@ -28,30 +28,31 @@ else grecaptcha.reset()});jQuery(document).trigger("frmFormErrors",[object,respo
|
|
28 |
jQuery(response.content).find(".frm_message");if(formCompleted.length)jQuery(document).trigger("frmFormComplete",[object,response]);else jQuery(document).trigger("frmPageChanged",[object,response])}function removeAddedScripts(formContainer,formID){var endReplace=jQuery(".frm_end_ajax_"+formID);if(endReplace.length){formContainer.nextUntil(".frm_end_ajax_"+formID).remove();endReplace.remove()}}function maybeSlideOut(oldContent,newContent){var c,newClass="frm_slideout";if(newContent.indexOf(" frm_slide")!==
|
29 |
-1){c=oldContent.children();if(newContent.indexOf(" frm_going_back")!==-1)newClass+=" frm_going_back";c.removeClass("frm_going_back");c.addClass(newClass);return 300}return 0}function addUrlParam(response){var url;if(history.pushState&&typeof response.page!=="undefined"){url=addQueryVar("frm_page",response.page);window.history.pushState({"html":response.html},"","?"+url)}}function addQueryVar(key,value){var kvp,i,x;key=encodeURI(key);value=encodeURI(value);kvp=document.location.search.substr(1).split("&");
|
30 |
i=kvp.length;while(i--){x=kvp[i].split("=");if(x[0]==key){x[1]=value;kvp[i]=x.join("=");break}}if(i<0)kvp[kvp.length]=[key,value].join("=");return kvp.join("&")}function addFieldError($fieldCont,key,jsErrors){var input,id,describedBy;if($fieldCont.length&&$fieldCont.is(":visible")){$fieldCont.addClass("frm_blank_field");input=$fieldCont.find("input, select, textarea");id="frm_error_field_"+key;describedBy=input.attr("aria-describedby");if(typeof frmThemeOverride_frmPlaceError==="function")frmThemeOverride_frmPlaceError(key,
|
31 |
-
jsErrors);else{if(-1!==jsErrors[key].indexOf("<div"))$fieldCont.append(jsErrors[key]);else $fieldCont.append('<div class="frm_error" id="'+id+'">'+jsErrors[key]+"</div>");if(typeof describedBy==="undefined")describedBy=id;else if(describedBy.indexOf(id)===-1)describedBy=describedBy+" "+id;input.attr("aria-describedby",describedBy)}input.attr("aria-invalid",true);jQuery(document).trigger("frmAddFieldError",[$fieldCont,key,jsErrors])}}function removeFieldError($fieldCont){var errorMessage
|
32 |
-
errorId=errorMessage.attr("id"),input=$fieldCont.find("input, select, textarea"),describedBy=input.attr("aria-describedby");$fieldCont.removeClass("frm_blank_field has-error");errorMessage.remove();input.attr("aria-invalid",false);if(typeof describedBy!=="undefined"){describedBy=describedBy.replace(errorId,"");input.attr("aria-describedby",describedBy)}}function removeAllErrors(){jQuery(".form-field").removeClass("frm_blank_field has-error");
|
33 |
-
function scrollToFirstField(object){var field=jQuery(object).find(".frm_blank_field").first();if(field.length)frmFrontForm.scrollMsg(field,object,true)}function showSubmitLoading($object){showLoadingIndicator($object);disableSubmitButton($object);disableSaveDraft($object)}function showLoadingIndicator($object){if(!$object.hasClass("frm_loading_form")&&!$object.hasClass("frm_loading_prev")){addLoadingClass($object)
|
34 |
-
isGoingToPrevPage($object)?"frm_loading_prev":"frm_loading_form";$object.addClass(loadingClass)}function isGoingToPrevPage($object){return typeof frmProForm!=="undefined"&&frmProForm.goingToPreviousPage($object)}function removeSubmitLoading($object,enable,processesRunning){var loadingForm;if(processesRunning>0)return;loadingForm=jQuery(".frm_loading_form");loadingForm.removeClass("frm_loading_form");loadingForm.removeClass("frm_loading_prev");
|
35 |
-
enableSaveDraft(loadingForm)}}function showFileLoading(object){var fileval,loading=document.getElementById("frm_loading");if(loading!==null){fileval=jQuery(object).find("input[type=file]").val();if(typeof fileval!=="undefined"&&fileval!=="")setTimeout(function(){jQuery(loading).fadeIn("slow")},2E3)}}function clearDefault(){toggleDefault(jQuery(this),"clear")}function replaceDefault(){toggleDefault(jQuery(this),
|
36 |
-
"\r");if(v===""||typeof v==="undefined")return false;thisVal=$thisField.val().replace(/(\n|\r\n)/g,"\r");if("replace"===e){if(thisVal==="")$thisField.addClass("frm_default").val(v)}else if(thisVal==v)$thisField.removeClass("frm_default").val("")}function resendEmail(){var $link=jQuery(this),entryId=this.getAttribute("data-eid"),formId=this.getAttribute("data-fid"),label=$link.find(".frm_link_label");
|
37 |
-
url:frm_js.ajax_url,data:{action:"frm_entries_send_email",entry_id:entryId,form_id:formId,nonce:frm_js.nonce},success:function(msg){var admin=document.getElementById("wpbody");if(admin===null)label.html(msg);else{label.html("");$link.after(msg)}}});return false}function confirmClick(){var message=jQuery(this).data("frmconfirm");return confirm(message)}function toggleDiv(){var div=jQuery(this).data("frmtoggle");
|
38 |
-
return false}function addIndexOfFallbackForIE8(){var len,from;if(!Array.prototype.indexOf)Array.prototype.indexOf=function(elt){len=this.length>>>0;from=Number(arguments[1])||0;from=from<0?Math.ceil(from):Math.floor(from);if(from<0)from+=len;for(;from<len;from++)if(from in this&&this[from]===elt)return from;return-1}}function addTrimFallbackForIE8(){if(typeof String.prototype.trim!=="function")String.prototype.trim=
|
39 |
-
len,res,thisp,i,val;if(!Array.prototype.filter)Array.prototype.filter=function(fun){if(this===void 0||this===null)throw new TypeError;t=Object(this);len=t.length>>>0;if(typeof fun!=="function")throw new TypeError;res=[];thisp=arguments[1];for(i=0;i<len;i++)if(i in t){val=t[i];if(fun.call(thisp,val,i,t))res.push(val)}return res}}function addKeysFallbackForIE8(){var keys,i;if(!Object.keys)Object.keys=function(obj){keys=
|
40 |
-
jQuery(this).css("box-shadow");if(css.match(/inset/))this.parentNode.removeChild(this)}function changeFocusWhenClickComboFieldLabel(){var label;var comboInputsContainer=document.querySelectorAll(".frm_combo_inputs_container");comboInputsContainer.forEach(function(inputsContainer){if(!inputsContainer.closest(".frm_form_field"))return;label=inputsContainer.closest(".frm_form_field").querySelector(".frm_primary_label");
|
41 |
-
function checkForErrorsAndMaybeSetFocus(){var errors,element,timeoutCallback;errors=document.querySelectorAll(".frm_form_field .frm_error");if(!errors.length)return;element=errors[0];do{element=element.previousSibling;if(-1!==["input","select","textarea"].indexOf(element.nodeName.toLowerCase())){element.focus();
|
42 |
-
else if(element.classList.contains("tmce-active"))timeoutCallback=function(){tinyMCE.activeEditor.focus()};if("function"===typeof timeoutCallback){setTimeout(timeoutCallback,0);break}}}while(element.previousSibling)}return{init:function(){jQuery(document).off("submit.formidable",".frm-show-form");
|
43 |
-
jQuery(document).on("focus",".frm_toggle_default",clearDefault);jQuery(document).on("blur",".frm_toggle_default",replaceDefault);jQuery(".frm_toggle_default").trigger("blur");jQuery(document.getElementById("frm_resend_email")).on("click",resendEmail);jQuery(document).on("change",
|
44 |
-
maybeShowLabel);jQuery(document).on("change","[id^=frm_email_]",onHoneypotFieldChange);jQuery(document).on("click","a[data-frmconfirm]",confirmClick);jQuery("a[data-frmtoggle]").on("click",
|
45 |
-
captcha.getAttribute("data-size"),rendered=captcha.getAttribute("data-rid")!==null,params={"sitekey":captcha.getAttribute("data-sitekey"),"size":size,"theme":captcha.getAttribute("data-theme")};
|
46 |
-
captcha.setAttribute("data-rid",recaptchaID)},afterSingleRecaptcha:function(){var object=jQuery(".frm-show-form .g-recaptcha").closest("form")[0];frmFrontForm.submitFormNow(object)},afterRecaptcha:function(token,
|
47 |
-
if(classList&&invisibleRecaptcha.length<1){isPro=classList.indexOf("frm_pro_form")>-1;if(!isPro)return}if(jQuery("body").hasClass("wp-admin")&&jQuery(object).closest(".frmapi-form").length<
|
48 |
-
if(Object.keys(errors).length===0){showSubmitLoading(jQuery(object));frmFrontForm.submitFormNow(object,classList)}}},submitFormNow:function(object){var hasFileFields,antispamInput,classList=
|
49 |
-
|
50 |
-
|
51 |
-
"
|
52 |
-
|
53 |
-
newPos
|
54 |
-
|
|
|
55 |
if(typeof frmProForm!=="undefined")return frmProForm.goingToPreviousPage(object)},hideOrShowFields:function(){console.warn("DEPRECATED: function frmFrontForm.hideOrShowFields in v3.0 use frmProForm.hideOrShowFields");if(typeof frmProForm!=="undefined")frmProForm.hideOrShowFields()},hidePreviouslyHiddenFields:function(){console.warn("DEPRECATED: function frmFrontForm.hidePreviouslyHiddenFields in v3.0 use frmProForm.hidePreviouslyHiddenFields");if(typeof frmProForm!=="undefined")frmProForm.hidePreviouslyHiddenFields()},
|
56 |
checkDependentDynamicFields:function(ids){console.warn("DEPRECATED: function frmFrontForm.checkDependentDynamicFields in v3.0 use frmProForm.checkDependentDynamicFields");if(typeof frmProForm!=="undefined")frmProForm.checkDependentDynamicFields(ids)},checkDependentLookupFields:function(ids){console.warn("DEPRECATED: function frmFrontForm.checkDependentLookupFields in v3.0 use frmProForm.checkDependentLookupFields");if(typeof frmProForm!=="undefined")frmProForm.checkDependentLookupFields(ids)},loadGoogle:function(){console.warn("DEPRECATED: function frmFrontForm.loadGoogle in v3.0 use frmProForm.loadGoogle");
|
57 |
frmProForm.loadGoogle()},escapeHtml:function(text){return text.replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,""").replace(/'/g,"'")},invisible:function(classes){jQuery(classes).css("visibility","hidden")},visible:function(classes){jQuery(classes).css("visibility","visible")}}}frmFrontForm=frmFrontFormJS();jQuery(document).ready(function(){frmFrontForm.init()});
|
28 |
jQuery(response.content).find(".frm_message");if(formCompleted.length)jQuery(document).trigger("frmFormComplete",[object,response]);else jQuery(document).trigger("frmPageChanged",[object,response])}function removeAddedScripts(formContainer,formID){var endReplace=jQuery(".frm_end_ajax_"+formID);if(endReplace.length){formContainer.nextUntil(".frm_end_ajax_"+formID).remove();endReplace.remove()}}function maybeSlideOut(oldContent,newContent){var c,newClass="frm_slideout";if(newContent.indexOf(" frm_slide")!==
|
29 |
-1){c=oldContent.children();if(newContent.indexOf(" frm_going_back")!==-1)newClass+=" frm_going_back";c.removeClass("frm_going_back");c.addClass(newClass);return 300}return 0}function addUrlParam(response){var url;if(history.pushState&&typeof response.page!=="undefined"){url=addQueryVar("frm_page",response.page);window.history.pushState({"html":response.html},"","?"+url)}}function addQueryVar(key,value){var kvp,i,x;key=encodeURI(key);value=encodeURI(value);kvp=document.location.search.substr(1).split("&");
|
30 |
i=kvp.length;while(i--){x=kvp[i].split("=");if(x[0]==key){x[1]=value;kvp[i]=x.join("=");break}}if(i<0)kvp[kvp.length]=[key,value].join("=");return kvp.join("&")}function addFieldError($fieldCont,key,jsErrors){var input,id,describedBy;if($fieldCont.length&&$fieldCont.is(":visible")){$fieldCont.addClass("frm_blank_field");input=$fieldCont.find("input, select, textarea");id="frm_error_field_"+key;describedBy=input.attr("aria-describedby");if(typeof frmThemeOverride_frmPlaceError==="function")frmThemeOverride_frmPlaceError(key,
|
31 |
+
jsErrors);else{if(-1!==jsErrors[key].indexOf("<div"))$fieldCont.append(jsErrors[key]);else $fieldCont.append('<div class="frm_error" role="alert" id="'+id+'">'+jsErrors[key]+"</div>");if(typeof describedBy==="undefined")describedBy=id;else if(describedBy.indexOf(id)===-1)describedBy=describedBy+" "+id;input.attr("aria-describedby",describedBy)}input.attr("aria-invalid",true);input.attr("aria-describedby",id);jQuery(document).trigger("frmAddFieldError",[$fieldCont,key,jsErrors])}}function removeFieldError($fieldCont){var errorMessage=
|
32 |
+
$fieldCont.find(".frm_error"),errorId=errorMessage.attr("id"),input=$fieldCont.find("input, select, textarea"),describedBy=input.attr("aria-describedby");$fieldCont.removeClass("frm_blank_field has-error");errorMessage.remove();input.attr("aria-invalid",false);input.removeAttr("aria-describedby");if(typeof describedBy!=="undefined"){describedBy=describedBy.replace(errorId,"");input.attr("aria-describedby",describedBy)}}function removeAllErrors(){jQuery(".form-field").removeClass("frm_blank_field has-error");
|
33 |
+
jQuery(".form-field .frm_error").replaceWith("");jQuery(".frm_error_style").remove()}function scrollToFirstField(object){var field=jQuery(object).find(".frm_blank_field").first();if(field.length)frmFrontForm.scrollMsg(field,object,true)}function showSubmitLoading($object){showLoadingIndicator($object);disableSubmitButton($object);disableSaveDraft($object)}function showLoadingIndicator($object){if(!$object.hasClass("frm_loading_form")&&!$object.hasClass("frm_loading_prev")){addLoadingClass($object);
|
34 |
+
$object.trigger("frmStartFormLoading")}}function addLoadingClass($object){var loadingClass=isGoingToPrevPage($object)?"frm_loading_prev":"frm_loading_form";$object.addClass(loadingClass)}function isGoingToPrevPage($object){return typeof frmProForm!=="undefined"&&frmProForm.goingToPreviousPage($object)}function removeSubmitLoading($object,enable,processesRunning){var loadingForm;if(processesRunning>0)return;loadingForm=jQuery(".frm_loading_form");loadingForm.removeClass("frm_loading_form");loadingForm.removeClass("frm_loading_prev");
|
35 |
+
loadingForm.trigger("frmEndFormLoading");if(enable==="enable"){enableSubmitButton(loadingForm);enableSaveDraft(loadingForm)}}function showFileLoading(object){var fileval,loading=document.getElementById("frm_loading");if(loading!==null){fileval=jQuery(object).find("input[type=file]").val();if(typeof fileval!=="undefined"&&fileval!=="")setTimeout(function(){jQuery(loading).fadeIn("slow")},2E3)}}function clearDefault(){toggleDefault(jQuery(this),"clear")}function replaceDefault(){toggleDefault(jQuery(this),
|
36 |
+
"replace")}function toggleDefault($thisField,e){var thisVal,v=$thisField.data("frmval").replace(/(\n|\r\n)/g,"\r");if(v===""||typeof v==="undefined")return false;thisVal=$thisField.val().replace(/(\n|\r\n)/g,"\r");if("replace"===e){if(thisVal==="")$thisField.addClass("frm_default").val(v)}else if(thisVal==v)$thisField.removeClass("frm_default").val("")}function resendEmail(){var $link=jQuery(this),entryId=this.getAttribute("data-eid"),formId=this.getAttribute("data-fid"),label=$link.find(".frm_link_label");
|
37 |
+
if(label.length<1)label=$link;label.append('<span class="frm-wait"></span>');jQuery.ajax({type:"POST",url:frm_js.ajax_url,data:{action:"frm_entries_send_email",entry_id:entryId,form_id:formId,nonce:frm_js.nonce},success:function(msg){var admin=document.getElementById("wpbody");if(admin===null)label.html(msg);else{label.html("");$link.after(msg)}}});return false}function confirmClick(){var message=jQuery(this).data("frmconfirm");return confirm(message)}function toggleDiv(){var div=jQuery(this).data("frmtoggle");
|
38 |
+
if(jQuery(div).is(":visible"))jQuery(div).slideUp("fast");else jQuery(div).slideDown("fast");return false}function addIndexOfFallbackForIE8(){var len,from;if(!Array.prototype.indexOf)Array.prototype.indexOf=function(elt){len=this.length>>>0;from=Number(arguments[1])||0;from=from<0?Math.ceil(from):Math.floor(from);if(from<0)from+=len;for(;from<len;from++)if(from in this&&this[from]===elt)return from;return-1}}function addTrimFallbackForIE8(){if(typeof String.prototype.trim!=="function")String.prototype.trim=
|
39 |
+
function(){return this.replace(/^\s+|\s+$/g,"")}}function addFilterFallbackForIE8(){var t,len,res,thisp,i,val;if(!Array.prototype.filter)Array.prototype.filter=function(fun){if(this===void 0||this===null)throw new TypeError;t=Object(this);len=t.length>>>0;if(typeof fun!=="function")throw new TypeError;res=[];thisp=arguments[1];for(i=0;i<len;i++)if(i in t){val=t[i];if(fun.call(thisp,val,i,t))res.push(val)}return res}}function addKeysFallbackForIE8(){var keys,i;if(!Object.keys)Object.keys=function(obj){keys=
|
40 |
+
[];for(i in obj)if(obj.hasOwnProperty(i))keys.push(i);return keys}}function onHoneypotFieldChange(){var css=jQuery(this).css("box-shadow");if(css.match(/inset/))this.parentNode.removeChild(this)}function changeFocusWhenClickComboFieldLabel(){var label;var comboInputsContainer=document.querySelectorAll(".frm_combo_inputs_container");comboInputsContainer.forEach(function(inputsContainer){if(!inputsContainer.closest(".frm_form_field"))return;label=inputsContainer.closest(".frm_form_field").querySelector(".frm_primary_label");
|
41 |
+
if(!label)return;label.addEventListener("click",function(e){inputsContainer.querySelector(".frm_form_field:first-child input, .frm_form_field:first-child select, .frm_form_field:first-child textarea").focus()})})}function checkForErrorsAndMaybeSetFocus(){var errors,element,timeoutCallback;errors=document.querySelectorAll(".frm_form_field .frm_error");if(!errors.length)return;element=errors[0];do{element=element.previousSibling;if(-1!==["input","select","textarea"].indexOf(element.nodeName.toLowerCase())){element.focus();
|
42 |
+
break}if("undefined"!==typeof element.classList){if(element.classList.contains("html-active"))timeoutCallback=function(){var textarea=element.querySelector("textarea");if(null!==textarea)textarea.focus()};else if(element.classList.contains("tmce-active"))timeoutCallback=function(){tinyMCE.activeEditor.focus()};if("function"===typeof timeoutCallback){setTimeout(timeoutCallback,0);break}}}while(element.previousSibling)}return{init:function(){jQuery(document).off("submit.formidable",".frm-show-form");
|
43 |
+
jQuery(document).on("submit.formidable",".frm-show-form",frmFrontForm.submitForm);jQuery(".frm-show-form input[onblur], .frm-show-form textarea[onblur]").each(function(){if(jQuery(this).val()==="")jQuery(this).trigger("blur")});jQuery(document).on("focus",".frm_toggle_default",clearDefault);jQuery(document).on("blur",".frm_toggle_default",replaceDefault);jQuery(".frm_toggle_default").trigger("blur");jQuery(document.getElementById("frm_resend_email")).on("click",resendEmail);jQuery(document).on("change",
|
44 |
+
'.frm-show-form input[name^="item_meta"], .frm-show-form select[name^="item_meta"], .frm-show-form textarea[name^="item_meta"]',frmFrontForm.fieldValueChanged);jQuery(document).on("change keyup",".frm-show-form .frm_inside_container input, .frm-show-form .frm_inside_container select, .frm-show-form .frm_inside_container textarea",maybeShowLabel);jQuery(document).on("change","[id^=frm_email_]",onHoneypotFieldChange);jQuery(document).on("click","a[data-frmconfirm]",confirmClick);jQuery("a[data-frmtoggle]").on("click",
|
45 |
+
toggleDiv);checkForErrorsAndMaybeSetFocus();changeFocusWhenClickComboFieldLabel();addIndexOfFallbackForIE8();addTrimFallbackForIE8();addFilterFallbackForIE8();addKeysFallbackForIE8()},getFieldId:function(field,fullID){return getFieldId(field,fullID)},renderRecaptcha:function(captcha){var formID,recaptchaID,size=captcha.getAttribute("data-size"),rendered=captcha.getAttribute("data-rid")!==null,params={"sitekey":captcha.getAttribute("data-sitekey"),"size":size,"theme":captcha.getAttribute("data-theme")};
|
46 |
+
if(rendered)return;if(size==="invisible"){formID=jQuery(captcha).closest("form").find('input[name="form_id"]').val();jQuery(captcha).closest(".frm_form_field .frm_primary_label").hide();params.callback=function(token){frmFrontForm.afterRecaptcha(token,formID)}}recaptchaID=grecaptcha.render(captcha.id,params);captcha.setAttribute("data-rid",recaptchaID)},afterSingleRecaptcha:function(){var object=jQuery(".frm-show-form .g-recaptcha").closest("form")[0];frmFrontForm.submitFormNow(object)},afterRecaptcha:function(token,
|
47 |
+
formID){var object=jQuery("#frm_form_"+formID+"_container form")[0];frmFrontForm.submitFormNow(object)},submitForm:function(e){frmFrontForm.submitFormManual(e,this)},submitFormManual:function(e,object){var isPro,errors,invisibleRecaptcha=hasInvisibleRecaptcha(object),classList=object.className.trim().split(/\s+/gi);if(classList&&invisibleRecaptcha.length<1){isPro=classList.indexOf("frm_pro_form")>-1;if(!isPro)return}if(jQuery("body").hasClass("wp-admin")&&jQuery(object).closest(".frmapi-form").length<
|
48 |
+
1)return;e.preventDefault();if(typeof frmProForm!=="undefined"&&typeof frmProForm.submitAllowed==="function")if(!frmProForm.submitAllowed(object))return;if(invisibleRecaptcha.length){showLoadingIndicator(jQuery(object));executeInvisibleRecaptcha(invisibleRecaptcha)}else{errors=frmFrontForm.validateFormSubmit(object);if(Object.keys(errors).length===0){showSubmitLoading(jQuery(object));frmFrontForm.submitFormNow(object,classList)}}},submitFormNow:function(object){var hasFileFields,antispamInput,classList=
|
49 |
+
object.className.trim().split(/\s+/gi);if(object.hasAttribute("data-token")&&null===object.querySelector('[name="antispam_token"]')){antispamInput=document.createElement("input");antispamInput.type="hidden";antispamInput.name="antispam_token";antispamInput.value=object.getAttribute("data-token");object.appendChild(antispamInput)}if(classList.indexOf("frm_ajax_submit")>-1){hasFileFields=jQuery(object).find('input[type="file"]').filter(function(){return!!this.value}).length;if(hasFileFields<1){action=
|
50 |
+
jQuery(object).find('input[name="frm_action"]').val();frmFrontForm.checkFormErrors(object,action)}else object.submit()}else object.submit()},validateFormSubmit:function(object){if(typeof tinyMCE!=="undefined"&&jQuery(object).find(".wp-editor-wrap").length)tinyMCE.triggerSave();jsErrors=[];if(shouldJSValidate(object)){frmFrontForm.getAjaxFormErrors(object);if(Object.keys(jsErrors).length)frmFrontForm.addAjaxFormErrors(object)}return jsErrors},getAjaxFormErrors:function(object){var customErrors,key;
|
51 |
+
jsErrors=validateForm(object);if(typeof frmThemeOverride_jsErrors==="function"){action=jQuery(object).find('input[name="frm_action"]').val();customErrors=frmThemeOverride_jsErrors(action,object);if(Object.keys(customErrors).length)for(key in customErrors)jsErrors[key]=customErrors[key]}return jsErrors},addAjaxFormErrors:function(object){var key,$fieldCont;removeAllErrors();for(key in jsErrors){$fieldCont=jQuery(object).find("#frm_field_"+key+"_container");if($fieldCont.length)addFieldError($fieldCont,
|
52 |
+
key,jsErrors);else delete jsErrors[key]}scrollToFirstField(object);checkForErrorsAndMaybeSetFocus()},checkFormErrors:function(object,action){getFormErrors(object,action)},checkRequiredField:function(field,errors){return checkRequiredField(field,errors)},showSubmitLoading:function($object){showSubmitLoading($object)},removeSubmitLoading:function($object,enable,processesRunning){removeSubmitLoading($object,enable,processesRunning)},scrollToID:function(id){var object=jQuery(document.getElementById(id));
|
53 |
+
frmFrontForm.scrollMsg(object,false)},scrollMsg:function(id,object,animate){var newPos,m,b,screenTop,screenBottom,scrollObj="";if(typeof object==="undefined"){scrollObj=jQuery(document.getElementById("frm_form_"+id+"_container"));if(scrollObj.length<1)return}else if(typeof id==="string")scrollObj=jQuery(object).find("#frm_field_"+id+"_container");else scrollObj=id;jQuery(scrollObj).trigger("focus");newPos=scrollObj.offset().top;if(!newPos||frm_js.offset==="-1")return;newPos=newPos-frm_js.offset;m=
|
54 |
+
jQuery("html").css("margin-top");b=jQuery("body").css("margin-top");if(m||b)newPos=newPos-parseInt(m)-parseInt(b);if(newPos&&window.innerHeight){screenTop=document.documentElement.scrollTop||document.body.scrollTop;screenBottom=screenTop+window.innerHeight;if(newPos>screenBottom||newPos<screenTop){if(typeof animate==="undefined")jQuery(window).scrollTop(newPos);else jQuery("html,body").animate({scrollTop:newPos},500);return false}}},fieldValueChanged:function(e){var fieldId=frmFrontForm.getFieldId(this,
|
55 |
+
false);if(!fieldId||typeof fieldId==="undefined")return;if(e.frmTriggered&&e.frmTriggered==fieldId)return;jQuery(document).trigger("frmFieldChanged",[this,fieldId,e]);if(e.selfTriggered!==true)maybeValidateChange(this)},savingDraft:function(object){console.warn("DEPRECATED: function frmFrontForm.savingDraft in v3.0 use frmProForm.savingDraft");if(typeof frmProForm!=="undefined")return frmProForm.savingDraft(object)},goingToPreviousPage:function(object){console.warn("DEPRECATED: function frmFrontForm.goingToPreviousPage in v3.0 use frmProForm.goingToPreviousPage");
|
56 |
if(typeof frmProForm!=="undefined")return frmProForm.goingToPreviousPage(object)},hideOrShowFields:function(){console.warn("DEPRECATED: function frmFrontForm.hideOrShowFields in v3.0 use frmProForm.hideOrShowFields");if(typeof frmProForm!=="undefined")frmProForm.hideOrShowFields()},hidePreviouslyHiddenFields:function(){console.warn("DEPRECATED: function frmFrontForm.hidePreviouslyHiddenFields in v3.0 use frmProForm.hidePreviouslyHiddenFields");if(typeof frmProForm!=="undefined")frmProForm.hidePreviouslyHiddenFields()},
|
57 |
checkDependentDynamicFields:function(ids){console.warn("DEPRECATED: function frmFrontForm.checkDependentDynamicFields in v3.0 use frmProForm.checkDependentDynamicFields");if(typeof frmProForm!=="undefined")frmProForm.checkDependentDynamicFields(ids)},checkDependentLookupFields:function(ids){console.warn("DEPRECATED: function frmFrontForm.checkDependentLookupFields in v3.0 use frmProForm.checkDependentLookupFields");if(typeof frmProForm!=="undefined")frmProForm.checkDependentLookupFields(ids)},loadGoogle:function(){console.warn("DEPRECATED: function frmFrontForm.loadGoogle in v3.0 use frmProForm.loadGoogle");
|
58 |
frmProForm.loadGoogle()},escapeHtml:function(text){return text.replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,""").replace(/'/g,"'")},invisible:function(classes){jQuery(classes).css("visibility","hidden")},visible:function(classes){jQuery(classes).css("visibility","visible")}}}frmFrontForm=frmFrontFormJS();jQuery(document).ready(function(){frmFrontForm.init()});
|
js/formidable_admin.js
CHANGED
@@ -5401,7 +5401,7 @@ function frmAdminBuildJS() {
|
|
5401 |
|
5402 |
function onEveryoneOptionSelected( $select ) {
|
5403 |
$select.val( '' );
|
5404 |
-
$select.next( '.btn-group' ).find( '.multiselect-container
|
5405 |
}
|
5406 |
|
5407 |
function unselectEveryoneOptionIfSelected( $select ) {
|
@@ -5409,7 +5409,7 @@ function frmAdminBuildJS() {
|
|
5409 |
index;
|
5410 |
|
5411 |
if ( selectedValues === null ) {
|
5412 |
-
$select.next( '.btn-group' ).find( '.multiselect-container
|
5413 |
onEveryoneOptionSelected( $select );
|
5414 |
return;
|
5415 |
}
|
@@ -5418,7 +5418,7 @@ function frmAdminBuildJS() {
|
|
5418 |
if ( index >= 0 ) {
|
5419 |
selectedValues.splice( index, 1 );
|
5420 |
$select.val( selectedValues );
|
5421 |
-
$select.next( '.btn-group' ).find( '.multiselect-container
|
5422 |
}
|
5423 |
}
|
5424 |
|
@@ -7609,9 +7609,9 @@ function frmAdminBuildJS() {
|
|
7609 |
labelledBy = id && labelledBy.length ? 'aria-labelledby="' + labelledBy.attr( 'id' ) + '"' : '';
|
7610 |
$select.multiselect({
|
7611 |
templates: {
|
7612 |
-
|
7613 |
-
|
7614 |
-
button: '<button type="button" class="multiselect dropdown-toggle" data-toggle="dropdown"
|
7615 |
},
|
7616 |
buttonContainer: '<div class="btn-group frm-btn-group dropdown" />',
|
7617 |
nonSelectedText: '',
|
@@ -8653,6 +8653,33 @@ function frmAdminBuildJS() {
|
|
8653 |
w.off( 'beforeunload.edit-post' );
|
8654 |
}
|
8655 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
8656 |
function maybeChangeEmbedFormMsg() {
|
8657 |
var fieldId = jQuery( this ).closest( '.frm-single-settings' ).data( 'fid' );
|
8658 |
var fieldItem = document.getElementById( 'frm_field_id_' + fieldId );
|
@@ -8983,6 +9010,8 @@ function frmAdminBuildJS() {
|
|
8983 |
|
8984 |
// prevent annoying confirmation message from WordPress
|
8985 |
jQuery( 'button, input[type=submit]' ).on( 'click', removeWPUnload );
|
|
|
|
|
8986 |
},
|
8987 |
|
8988 |
buildInit: function() {
|
5401 |
|
5402 |
function onEveryoneOptionSelected( $select ) {
|
5403 |
$select.val( '' );
|
5404 |
+
$select.next( '.btn-group' ).find( '.multiselect-container input[value!=""]' ).prop( 'checked', false );
|
5405 |
}
|
5406 |
|
5407 |
function unselectEveryoneOptionIfSelected( $select ) {
|
5409 |
index;
|
5410 |
|
5411 |
if ( selectedValues === null ) {
|
5412 |
+
$select.next( '.btn-group' ).find( '.multiselect-container input[value=""]' ).prop( 'checked', true );
|
5413 |
onEveryoneOptionSelected( $select );
|
5414 |
return;
|
5415 |
}
|
5418 |
if ( index >= 0 ) {
|
5419 |
selectedValues.splice( index, 1 );
|
5420 |
$select.val( selectedValues );
|
5421 |
+
$select.next( '.btn-group' ).find( '.multiselect-container input[value=""]' ).prop( 'checked', false );
|
5422 |
}
|
5423 |
}
|
5424 |
|
7609 |
labelledBy = id && labelledBy.length ? 'aria-labelledby="' + labelledBy.attr( 'id' ) + '"' : '';
|
7610 |
$select.multiselect({
|
7611 |
templates: {
|
7612 |
+
popupContainer: '<div class="multiselect-container frm-dropdown-menu"></div>',
|
7613 |
+
option: '<button type="button" class="multiselect-option dropdown-item frm_no_style_button"></button>',
|
7614 |
+
button: '<button type="button" class="multiselect dropdown-toggle btn" data-toggle="dropdown" ' + labelledBy + '><span class="multiselect-selected-text"></span> <b class="caret"></b></button>'
|
7615 |
},
|
7616 |
buttonContainer: '<div class="btn-group frm-btn-group dropdown" />',
|
7617 |
nonSelectedText: '',
|
8653 |
w.off( 'beforeunload.edit-post' );
|
8654 |
}
|
8655 |
|
8656 |
+
function addMultiselectLabelListener() {
|
8657 |
+
const clickListener = ( e ) => {
|
8658 |
+
if ( 'LABEL' !== e.target.nodeName ) {
|
8659 |
+
return;
|
8660 |
+
}
|
8661 |
+
|
8662 |
+
const labelFor = e.target.getAttribute( 'for' );
|
8663 |
+
if ( ! labelFor ) {
|
8664 |
+
return;
|
8665 |
+
}
|
8666 |
+
|
8667 |
+
const input = document.getElementById( labelFor );
|
8668 |
+
if ( ! input || ! input.nextElementSibling ) {
|
8669 |
+
return;
|
8670 |
+
}
|
8671 |
+
|
8672 |
+
const buttonToggle = input.nextElementSibling.querySelector( 'button.dropdown-toggle.multiselect' );
|
8673 |
+
if ( ! buttonToggle ) {
|
8674 |
+
return;
|
8675 |
+
}
|
8676 |
+
|
8677 |
+
const triggerMultiselectClick = () => buttonToggle.click();
|
8678 |
+
setTimeout( triggerMultiselectClick, 0 );
|
8679 |
+
};
|
8680 |
+
document.addEventListener( 'click', clickListener );
|
8681 |
+
}
|
8682 |
+
|
8683 |
function maybeChangeEmbedFormMsg() {
|
8684 |
var fieldId = jQuery( this ).closest( '.frm-single-settings' ).data( 'fid' );
|
8685 |
var fieldItem = document.getElementById( 'frm_field_id_' + fieldId );
|
9010 |
|
9011 |
// prevent annoying confirmation message from WordPress
|
9012 |
jQuery( 'button, input[type=submit]' ).on( 'click', removeWPUnload );
|
9013 |
+
|
9014 |
+
addMultiselectLabelListener();
|
9015 |
},
|
9016 |
|
9017 |
buildInit: function() {
|
languages/formidable.pot
CHANGED
@@ -2,14 +2,14 @@
|
|
2 |
# This file is distributed under the same license as the Formidable Forms plugin.
|
3 |
msgid ""
|
4 |
msgstr ""
|
5 |
-
"Project-Id-Version: Formidable Forms 5.
|
6 |
"Report-Msgid-Bugs-To: https://wordpress.org/support/plugin/formidable\n"
|
7 |
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
8 |
"Language-Team: LANGUAGE <LL@li.org>\n"
|
9 |
"MIME-Version: 1.0\n"
|
10 |
"Content-Type: text/plain; charset=UTF-8\n"
|
11 |
"Content-Transfer-Encoding: 8bit\n"
|
12 |
-
"POT-Creation-Date: 2022-01-
|
13 |
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
14 |
"X-Generator: WP-CLI 2.4.0\n"
|
15 |
"X-Domain: formidable\n"
|
@@ -1648,19 +1648,19 @@ msgstr ""
|
|
1648 |
msgid "Vietnamese"
|
1649 |
msgstr ""
|
1650 |
|
1651 |
-
#: classes/helpers/FrmAppHelper.php:
|
1652 |
msgid "Form Landing Pages"
|
1653 |
msgstr ""
|
1654 |
|
1655 |
-
#: classes/helpers/FrmAppHelper.php:
|
1656 |
msgid "Easily manage a landing page for your form. Upgrade to get form landing pages."
|
1657 |
msgstr ""
|
1658 |
|
1659 |
-
#: classes/helpers/FrmAppHelper.php:
|
1660 |
msgid "Your account has expired"
|
1661 |
msgstr ""
|
1662 |
|
1663 |
-
#: classes/helpers/FrmAppHelper.php:
|
1664 |
msgid "Renew Now"
|
1665 |
msgstr ""
|
1666 |
|
@@ -1773,16 +1773,16 @@ msgstr ""
|
|
1773 |
msgid "Yes"
|
1774 |
msgstr ""
|
1775 |
|
1776 |
-
#: classes/helpers/FrmEntriesListHelper.php:
|
1777 |
#: classes/views/frm-entries/sidebar-shared.php:43
|
1778 |
msgid "View"
|
1779 |
msgstr ""
|
1780 |
|
1781 |
-
#: classes/helpers/FrmEntriesListHelper.php:
|
1782 |
msgid "Permanently delete this entry?"
|
1783 |
msgstr ""
|
1784 |
|
1785 |
-
#: classes/helpers/FrmEntriesListHelper.php:
|
1786 |
#: classes/helpers/FrmFormsHelper.php:1166
|
1787 |
#: classes/helpers/FrmFormsListHelper.php:133
|
1788 |
#: classes/views/frm-form-actions/form_action.php:25
|
@@ -1790,7 +1790,7 @@ msgstr ""
|
|
1790 |
msgid "Delete"
|
1791 |
msgstr ""
|
1792 |
|
1793 |
-
#: classes/helpers/FrmEntriesListHelper.php:
|
1794 |
msgid "ALL selected entries in this form will be permanently deleted. Want to proceed?"
|
1795 |
msgstr ""
|
1796 |
|
@@ -5074,18 +5074,6 @@ msgstr ""
|
|
5074 |
msgid "Templates"
|
5075 |
msgstr ""
|
5076 |
|
5077 |
-
#: classes/views/frm-forms/multiselect-accessibility.php:7
|
5078 |
-
msgid "Checked. To uncheck this option, press Space or Enter"
|
5079 |
-
msgstr ""
|
5080 |
-
|
5081 |
-
#: classes/views/frm-forms/multiselect-accessibility.php:8
|
5082 |
-
msgid "Unchecked. To check this option, press Space or Enter"
|
5083 |
-
msgstr ""
|
5084 |
-
|
5085 |
-
#: classes/views/frm-forms/multiselect-accessibility.php:9
|
5086 |
-
msgid "You are on a Custom List of Checkboxes. To open, press Enter. Use Up and Down arrow keys to switch between options"
|
5087 |
-
msgstr ""
|
5088 |
-
|
5089 |
#: classes/views/frm-forms/new-form-overlay.php:11
|
5090 |
msgid "Back"
|
5091 |
msgstr ""
|
2 |
# This file is distributed under the same license as the Formidable Forms plugin.
|
3 |
msgid ""
|
4 |
msgstr ""
|
5 |
+
"Project-Id-Version: Formidable Forms 5.1\n"
|
6 |
"Report-Msgid-Bugs-To: https://wordpress.org/support/plugin/formidable\n"
|
7 |
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
8 |
"Language-Team: LANGUAGE <LL@li.org>\n"
|
9 |
"MIME-Version: 1.0\n"
|
10 |
"Content-Type: text/plain; charset=UTF-8\n"
|
11 |
"Content-Transfer-Encoding: 8bit\n"
|
12 |
+
"POT-Creation-Date: 2022-01-27T13:54:08+00:00\n"
|
13 |
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
14 |
"X-Generator: WP-CLI 2.4.0\n"
|
15 |
"X-Domain: formidable\n"
|
1648 |
msgid "Vietnamese"
|
1649 |
msgstr ""
|
1650 |
|
1651 |
+
#: classes/helpers/FrmAppHelper.php:3240
|
1652 |
msgid "Form Landing Pages"
|
1653 |
msgstr ""
|
1654 |
|
1655 |
+
#: classes/helpers/FrmAppHelper.php:3241
|
1656 |
msgid "Easily manage a landing page for your form. Upgrade to get form landing pages."
|
1657 |
msgstr ""
|
1658 |
|
1659 |
+
#: classes/helpers/FrmAppHelper.php:3328
|
1660 |
msgid "Your account has expired"
|
1661 |
msgstr ""
|
1662 |
|
1663 |
+
#: classes/helpers/FrmAppHelper.php:3331
|
1664 |
msgid "Renew Now"
|
1665 |
msgstr ""
|
1666 |
|
1773 |
msgid "Yes"
|
1774 |
msgstr ""
|
1775 |
|
1776 |
+
#: classes/helpers/FrmEntriesListHelper.php:314
|
1777 |
#: classes/views/frm-entries/sidebar-shared.php:43
|
1778 |
msgid "View"
|
1779 |
msgstr ""
|
1780 |
|
1781 |
+
#: classes/helpers/FrmEntriesListHelper.php:319
|
1782 |
msgid "Permanently delete this entry?"
|
1783 |
msgstr ""
|
1784 |
|
1785 |
+
#: classes/helpers/FrmEntriesListHelper.php:319
|
1786 |
#: classes/helpers/FrmFormsHelper.php:1166
|
1787 |
#: classes/helpers/FrmFormsListHelper.php:133
|
1788 |
#: classes/views/frm-form-actions/form_action.php:25
|
1790 |
msgid "Delete"
|
1791 |
msgstr ""
|
1792 |
|
1793 |
+
#: classes/helpers/FrmEntriesListHelper.php:368
|
1794 |
msgid "ALL selected entries in this form will be permanently deleted. Want to proceed?"
|
1795 |
msgstr ""
|
1796 |
|
5074 |
msgid "Templates"
|
5075 |
msgstr ""
|
5076 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
5077 |
#: classes/views/frm-forms/new-form-overlay.php:11
|
5078 |
msgid "Back"
|
5079 |
msgstr ""
|
readme.txt
CHANGED
@@ -3,9 +3,9 @@ Plugin Name: Formidable Forms - Contact Form, Survey & Quiz Forms Plugin for Wor
|
|
3 |
Contributors: formidableforms, sswells, srwells
|
4 |
Tags: forms, contact form, form builder, survey, free, form maker, form creator, paypal form, paypal, stripe, stripe form, aweber, aweber form, getresponse, getresponse form, calculator, price calculator, quote form, contact button, form manager, Akismet, payment form, survey form, donation form, email subscription, contact form widget, user registration form, wordpress registration, wordpress login form, constant contact, mailpoet, active campaign, salesforce, hubspot, campaign monitor, quiz builder, quiz, feedback form, mailchimp form
|
5 |
Requires at least: 5.0
|
6 |
-
Tested up to: 5.
|
7 |
Requires PHP: 5.6
|
8 |
-
Stable tag: 5.
|
9 |
|
10 |
The most advanced WordPress forms plugin. Go beyond contact forms with our drag & drop form builder for surveys, quizzes, and more.
|
11 |
|
@@ -438,6 +438,12 @@ Using our Zapier integration, you can easily connect Formidable with over 1000+
|
|
438 |
See all <a href="https://zapier.com/apps/formidable/integrations">Formidable Zapier Integrations</a>.
|
439 |
|
440 |
== Changelog ==
|
|
|
|
|
|
|
|
|
|
|
|
|
441 |
= 5.0.17 =
|
442 |
- The embedded CodeMirror code for compatibility with versions of WordPress before 4.9 has been removed.
|
443 |
- New: The ctype PHP extension is no longer a requirement.
|
@@ -456,13 +462,4 @@ See all <a href="https://zapier.com/apps/formidable/integrations">Formidable Zap
|
|
456 |
- Fix: Radio buttons and checkboxes were appearing overlapped with labels when using the H-Code theme.
|
457 |
- Fix: Field pop ups were displaying upgrade messages even for licenses that had access to the add on.
|
458 |
|
459 |
-
= 5.0.15 =
|
460 |
-
- New: Added a v3 reCAPTCHA type option and reCAPTCHA threshold slider to global reCAPTCHA settings. When using v3 the score will be compared to the threshold and marked as spam if it is lower than the threshold. The default value is 0.5. For more information on setting a score, see https://developers.google.com/recaptcha/docs/v3#interpreting_the_score
|
461 |
-
|
462 |
-
= 5.0.14 =
|
463 |
-
- New: HTML field descriptions now use a rich text editor instead of a plain textarea.
|
464 |
-
- New: Added a new array_separator option to entry shortcodes. This can be used with the [default-message] like [default-message array_separator="<br/>"] shortcode to change the separator used for multiple checkbox or dropdown values. It also works with the [frm-show-entry] shortcode in pro.
|
465 |
-
- New: Added tooltips to honeypot and JavaScript token spam settings.
|
466 |
-
- Fix: The adjusted color used for .frm-alt-table stripes was not calculating properly when the border color was set as an RGBA value in the style manager.
|
467 |
-
|
468 |
<a href="https://raw.githubusercontent.com/Strategy11/formidable-forms/master/changelog.txt">See changelog for all versions</a>
|
3 |
Contributors: formidableforms, sswells, srwells
|
4 |
Tags: forms, contact form, form builder, survey, free, form maker, form creator, paypal form, paypal, stripe, stripe form, aweber, aweber form, getresponse, getresponse form, calculator, price calculator, quote form, contact button, form manager, Akismet, payment form, survey form, donation form, email subscription, contact form widget, user registration form, wordpress registration, wordpress login form, constant contact, mailpoet, active campaign, salesforce, hubspot, campaign monitor, quiz builder, quiz, feedback form, mailchimp form
|
5 |
Requires at least: 5.0
|
6 |
+
Tested up to: 5.9
|
7 |
Requires PHP: 5.6
|
8 |
+
Stable tag: 5.1
|
9 |
|
10 |
The most advanced WordPress forms plugin. Go beyond contact forms with our drag & drop form builder for surveys, quizzes, and more.
|
11 |
|
438 |
See all <a href="https://zapier.com/apps/formidable/integrations">Formidable Zapier Integrations</a>.
|
439 |
|
440 |
== Changelog ==
|
441 |
+
= 5.1 =
|
442 |
+
- Updated Bootstrap Multiselect to version 1.1.1, fixing issues with the accessibility of backend multiselect dropdowns for blind users.
|
443 |
+
- New: Inputs with errors will now add the aria-describedby attribute during JavaScript validation for more accessible errors.
|
444 |
+
- New: Form errors will now always include the role="alert" attribute for more accessible errors. New fields will now also include role="alert" in custom field HTML.
|
445 |
+
- New: Added a new frm_entries_column_value filter hook.
|
446 |
+
|
447 |
= 5.0.17 =
|
448 |
- The embedded CodeMirror code for compatibility with versions of WordPress before 4.9 has been removed.
|
449 |
- New: The ctype PHP extension is no longer a requirement.
|
462 |
- Fix: Radio buttons and checkboxes were appearing overlapped with labels when using the H-Code theme.
|
463 |
- Fix: Field pop ups were displaying upgrade messages even for licenses that had access to the add on.
|
464 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
465 |
<a href="https://raw.githubusercontent.com/Strategy11/formidable-forms/master/changelog.txt">See changelog for all versions</a>
|