Meta Box - Version 4.8.6

Version Description

  • Improvement: Edit link on media items now opens edit modal
  • Improvement: Refresh map when sorting meta boxes.
  • Improvement: Wrap checkbox's description into a
  • Improvement: Remove Spanish language (ES) as it's already translated on translate.wordpress.org
  • Improvement: Add support for saving zoom in map
  • Improvement: Prevent output localized strings twice.
  • Improvement: Add fallback for autoload in PHP 5.2 in case it's disabled.
  • Improvement: No need to json_encode for custom attributes. User can pass an array to custom attribute
  • Improvement: Add style for select2 library to match WordPress admin style
  • Improvement: Adds min width to select. @prop ahmadawais
  • Improvement: Added max_status option for media type fields. true to show status, false to hide
  • Improvement: Add attachment meta data to file info
  • Fix: Validation for non-Meta Box fields
  • Fix: advanced_image field after reload page F5 in Firefox
  • Fix: Cannot read property 'getFullYear' of null
  • Fix: Empty date converting to 0
  • Fix: Add missing class for image_select field which prevents setting input's name when cloning.
  • Fix: Fix bug with blank maps on the front end
  • Fix: Fix bug with cloning media fields
  • Fix: Remove empty values in clones and reset index.
  • Fix: Reset of cloned select fields
  • Fix: select_advanced with multiple=true adds empty selected option
  • Fix: No empty option for simple select field
  • Fix: Empty datetime field with timestamp => true returns January 1, 1970
  • Fix: For color picker when using with Columns extension
  • Fix: Fix bug with taxonomy advanced returns all taxonomy items for posts with no meta saved
  • Fix: Fix bug with taxonomy advanced not saving value when field isn't multiple
  • Fix: Make radio inline again
  • Fix: Wrong meta value when using helper function outside the loop
  • Fix: Validation now works for hidden elements in tabs
Download this release

Release Info

Developer rilwis
Plugin Icon 128x128 Meta Box
Version 4.8.6
Comparing to
See all releases

Code changes from version 4.8.5 to 4.8.6

css/color.css CHANGED
@@ -4,4 +4,5 @@
4
  .rwmb-color-wrapper .wp-picker-holder {
5
  position: absolute;
6
  z-index: 9;
 
7
  }
4
  .rwmb-color-wrapper .wp-picker-holder {
5
  position: absolute;
6
  z-index: 9;
7
+ min-width: 255px;
8
  }
css/input-list.css CHANGED
@@ -2,6 +2,19 @@
2
  line-height: 22px;
3
  }
4
 
 
 
 
 
 
 
 
 
 
 
 
 
 
5
  li .rwmb-input-list {
6
  margin-left: 15px;
7
  }
2
  line-height: 22px;
3
  }
4
 
5
+ .rwmb-input-list.inline li{
6
+ display:inline-block;
7
+ margin-right: 0;
8
+ line-height:1;
9
+ }
10
+ .rwmb-input-list.inline li label {
11
+ margin-right: 10px;
12
+ }
13
+
14
+ .rwmb-input-list.inline {
15
+ margin:0;
16
+ }
17
+
18
  li .rwmb-input-list {
19
  margin-left: 15px;
20
  }
css/select-advanced.css CHANGED
@@ -2,7 +2,12 @@
2
  height: auto;
3
  min-width: 200px;
4
  }
5
-
6
- #post-body .rwmb-select-all {
7
  margin-top: 5px;
8
- }
 
 
 
 
 
2
  height: auto;
3
  min-width: 200px;
4
  }
5
+ #wpbody .rwmb-select-all {
6
+ display: block;
7
  margin-top: 5px;
8
+ }
9
+ #wpbody .select2-selection--single,
10
+ #wpbody .select2-selection--multiple,
11
+ .select2-dropdown {
12
+ border-color: #ddd;
13
+ }
css/select.css CHANGED
@@ -1,3 +1,9 @@
 
 
 
 
 
 
1
  .rwmb-select-all-none {
2
  display: block;
3
  margin-top: 5px;
1
+ .rwmb-select {
2
+ min-width: 160px;
3
+ }
4
+ .rwmb-select option {
5
+ padding: .5rem 1rem;
6
+ }
7
  .rwmb-select-all-none {
8
  display: block;
9
  margin-top: 5px;
css/style.css CHANGED
@@ -26,6 +26,7 @@
26
  .rwmb-label.required > span {
27
  color: #c00;
28
  font-weight: bold;
 
29
  }
30
 
31
  /* 75% if field has label, 100% if no label */
26
  .rwmb-label.required > span {
27
  color: #c00;
28
  font-weight: bold;
29
+ margin-left: 3px;
30
  }
31
 
32
  /* 75% if field has label, 100% if no label */
css/upload.css CHANGED
@@ -16,7 +16,7 @@
16
  -webkit-transform: translateY(-50%);
17
  -moz-transform: translateY(-50%);
18
  -ms-transform: translateY(-50%);
19
- margin-top:
20
  }
21
 
22
  .rwmb-upload-inside p, .rwmb-upload-inside h3 {
16
  -webkit-transform: translateY(-50%);
17
  -moz-transform: translateY(-50%);
18
  -ms-transform: translateY(-50%);
19
+ margin-top: 10px;
20
  }
21
 
22
  .rwmb-upload-inside p, .rwmb-upload-inside h3 {
inc/field.php CHANGED
@@ -1,4 +1,5 @@
1
  <?php
 
2
  /**
3
  * Base field class which defines all necessary methods.
4
  * Fields must inherit this class and overwrite methods with its own.
@@ -106,7 +107,7 @@ abstract class RWMB_Field
106
  $html = RWMB_Core::filter( 'wrapper_html', "$begin$field_html$end", $field, $meta );
107
 
108
  // Display label and input in DIV and allow user-defined classes to be appended
109
- $classes = "rwmb-field rwmb-{$field['type']}-wrapper " . $field['class'] ;
110
  if ( 'hidden' === $field['type'] )
111
  $classes .= ' hidden';
112
  if ( ! empty( $field['required'] ) )
@@ -304,13 +305,15 @@ abstract class RWMB_Field
304
  // If field is cloneable, value is saved as a single entry in the database
305
  if ( $field['clone'] )
306
  {
307
- // Reset indexes
308
- $new = array_values( (array) $new );
309
  foreach ( $new as $k => $v )
310
  {
311
- if ( '' === $v )
312
  unset( $new[$k] );
313
  }
 
 
314
  update_post_meta( $post_id, $name, $new );
315
  return;
316
  }
@@ -400,14 +403,18 @@ abstract class RWMB_Field
400
  static function render_attributes( $attributes )
401
  {
402
  $output = '';
 
403
  foreach ( $attributes as $key => $value )
404
  {
405
  if ( false === $value || '' === $value )
406
- {
407
  continue;
408
- }
 
 
 
409
  $output .= sprintf( true === $value ? ' %s' : ' %s="%s"', $key, esc_attr( $value ) );
410
  }
 
411
  return $output;
412
  }
413
 
1
  <?php
2
+
3
  /**
4
  * Base field class which defines all necessary methods.
5
  * Fields must inherit this class and overwrite methods with its own.
107
  $html = RWMB_Core::filter( 'wrapper_html', "$begin$field_html$end", $field, $meta );
108
 
109
  // Display label and input in DIV and allow user-defined classes to be appended
110
+ $classes = "rwmb-field rwmb-{$field['type']}-wrapper " . $field['class'];
111
  if ( 'hidden' === $field['type'] )
112
  $classes .= ' hidden';
113
  if ( ! empty( $field['required'] ) )
305
  // If field is cloneable, value is saved as a single entry in the database
306
  if ( $field['clone'] )
307
  {
308
+ // Remove empty values
309
+ $new = (array) $new;
310
  foreach ( $new as $k => $v )
311
  {
312
+ if ( '' === $v || array() === $v )
313
  unset( $new[$k] );
314
  }
315
+ // Reset indexes
316
+ $new = array_values( $new );
317
  update_post_meta( $post_id, $name, $new );
318
  return;
319
  }
403
  static function render_attributes( $attributes )
404
  {
405
  $output = '';
406
+
407
  foreach ( $attributes as $key => $value )
408
  {
409
  if ( false === $value || '' === $value )
 
410
  continue;
411
+
412
+ if ( is_array( $value ) )
413
+ $value = json_encode( $value );
414
+
415
  $output .= sprintf( true === $value ? ' %s' : ' %s="%s"', $key, esc_attr( $value ) );
416
  }
417
+
418
  return $output;
419
  }
420
 
inc/fields/autocomplete.php CHANGED
@@ -1,4 +1,5 @@
1
  <?php
 
2
  /**
3
  * Autocomplete field class.
4
  */
@@ -11,7 +12,16 @@ class RWMB_Autocomplete_Field extends RWMB_Multiple_Values_Field
11
  {
12
  wp_enqueue_style( 'rwmb-autocomplete', RWMB_CSS_URL . 'autocomplete.css', array( 'wp-admin' ), RWMB_VER );
13
  wp_enqueue_script( 'rwmb-autocomplete', RWMB_JS_URL . 'autocomplete.js', array( 'jquery-ui-autocomplete' ), RWMB_VER, true );
14
- wp_localize_script( 'rwmb-autocomplete', 'RWMB_Autocomplete', array( 'delete' => __( 'Delete', 'meta-box' ) ) );
 
 
 
 
 
 
 
 
 
15
  }
16
 
17
  /**
1
  <?php
2
+
3
  /**
4
  * Autocomplete field class.
5
  */
12
  {
13
  wp_enqueue_style( 'rwmb-autocomplete', RWMB_CSS_URL . 'autocomplete.css', array( 'wp-admin' ), RWMB_VER );
14
  wp_enqueue_script( 'rwmb-autocomplete', RWMB_JS_URL . 'autocomplete.js', array( 'jquery-ui-autocomplete' ), RWMB_VER, true );
15
+
16
+ /**
17
+ * Prevent loading localized string twice.
18
+ * @link https://github.com/rilwis/meta-box/issues/850
19
+ */
20
+ $wp_scripts = wp_scripts();
21
+ if ( ! $wp_scripts->get_data( 'rwmb-autocomplete', 'data' ) )
22
+ {
23
+ wp_localize_script( 'rwmb-autocomplete', 'RWMB_Autocomplete', array( 'delete' => __( 'Delete', 'meta-box' ) ) );
24
+ }
25
  }
26
 
27
  /**
inc/fields/checkbox.php CHANGED
@@ -7,7 +7,7 @@ class RWMB_Checkbox_Field extends RWMB_Input_Field
7
  /**
8
  * Enqueue scripts and styles.
9
  */
10
- static function admin_enqueue_scripts()
11
  {
12
  wp_enqueue_style( 'rwmb-checkbox', RWMB_CSS_URL . 'checkbox.css', array(), RWMB_VER );
13
  }
@@ -19,14 +19,37 @@ class RWMB_Checkbox_Field extends RWMB_Input_Field
19
  * @param array $field
20
  * @return string
21
  */
22
- static function html( $meta, $field )
23
  {
24
  $attributes = self::get_attributes( $field, 1 );
25
- return sprintf(
26
  '<input %s %s>',
27
  self::render_attributes( $attributes ),
28
  checked( ! empty( $meta ), 1, false )
29
  );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
30
  }
31
 
32
  /**
@@ -36,9 +59,9 @@ class RWMB_Checkbox_Field extends RWMB_Input_Field
36
  * @param mixed $value
37
  * @return array
38
  */
39
- static function get_attributes( $field, $value = null )
40
  {
41
- $attributes = parent::get_attributes( $field, $value );
42
  $attributes['type'] = 'checkbox';
43
  $attributes['list'] = false;
44
 
@@ -58,7 +81,7 @@ class RWMB_Checkbox_Field extends RWMB_Input_Field
58
  *
59
  * @return int
60
  */
61
- static function value( $new, $old, $post_id, $field )
62
  {
63
  return empty( $new ) ? 0 : 1;
64
  }
@@ -79,7 +102,7 @@ class RWMB_Checkbox_Field extends RWMB_Input_Field
79
  *
80
  * @return string HTML output of the field
81
  */
82
- static function the_value( $field, $args = array(), $post_id = null )
83
  {
84
  $value = self::get_value( $field, $args, $post_id );
85
  return $value ? __( 'Yes', 'meta-box' ) : __( 'No', 'meta-box' );
7
  /**
8
  * Enqueue scripts and styles.
9
  */
10
+ public static function admin_enqueue_scripts()
11
  {
12
  wp_enqueue_style( 'rwmb-checkbox', RWMB_CSS_URL . 'checkbox.css', array(), RWMB_VER );
13
  }
19
  * @param array $field
20
  * @return string
21
  */
22
+ public static function html( $meta, $field )
23
  {
24
  $attributes = self::get_attributes( $field, 1 );
25
+ $output = sprintf(
26
  '<input %s %s>',
27
  self::render_attributes( $attributes ),
28
  checked( ! empty( $meta ), 1, false )
29
  );
30
+ if ( $field['desc'] )
31
+ {
32
+ $output = "<label id='{$field['id']}_description' class='description'>$output {$field['desc']}</label>";
33
+ }
34
+ return $output;
35
+ }
36
+
37
+ /**
38
+ * Show end HTML markup for fields
39
+ *
40
+ * @param mixed $meta
41
+ * @param array $field
42
+ *
43
+ * @return string
44
+ */
45
+ public static function end_html( $meta, $field )
46
+ {
47
+ $button = $field['clone'] ? call_user_func( array( RW_Meta_Box::get_class_name( $field ), 'add_clone_button' ), $field ) : '';
48
+
49
+ // Closes the container
50
+ $html = "{$button}</div>";
51
+
52
+ return $html;
53
  }
54
 
55
  /**
59
  * @param mixed $value
60
  * @return array
61
  */
62
+ public static function get_attributes( $field, $value = null )
63
  {
64
+ $attributes = parent::get_attributes( $field, $value );
65
  $attributes['type'] = 'checkbox';
66
  $attributes['list'] = false;
67
 
81
  *
82
  * @return int
83
  */
84
+ public static function value( $new, $old, $post_id, $field )
85
  {
86
  return empty( $new ) ? 0 : 1;
87
  }
102
  *
103
  * @return string HTML output of the field
104
  */
105
+ public static function the_value( $field, $args = array(), $post_id = null )
106
  {
107
  $value = self::get_value( $field, $args, $post_id );
108
  return $value ? __( 'Yes', 'meta-box' ) : __( 'No', 'meta-box' );
inc/fields/datetime.php CHANGED
@@ -75,14 +75,26 @@ class RWMB_Datetime_Field extends RWMB_Text_Field
75
  wp_register_script( 'rwmb-datetime', RWMB_JS_URL . 'datetime.js', $deps, RWMB_VER, true );
76
  wp_register_script( 'rwmb-date', RWMB_JS_URL . 'date.js', $deps, RWMB_VER, true );
77
  wp_register_script( 'rwmb-time', RWMB_JS_URL . 'time.js', array( 'jquery-ui-timepicker-i18n' ), RWMB_VER, true );
78
- wp_localize_script( 'rwmb-datetime', 'RWMB_Datetimepicker', array(
79
- 'locale' => $locale,
80
- 'localeShort' => $locale_short,
81
- ) );
82
- wp_localize_script( 'rwmb-time', 'RWMB_Timepicker', array(
83
- 'locale' => $locale,
84
- 'localeShort' => $locale_short,
85
- ) );
 
 
 
 
 
 
 
 
 
 
 
 
86
  }
87
 
88
  /**
@@ -149,12 +161,12 @@ class RWMB_Datetime_Field extends RWMB_Text_Field
149
  {
150
  foreach ( $new as $key => $value )
151
  {
152
- $new[$key] = isset( $value['timestamp'] ) ? $value['timestamp'] : 0;
153
  }
154
  return $new;
155
  }
156
 
157
- return isset( $new['timestamp'] ) ? $new['timestamp'] : 0;
158
  }
159
 
160
  /**
@@ -179,16 +191,16 @@ class RWMB_Datetime_Field extends RWMB_Text_Field
179
  foreach ( $meta as $key => $value )
180
  {
181
  $meta[$key] = array(
182
- 'timestamp' => $value,
183
- 'formatted' => date( call_user_func( $method, $field ), intval( $value ) ),
184
  );
185
  }
186
  }
187
  else
188
  {
189
  $meta = array(
190
- 'timestamp' => $meta,
191
- 'formatted' => date( call_user_func( $method, $field ), intval( $meta ) ),
192
  );
193
  }
194
  return $meta;
75
  wp_register_script( 'rwmb-datetime', RWMB_JS_URL . 'datetime.js', $deps, RWMB_VER, true );
76
  wp_register_script( 'rwmb-date', RWMB_JS_URL . 'date.js', $deps, RWMB_VER, true );
77
  wp_register_script( 'rwmb-time', RWMB_JS_URL . 'time.js', array( 'jquery-ui-timepicker-i18n' ), RWMB_VER, true );
78
+
79
+ /**
80
+ * Prevent loading localized string twice.
81
+ * @link https://github.com/rilwis/meta-box/issues/850
82
+ */
83
+ $wp_scripts = wp_scripts();
84
+ if ( ! $wp_scripts->get_data( 'rwmb-datetime', 'data' ) )
85
+ {
86
+ wp_localize_script( 'rwmb-datetime', 'RWMB_Datetimepicker', array(
87
+ 'locale' => $locale,
88
+ 'localeShort' => $locale_short,
89
+ ) );
90
+ }
91
+ if ( ! $wp_scripts->get_data( 'rwmb-time', 'data' ) )
92
+ {
93
+ wp_localize_script( 'rwmb-time', 'RWMB_Timepicker', array(
94
+ 'locale' => $locale,
95
+ 'localeShort' => $locale_short,
96
+ ) );
97
+ }
98
  }
99
 
100
  /**
161
  {
162
  foreach ( $new as $key => $value )
163
  {
164
+ $new[$key] = isset( $value['timestamp'] ) ? $value['timestamp'] : null;
165
  }
166
  return $new;
167
  }
168
 
169
+ return isset( $new['timestamp'] ) ? $new['timestamp'] : null;
170
  }
171
 
172
  /**
191
  foreach ( $meta as $key => $value )
192
  {
193
  $meta[$key] = array(
194
+ 'timestamp' => ( $value != "" ) ? $value : null,
195
+ 'formatted' => ( $value != "" ) ? date( call_user_func( $method, $field ), intval( $value ) ) : "",
196
  );
197
  }
198
  }
199
  else
200
  {
201
  $meta = array(
202
+ 'timestamp' => ( $meta != "" ) ? $meta : null,
203
+ 'formatted' => ( $meta != "" ) ? date( call_user_func( $method, $field ), intval( $meta ) ) : "",
204
  );
205
  }
206
  return $meta;
inc/fields/file-input.php CHANGED
@@ -1,4 +1,5 @@
1
  <?php
 
2
  /**
3
  * File input field class which uses an input for file URL.
4
  */
@@ -11,12 +12,19 @@ class RWMB_File_Input_Field extends RWMB_Field
11
  */
12
  static function admin_enqueue_scripts()
13
  {
14
- // Make sure scripts for new media uploader in WordPress 3.5 is enqueued
15
  wp_enqueue_media();
16
  wp_enqueue_script( 'rwmb-file-input', RWMB_JS_URL . 'file-input.js', array( 'jquery' ), RWMB_VER, true );
17
- wp_localize_script( 'rwmb-file-input', 'rwmbFileInput', array(
18
- 'frameTitle' => __( 'Select File', 'meta-box' ),
19
- ) );
 
 
 
 
 
 
 
 
20
  }
21
 
22
  /**
1
  <?php
2
+
3
  /**
4
  * File input field class which uses an input for file URL.
5
  */
12
  */
13
  static function admin_enqueue_scripts()
14
  {
 
15
  wp_enqueue_media();
16
  wp_enqueue_script( 'rwmb-file-input', RWMB_JS_URL . 'file-input.js', array( 'jquery' ), RWMB_VER, true );
17
+ /**
18
+ * Prevent loading localized string twice.
19
+ * @link https://github.com/rilwis/meta-box/issues/850
20
+ */
21
+ $wp_scripts = wp_scripts();
22
+ if ( ! $wp_scripts->get_data( 'rwmb-file-input', 'data' ) )
23
+ {
24
+ wp_localize_script( 'rwmb-file-input', 'rwmbFileInput', array(
25
+ 'frameTitle' => __( 'Select File', 'meta-box' ),
26
+ ) );
27
+ }
28
  }
29
 
30
  /**
inc/fields/file.php CHANGED
@@ -1,4 +1,5 @@
1
  <?php
 
2
  /**
3
  * File field class which uses HTML <input type="file"> to upload file.
4
  */
@@ -11,10 +12,19 @@ class RWMB_File_Field extends RWMB_Field
11
  {
12
  wp_enqueue_style( 'rwmb-file', RWMB_CSS_URL . 'file.css', array(), RWMB_VER );
13
  wp_enqueue_script( 'rwmb-file', RWMB_JS_URL . 'file.js', array( 'jquery' ), RWMB_VER, true );
14
- wp_localize_script( 'rwmb-file', 'rwmbFile', array(
15
- 'maxFileUploadsSingle' => __( 'You may only upload maximum %d file', 'meta-box' ),
16
- 'maxFileUploadsPlural' => __( 'You may only upload maximum %d files', 'meta-box' ),
17
- ) );
 
 
 
 
 
 
 
 
 
18
  }
19
 
20
  /**
@@ -356,12 +366,14 @@ class RWMB_File_Field extends RWMB_Field
356
  return false;
357
  }
358
 
359
- return array(
360
  'ID' => $file_id,
361
  'name' => basename( $path ),
362
  'path' => $path,
363
  'url' => wp_get_attachment_url( $file_id ),
364
  'title' => get_the_title( $file_id ),
365
  );
 
 
366
  }
367
  }
1
  <?php
2
+
3
  /**
4
  * File field class which uses HTML <input type="file"> to upload file.
5
  */
12
  {
13
  wp_enqueue_style( 'rwmb-file', RWMB_CSS_URL . 'file.css', array(), RWMB_VER );
14
  wp_enqueue_script( 'rwmb-file', RWMB_JS_URL . 'file.js', array( 'jquery' ), RWMB_VER, true );
15
+
16
+ /**
17
+ * Prevent loading localized string twice.
18
+ * @link https://github.com/rilwis/meta-box/issues/850
19
+ */
20
+ $wp_scripts = wp_scripts();
21
+ if ( ! $wp_scripts->get_data( 'rwmb-file', 'data' ) )
22
+ {
23
+ wp_localize_script( 'rwmb-file', 'rwmbFile', array(
24
+ 'maxFileUploadsSingle' => __( 'You may only upload maximum %d file', 'meta-box' ),
25
+ 'maxFileUploadsPlural' => __( 'You may only upload maximum %d files', 'meta-box' ),
26
+ ) );
27
+ }
28
  }
29
 
30
  /**
366
  return false;
367
  }
368
 
369
+ $info = array(
370
  'ID' => $file_id,
371
  'name' => basename( $path ),
372
  'path' => $path,
373
  'url' => wp_get_attachment_url( $file_id ),
374
  'title' => get_the_title( $file_id ),
375
  );
376
+
377
+ return wp_parse_args( $info, wp_get_attachment_metadata( $file_id ) );
378
  }
379
  }
inc/fields/image-select.php CHANGED
@@ -23,7 +23,7 @@ class RWMB_Image_Select_Field extends RWMB_Field
23
  static function html( $meta, $field )
24
  {
25
  $html = array();
26
- $tpl = '<label class="rwmb-image-select"><img src="%s"><input type="%s" class="hidden" name="%s" value="%s"%s></label>';
27
 
28
  $meta = (array) $meta;
29
  foreach ( $field['options'] as $value => $image )
23
  static function html( $meta, $field )
24
  {
25
  $html = array();
26
+ $tpl = '<label class="rwmb-image-select"><img src="%s"><input type="%s" class="rwmb-image_select hidden" name="%s" value="%s"%s></label>';
27
 
28
  $meta = (array) $meta;
29
  foreach ( $field['options'] as $value => $image )
inc/fields/image.php CHANGED
@@ -217,8 +217,6 @@ class RWMB_Image_Field extends RWMB_File_Field
217
  'name' => basename( $path ),
218
  'path' => $path,
219
  'url' => $img_src[0],
220
- 'width' => $img_src[1],
221
- 'height' => $img_src[2],
222
  'full_url' => wp_get_attachment_url( $file_id ),
223
  'title' => $attachment->post_title,
224
  'caption' => $attachment->post_excerpt,
@@ -229,6 +227,8 @@ class RWMB_Image_Field extends RWMB_File_Field
229
  {
230
  $info['srcset'] = wp_get_attachment_image_srcset( $file_id );
231
  }
 
 
232
  return $info;
233
  }
234
  }
217
  'name' => basename( $path ),
218
  'path' => $path,
219
  'url' => $img_src[0],
 
 
220
  'full_url' => wp_get_attachment_url( $file_id ),
221
  'title' => $attachment->post_title,
222
  'caption' => $attachment->post_excerpt,
227
  {
228
  $info['srcset'] = wp_get_attachment_image_srcset( $file_id );
229
  }
230
+
231
+ $info = wp_parse_args( $info, wp_get_attachment_metadata( $file_id ) );
232
  return $info;
233
  }
234
  }
inc/fields/input-list.php CHANGED
@@ -26,7 +26,10 @@ class RWMB_Input_List_Field extends RWMB_Choice_Field
26
  public static function walk( $options, $db_fields, $meta, $field )
27
  {
28
  $walker = new RWMB_Input_List_Walker( $db_fields, $field, $meta );
29
- $output = sprintf( '<ul class="rwmb-input-list %s">', $field['collapse'] ? 'collapse' : '' );
 
 
 
30
  $output .= $walker->walk( $options, $field['flatten'] ? - 1 : 0 );
31
  $output .= '</ul>';
32
 
@@ -46,9 +49,11 @@ class RWMB_Input_List_Field extends RWMB_Choice_Field
46
  $field = parent::normalize( $field );
47
  $field = wp_parse_args( $field, array(
48
  'collapse' => true,
 
49
  ) );
50
 
51
  $field['flatten'] = $field['multiple'] ? $field['flatten'] : true;
 
52
 
53
  return $field;
54
  }
@@ -63,10 +68,10 @@ class RWMB_Input_List_Field extends RWMB_Choice_Field
63
  */
64
  public static function get_attributes( $field, $value = null )
65
  {
66
- $attributes = RWMB_Input_Field::get_attributes( $field, $value );
67
- $attributes['id'] = false;
68
- $attributes['type'] = $field['multiple'] ? 'checkbox' : 'radio';
69
- $attributes['value'] = $value;
70
 
71
  return $attributes;
72
  }
26
  public static function walk( $options, $db_fields, $meta, $field )
27
  {
28
  $walker = new RWMB_Input_List_Walker( $db_fields, $field, $meta );
29
+ $output = sprintf( '<ul class="rwmb-input-list %s %s">',
30
+ $field['collapse'] ? 'collapse' : '',
31
+ $field['inline'] ? 'inline' : ''
32
+ );
33
  $output .= $walker->walk( $options, $field['flatten'] ? - 1 : 0 );
34
  $output .= '</ul>';
35
 
49
  $field = parent::normalize( $field );
50
  $field = wp_parse_args( $field, array(
51
  'collapse' => true,
52
+ 'inline' => null,
53
  ) );
54
 
55
  $field['flatten'] = $field['multiple'] ? $field['flatten'] : true;
56
+ $field['inline'] = ! $field['multiple'] && ! isset( $field['inline'] ) ? true : $field['inline'];
57
 
58
  return $field;
59
  }
68
  */
69
  public static function get_attributes( $field, $value = null )
70
  {
71
+ $attributes = RWMB_Input_Field::get_attributes( $field, $value );
72
+ $attributes['id'] = false;
73
+ $attributes['type'] = $field['multiple'] ? 'checkbox' : 'radio';
74
+ $attributes['value'] = $value;
75
 
76
  return $attributes;
77
  }
inc/fields/media.php CHANGED
@@ -1,4 +1,5 @@
1
  <?php
 
2
  /**
3
  * Media field class which users WordPress media popup to upload and select files.
4
  */
@@ -13,20 +14,29 @@ class RWMB_Media_Field extends RWMB_Field
13
  {
14
  wp_enqueue_media();
15
  wp_enqueue_style( 'rwmb-media', RWMB_CSS_URL . 'media.css', array(), RWMB_VER );
16
- wp_enqueue_script( 'rwmb-media', RWMB_JS_URL . 'media.js', array( 'jquery-ui-sortable', 'underscore', 'backbone' ), RWMB_VER, true );
17
- wp_localize_script( 'rwmb-media', 'i18nRwmbMedia', array(
18
- 'add' => apply_filters( 'rwmb_media_add_string', _x( '+ Add Media', 'media', 'meta-box' ) ),
19
- 'single' => apply_filters( 'rwmb_media_single_files_string', _x( ' file', 'media', 'meta-box' ) ),
20
- 'multiple' => apply_filters( 'rwmb_media_multiple_files_string', _x( ' files', 'media', 'meta-box' ) ),
21
- 'remove' => apply_filters( 'rwmb_media_remove_string', _x( 'Remove', 'media', 'meta-box' ) ),
22
- 'edit' => apply_filters( 'rwmb_media_edit_string', _x( 'Edit', 'media', 'meta-box' ) ),
23
- 'view' => apply_filters( 'rwmb_media_view_string', _x( 'View', 'media', 'meta-box' ) ),
24
- 'noTitle' => _x( 'No Title', 'media', 'meta-box' ),
25
- 'loadingUrl' => RWMB_URL . 'img/loader.gif',
26
- 'extensions' => self::get_mime_extensions(),
27
- 'select' => _x( 'Select Files', 'media', 'meta-box' ),
28
- 'uploadInstructions' => _x( 'Drop files here to upload', 'media', 'meta-box' )
29
- ) );
 
 
 
 
 
 
 
 
 
30
  }
31
 
32
  /**
@@ -50,17 +60,18 @@ class RWMB_Media_Field extends RWMB_Field
50
  */
51
  static function html( $meta, $field )
52
  {
53
- $meta = (array) $meta;
54
- $meta = implode( ',', $meta );
55
- $attributes = self::get_attributes( $field, $meta );
56
 
57
  $html = sprintf(
58
  '<input %s>
59
- <div class="rwmb-media-view" data-mime-type="%s" data-max-files="%s" data-force-delete="%s"></div>',
60
  self::render_attributes( $attributes ),
61
  $field['mime_type'],
62
  $field['max_file_uploads'],
63
- $field['force_delete'] ? 'true' : 'false'
 
64
  );
65
 
66
  return $html;
@@ -81,6 +92,7 @@ class RWMB_Media_Field extends RWMB_Field
81
  'mime_type' => '',
82
  'max_file_uploads' => 0,
83
  'force_delete' => false,
 
84
  ) );
85
 
86
  $field['multiple'] = true;
@@ -98,9 +110,9 @@ class RWMB_Media_Field extends RWMB_Field
98
  */
99
  static function get_attributes( $field, $value = null )
100
  {
101
- $attributes = parent::get_attributes( $field, $value );
102
- $attributes['type'] = 'hidden';
103
- $attributes['name'] .= ! $field['clone'] && $field['multiple'] ? '[]' : '';
104
  $attributes['disabled'] = true;
105
  $attributes['id'] = false;
106
  $attributes['value'] = $value;
@@ -112,15 +124,15 @@ class RWMB_Media_Field extends RWMB_Field
112
  {
113
  $mime_types = wp_get_mime_types();
114
  $extensions = array();
115
- foreach( $mime_types as $ext => $mime )
116
  {
117
- $ext = explode( '|', $ext );
118
- $extensions[ $mime ] = $ext;
119
 
120
  $mime_parts = explode( '/', $mime );
121
- if( empty( $extensions[ $mime_parts[0] ] ) )
122
- $extensions[ $mime_parts[0] ] = array();
123
- $extensions[ $mime_parts[0] ] = $extensions[ $mime_parts[0] . '/*' ] = array_merge( $extensions[ $mime_parts[0] ], $ext );
124
 
125
  }
126
 
@@ -141,6 +153,33 @@ class RWMB_Media_Field extends RWMB_Field
141
  parent::save( $new, array(), $post_id, $field );
142
  }
143
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
144
  /**
145
  * Template for media item
146
  * @return void
1
  <?php
2
+
3
  /**
4
  * Media field class which users WordPress media popup to upload and select files.
5
  */
14
  {
15
  wp_enqueue_media();
16
  wp_enqueue_style( 'rwmb-media', RWMB_CSS_URL . 'media.css', array(), RWMB_VER );
17
+ wp_enqueue_script( 'rwmb-media', RWMB_JS_URL . 'media.js', array( 'jquery-ui-sortable', 'underscore', 'backbone', 'media-grid' ), RWMB_VER, true );
18
+
19
+ /**
20
+ * Prevent loading localized string twice.
21
+ * @link https://github.com/rilwis/meta-box/issues/850
22
+ */
23
+ $wp_scripts = wp_scripts();
24
+ if ( ! $wp_scripts->get_data( 'rwmb-media', 'data' ) )
25
+ {
26
+ wp_localize_script( 'rwmb-media', 'i18nRwmbMedia', array(
27
+ 'add' => apply_filters( 'rwmb_media_add_string', _x( '+ Add Media', 'media', 'meta-box' ) ),
28
+ 'single' => apply_filters( 'rwmb_media_single_files_string', _x( ' file', 'media', 'meta-box' ) ),
29
+ 'multiple' => apply_filters( 'rwmb_media_multiple_files_string', _x( ' files', 'media', 'meta-box' ) ),
30
+ 'remove' => apply_filters( 'rwmb_media_remove_string', _x( 'Remove', 'media', 'meta-box' ) ),
31
+ 'edit' => apply_filters( 'rwmb_media_edit_string', _x( 'Edit', 'media', 'meta-box' ) ),
32
+ 'view' => apply_filters( 'rwmb_media_view_string', _x( 'View', 'media', 'meta-box' ) ),
33
+ 'noTitle' => _x( 'No Title', 'media', 'meta-box' ),
34
+ 'loadingUrl' => RWMB_URL . 'img/loader.gif',
35
+ 'extensions' => self::get_mime_extensions(),
36
+ 'select' => _x( 'Select Files', 'media', 'meta-box' ),
37
+ 'uploadInstructions' => _x( 'Drop files here to upload', 'media', 'meta-box' ),
38
+ ) );
39
+ }
40
  }
41
 
42
  /**
60
  */
61
  static function html( $meta, $field )
62
  {
63
+ $meta = (array) $meta;
64
+ $meta = implode( ',', $meta );
65
+ $attributes = $load_test_attr = self::get_attributes( $field, $meta );
66
 
67
  $html = sprintf(
68
  '<input %s>
69
+ <div class="rwmb-media-view" data-mime-type="%s" data-max-files="%s" data-force-delete="%s" data-show-status="%s"></div>',
70
  self::render_attributes( $attributes ),
71
  $field['mime_type'],
72
  $field['max_file_uploads'],
73
+ $field['force_delete'] ? 'true' : 'false',
74
+ $field['max_status']
75
  );
76
 
77
  return $html;
92
  'mime_type' => '',
93
  'max_file_uploads' => 0,
94
  'force_delete' => false,
95
+ 'max_status' => true,
96
  ) );
97
 
98
  $field['multiple'] = true;
110
  */
111
  static function get_attributes( $field, $value = null )
112
  {
113
+ $attributes = parent::get_attributes( $field, $value );
114
+ $attributes['type'] = 'hidden';
115
+ $attributes['name'] .= ! $field['clone'] && $field['multiple'] ? '[]' : '';
116
  $attributes['disabled'] = true;
117
  $attributes['id'] = false;
118
  $attributes['value'] = $value;
124
  {
125
  $mime_types = wp_get_mime_types();
126
  $extensions = array();
127
+ foreach ( $mime_types as $ext => $mime )
128
  {
129
+ $ext = explode( '|', $ext );
130
+ $extensions[$mime] = $ext;
131
 
132
  $mime_parts = explode( '/', $mime );
133
+ if ( empty( $extensions[$mime_parts[0]] ) )
134
+ $extensions[$mime_parts[0]] = array();
135
+ $extensions[$mime_parts[0]] = $extensions[$mime_parts[0] . '/*'] = array_merge( $extensions[$mime_parts[0]], $ext );
136
 
137
  }
138
 
153
  parent::save( $new, array(), $post_id, $field );
154
  }
155
 
156
+ /**
157
+ * Get meta values to save
158
+ *
159
+ * @param mixed $new
160
+ * @param mixed $old
161
+ * @param int $post_id
162
+ * @param array $field
163
+ *
164
+ * @return array|mixed
165
+ */
166
+ static function value( $new, $old, $post_id, $field )
167
+ {
168
+ if ( $field['clone'] )
169
+ {
170
+ foreach ( (array) $new as $n )
171
+ {
172
+ if ( - 1 === intval( $n ) )
173
+ return $old;
174
+ }
175
+ }
176
+
177
+ if ( - 1 === intval( $new ) )
178
+ return $old;
179
+
180
+ return $new;
181
+ }
182
+
183
  /**
184
  * Template for media item
185
  * @return void
inc/fields/select-advanced.php CHANGED
@@ -15,7 +15,7 @@ class RWMB_Select_Advanced_Field extends RWMB_Select_Field
15
 
16
  wp_register_script( 'rwmb-select2', RWMB_JS_URL . 'select2/select2.min.js', array(), '4.0.2', true );
17
 
18
- //Localize
19
  $deps = array( 'rwmb-select2', 'rwmb-select' );
20
  $dir = RWMB_JS_URL . 'select2/i18n/';
21
  $file = str_replace( '_', '-', get_locale() );
@@ -30,7 +30,6 @@ class RWMB_Select_Advanced_Field extends RWMB_Select_Field
30
 
31
  wp_enqueue_script( 'rwmb-select', RWMB_JS_URL . 'select.js', array(), RWMB_VER, true );
32
  wp_enqueue_script( 'rwmb-select-advanced', RWMB_JS_URL . 'select-advanced.js', $deps, RWMB_VER, true );
33
-
34
  }
35
 
36
  /**
@@ -52,7 +51,6 @@ class RWMB_Select_Advanced_Field extends RWMB_Select_Field
52
  self::render_attributes( $attributes )
53
  );
54
 
55
- $output .= '<option></option>';
56
  $output .= $walker->walk( $options, $field['flatten'] ? - 1 : 0 );
57
  $output .= '</select>';
58
  $output .= self::get_select_all_html( $field );
@@ -69,7 +67,7 @@ class RWMB_Select_Advanced_Field extends RWMB_Select_Field
69
  {
70
  $field = wp_parse_args( $field, array(
71
  'js_options' => array(),
72
- 'placeholder' => 'Select an item',
73
  ) );
74
 
75
  $field = parent::normalize( $field );
15
 
16
  wp_register_script( 'rwmb-select2', RWMB_JS_URL . 'select2/select2.min.js', array(), '4.0.2', true );
17
 
18
+ // Localize
19
  $deps = array( 'rwmb-select2', 'rwmb-select' );
20
  $dir = RWMB_JS_URL . 'select2/i18n/';
21
  $file = str_replace( '_', '-', get_locale() );
30
 
31
  wp_enqueue_script( 'rwmb-select', RWMB_JS_URL . 'select.js', array(), RWMB_VER, true );
32
  wp_enqueue_script( 'rwmb-select-advanced', RWMB_JS_URL . 'select-advanced.js', $deps, RWMB_VER, true );
 
33
  }
34
 
35
  /**
51
  self::render_attributes( $attributes )
52
  );
53
 
 
54
  $output .= $walker->walk( $options, $field['flatten'] ? - 1 : 0 );
55
  $output .= '</select>';
56
  $output .= self::get_select_all_html( $field );
67
  {
68
  $field = wp_parse_args( $field, array(
69
  'js_options' => array(),
70
+ 'placeholder' => __( 'Select an item', 'meta-box' ),
71
  ) );
72
 
73
  $field = parent::normalize( $field );
inc/fields/select.php CHANGED
@@ -33,7 +33,7 @@ class RWMB_Select_Field extends RWMB_Choice_Field
33
  );
34
  if ( false === $field['multiple'] )
35
  {
36
- $output .= isset( $field['placeholder'] ) ? "<option value=''>{$field['placeholder']}</option>" : '<option></option>';
37
  }
38
  $output .= $walker->walk( $options, $field['flatten'] ? - 1 : 0 );
39
  $output .= '</select>';
33
  );
34
  if ( false === $field['multiple'] )
35
  {
36
+ $output .= $field['placeholder'] ? '<option value="">' . esc_html( $field['placeholder'] ) . '</option>' : '';
37
  }
38
  $output .= $walker->walk( $options, $field['flatten'] ? - 1 : 0 );
39
  $output .= '</select>';
inc/fields/slider.php CHANGED
@@ -29,7 +29,7 @@ class RWMB_Slider_Field extends RWMB_Field
29
  * @return string
30
  */
31
  static function html( $meta, $field )
32
- {
33
  return sprintf(
34
  '<div class="clearfix">
35
  <div class="rwmb-slider" id="%s" data-options="%s"></div>
@@ -37,8 +37,8 @@ class RWMB_Slider_Field extends RWMB_Field
37
  <input type="hidden" name="%s" value="%s" class="rwmb-slider-value">
38
  </div>',
39
  $field['id'], esc_attr( wp_json_encode( $field['js_options'] ) ),
40
- $field['prefix'], $meta, $field['suffix'],
41
- $field['field_name'], $meta
42
  );
43
  }
44
 
@@ -55,10 +55,12 @@ class RWMB_Slider_Field extends RWMB_Field
55
  $field = wp_parse_args( $field, array(
56
  'prefix' => '',
57
  'suffix' => '',
 
58
  'js_options' => array(),
59
  ) );
60
  $field['js_options'] = wp_parse_args( $field['js_options'], array(
61
  'range' => 'min', // range = 'min' will add a dark background to sliding part, better UI
 
62
  ) );
63
 
64
  return $field;
29
  * @return string
30
  */
31
  static function html( $meta, $field )
32
+ {
33
  return sprintf(
34
  '<div class="clearfix">
35
  <div class="rwmb-slider" id="%s" data-options="%s"></div>
37
  <input type="hidden" name="%s" value="%s" class="rwmb-slider-value">
38
  </div>',
39
  $field['id'], esc_attr( wp_json_encode( $field['js_options'] ) ),
40
+ $field['prefix'], ( $meta >= 0 ) ? $meta : $field['std'], $field['suffix'],
41
+ $field['field_name'], ( $meta >= 0 ) ? $meta : $field['std']
42
  );
43
  }
44
 
55
  $field = wp_parse_args( $field, array(
56
  'prefix' => '',
57
  'suffix' => '',
58
+ 'std' => '',
59
  'js_options' => array(),
60
  ) );
61
  $field['js_options'] = wp_parse_args( $field['js_options'], array(
62
  'range' => 'min', // range = 'min' will add a dark background to sliding part, better UI
63
+ 'value' => $field['std'],
64
  ) );
65
 
66
  return $field;
inc/fields/taxonomy-advanced.php CHANGED
@@ -16,9 +16,9 @@ class RWMB_Taxonomy_Advanced_Field extends RWMB_Taxonomy_Field
16
  *
17
  * @return string
18
  */
19
- static function value( $new, $old, $post_id, $field )
20
  {
21
- return is_array( $new ) ? implode( ',', array_unique( $new ) ) : null;
22
  }
23
 
24
  /**
@@ -31,7 +31,7 @@ class RWMB_Taxonomy_Advanced_Field extends RWMB_Taxonomy_Field
31
  *
32
  * @return string
33
  */
34
- static function save( $new, $old, $post_id, $field )
35
  {
36
  if ( $new )
37
  update_post_meta( $post_id, $field['id'], $new );
@@ -48,10 +48,11 @@ class RWMB_Taxonomy_Advanced_Field extends RWMB_Taxonomy_Field
48
  *
49
  * @return array
50
  */
51
- static function meta( $post_id, $saved, $field )
52
  {
53
  $meta = get_post_meta( $post_id, $field['id'], true );
54
  $meta = wp_parse_id_list( $meta );
 
55
  return $meta;
56
  }
57
 
@@ -65,12 +66,14 @@ class RWMB_Taxonomy_Advanced_Field extends RWMB_Taxonomy_Field
65
  *
66
  * @return array List of post term objects
67
  */
68
- static function get_value( $field, $args = array(), $post_id = null )
69
  {
70
  if ( ! $post_id )
71
  $post_id = get_the_ID();
72
 
73
  $value = self::meta( $post_id, '', $field );
 
 
74
 
75
  // Allow to pass more arguments to "get_terms"
76
  $args = wp_parse_args( array(
16
  *
17
  * @return string
18
  */
19
+ public static function value( $new, $old, $post_id, $field )
20
  {
21
+ return implode( ',', array_unique( (array) $new ) );
22
  }
23
 
24
  /**
31
  *
32
  * @return string
33
  */
34
+ public static function save( $new, $old, $post_id, $field )
35
  {
36
  if ( $new )
37
  update_post_meta( $post_id, $field['id'], $new );
48
  *
49
  * @return array
50
  */
51
+ public static function meta( $post_id, $saved, $field )
52
  {
53
  $meta = get_post_meta( $post_id, $field['id'], true );
54
  $meta = wp_parse_id_list( $meta );
55
+ $meta = array_filter( $meta );
56
  return $meta;
57
  }
58
 
66
  *
67
  * @return array List of post term objects
68
  */
69
+ public static function get_value( $field, $args = array(), $post_id = null )
70
  {
71
  if ( ! $post_id )
72
  $post_id = get_the_ID();
73
 
74
  $value = self::meta( $post_id, '', $field );
75
+ if( empty( $value ) )
76
+ return;
77
 
78
  // Allow to pass more arguments to "get_terms"
79
  $args = wp_parse_args( array(
inc/fields/taxonomy.php CHANGED
@@ -10,7 +10,7 @@ class RWMB_Taxonomy_Field extends RWMB_Object_Choice_Field
10
  * @param $field
11
  * @return array
12
  */
13
- static function normalize( $field )
14
  {
15
  /**
16
  * Backwards compatibility with field args
@@ -65,7 +65,7 @@ class RWMB_Taxonomy_Field extends RWMB_Object_Choice_Field
65
  *
66
  * @return array
67
  */
68
- static function get_db_fields()
69
  {
70
  return array(
71
  'parent' => 'parent',
@@ -81,7 +81,7 @@ class RWMB_Taxonomy_Field extends RWMB_Object_Choice_Field
81
  *
82
  * @return array
83
  */
84
- static function get_options( $field )
85
  {
86
  $options = get_terms( $field['taxonomy'], $field['query_args'] );
87
  return $options;
@@ -97,7 +97,7 @@ class RWMB_Taxonomy_Field extends RWMB_Object_Choice_Field
97
  *
98
  * @return string
99
  */
100
- static function save( $new, $old, $post_id, $field )
101
  {
102
  $new = array_unique( array_map( 'intval', (array) $new ) );
103
  $new = empty( $new ) ? null : $new;
@@ -113,7 +113,7 @@ class RWMB_Taxonomy_Field extends RWMB_Object_Choice_Field
113
  *
114
  * @return array
115
  */
116
- static function meta( $post_id, $saved, $field )
117
  {
118
  $meta = get_the_terms( $post_id, $field['taxonomy'] );
119
  $meta = (array) $meta;
@@ -132,7 +132,7 @@ class RWMB_Taxonomy_Field extends RWMB_Object_Choice_Field
132
  *
133
  * @return array List of post term objects
134
  */
135
- static function get_value( $field, $args = array(), $post_id = null )
136
  {
137
  $value = get_the_terms( $post_id, $field['taxonomy'] );
138
 
@@ -152,7 +152,7 @@ class RWMB_Taxonomy_Field extends RWMB_Object_Choice_Field
152
  *
153
  * @return string
154
  */
155
- static function get_option_label( $value, $field )
156
  {
157
  return sprintf(
158
  '<a href="%s" title="%s">%s</a>',
10
  * @param $field
11
  * @return array
12
  */
13
+ public static function normalize( $field )
14
  {
15
  /**
16
  * Backwards compatibility with field args
65
  *
66
  * @return array
67
  */
68
+ public static function get_db_fields()
69
  {
70
  return array(
71
  'parent' => 'parent',
81
  *
82
  * @return array
83
  */
84
+ public static function get_options( $field )
85
  {
86
  $options = get_terms( $field['taxonomy'], $field['query_args'] );
87
  return $options;
97
  *
98
  * @return string
99
  */
100
+ public static function save( $new, $old, $post_id, $field )
101
  {
102
  $new = array_unique( array_map( 'intval', (array) $new ) );
103
  $new = empty( $new ) ? null : $new;
113
  *
114
  * @return array
115
  */
116
+ public static function meta( $post_id, $saved, $field )
117
  {
118
  $meta = get_the_terms( $post_id, $field['taxonomy'] );
119
  $meta = (array) $meta;
132
  *
133
  * @return array List of post term objects
134
  */
135
+ public static function get_value( $field, $args = array(), $post_id = null )
136
  {
137
  $value = get_the_terms( $post_id, $field['taxonomy'] );
138
 
152
  *
153
  * @return string
154
  */
155
+ public static function get_option_label( $value, $field )
156
  {
157
  return sprintf(
158
  '<a href="%s" title="%s">%s</a>',
inc/fields/user.php CHANGED
@@ -11,7 +11,7 @@ class RWMB_User_Field extends RWMB_Object_Choice_Field
11
  *
12
  * @return array
13
  */
14
- static function normalize( $field )
15
  {
16
  /**
17
  * Set default field args
@@ -53,7 +53,7 @@ class RWMB_User_Field extends RWMB_Object_Choice_Field
53
  *
54
  * @return array
55
  */
56
- static function get_options( $field )
57
  {
58
  $options = get_users( $field['query_args'] );
59
  return $options;
@@ -64,7 +64,7 @@ class RWMB_User_Field extends RWMB_Object_Choice_Field
64
  *
65
  * @return array
66
  */
67
- static function get_db_fields()
68
  {
69
  return array(
70
  'parent' => 'parent',
@@ -81,7 +81,7 @@ class RWMB_User_Field extends RWMB_Object_Choice_Field
81
  *
82
  * @return string
83
  */
84
- static function get_option_label( $value, $field )
85
  {
86
  $user = get_userdata( $value );
87
  return '<a href="' . get_author_posts_url( $value ) . '">' . $user->display_name . '</a>';
11
  *
12
  * @return array
13
  */
14
+ public static function normalize( $field )
15
  {
16
  /**
17
  * Set default field args
53
  *
54
  * @return array
55
  */
56
+ public static function get_options( $field )
57
  {
58
  $options = get_users( $field['query_args'] );
59
  return $options;
64
  *
65
  * @return array
66
  */
67
+ public static function get_db_fields()
68
  {
69
  return array(
70
  'parent' => 'parent',
81
  *
82
  * @return string
83
  */
84
+ public static function get_option_label( $value, $field )
85
  {
86
  $user = get_userdata( $value );
87
  return '<a href="' . get_author_posts_url( $value ) . '">' . $user->display_name . '</a>';
inc/functions.php CHANGED
@@ -20,7 +20,7 @@ if ( ! function_exists( 'rwmb_meta' ) )
20
  * If meta boxes is registered in the backend only, we can't get field's params
21
  * This is for backward compatibility with version < 4.8.0
22
  */
23
- $field = RWMB_Helper::find_field( $key );
24
  if ( false === $field || isset( $args['type'] ) )
25
  {
26
  return apply_filters( 'rwmb_meta', RWMB_Helper::meta( $key, $args, $post_id ) );
@@ -46,7 +46,7 @@ if ( ! function_exists( 'rwmb_get_value' ) )
46
  */
47
  function rwmb_get_value( $field_id, $args = array(), $post_id = null )
48
  {
49
- $field = RWMB_Helper::find_field( $field_id );
50
 
51
  // Get field value
52
  $value = $field ? call_user_func( array( RW_Meta_Box::get_class_name( $field ), 'get_value' ), $field, $args, $post_id ) : false;
@@ -81,7 +81,7 @@ if ( ! function_exists( 'rwmb_the_value' ) )
81
  function rwmb_the_value( $field_id, $args = array(), $post_id = null, $echo = true )
82
  {
83
  // Find field
84
- $field = RWMB_Helper::find_field( $field_id );
85
 
86
  if ( ! $field )
87
  return '';
20
  * If meta boxes is registered in the backend only, we can't get field's params
21
  * This is for backward compatibility with version < 4.8.0
22
  */
23
+ $field = RWMB_Helper::find_field( $key, $post_id );
24
  if ( false === $field || isset( $args['type'] ) )
25
  {
26
  return apply_filters( 'rwmb_meta', RWMB_Helper::meta( $key, $args, $post_id ) );
46
  */
47
  function rwmb_get_value( $field_id, $args = array(), $post_id = null )
48
  {
49
+ $field = RWMB_Helper::find_field( $field_id, $post_id );
50
 
51
  // Get field value
52
  $value = $field ? call_user_func( array( RW_Meta_Box::get_class_name( $field ), 'get_value' ), $field, $args, $post_id ) : false;
81
  function rwmb_the_value( $field_id, $args = array(), $post_id = null, $echo = true )
82
  {
83
  // Find field
84
+ $field = RWMB_Helper::find_field( $field_id, $post_id );
85
 
86
  if ( ! $field )
87
  return '';
inc/loader.php CHANGED
@@ -18,7 +18,20 @@ class RWMB_Loader
18
  public function __construct()
19
  {
20
  $this->constants();
 
 
 
 
 
 
 
 
21
  spl_autoload_register( array( $this, 'autoload' ) );
 
 
 
 
 
22
  $this->init();
23
  }
24
 
@@ -28,7 +41,7 @@ class RWMB_Loader
28
  public function constants()
29
  {
30
  // Script version, used to add version for scripts and styles
31
- define( 'RWMB_VER', '4.8.5' );
32
 
33
  list( $path, $url ) = self::get_path();
34
 
@@ -60,15 +73,13 @@ class RWMB_Loader
60
  // Default URL
61
  $url = plugins_url( '', $path . '/' . basename( $path ) . '.php' );
62
 
63
- // Installed as a plugin?
64
- if ( 0 === strpos( $path, wp_normalize_path( WP_PLUGIN_DIR ) ) || 0 === strpos( $path, wp_normalize_path( WPMU_PLUGIN_DIR ) ) )
65
- {
66
- // Do nothing
67
- }
68
  // Included into themes
69
- elseif ( 0 === strpos( $path, $content_dir ) )
 
 
 
 
70
  {
71
- // Get plugin base URL
72
  $content_url = untrailingslashit( dirname( dirname( get_stylesheet_directory_uri() ) ) );
73
  $url = str_replace( $content_dir, $content_url, $path );
74
  }
@@ -115,6 +126,94 @@ class RWMB_Loader
115
  }
116
  }
117
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
118
  /**
119
  * Initialize plugin.
120
  */
18
  public function __construct()
19
  {
20
  $this->constants();
21
+
22
+ /**
23
+ * Register autoloader for plugin classes.
24
+ * In PHP 5.3, SPL extension cannot be disabled and it's safe to use autoload.
25
+ * However, hosting providers can disable it in PHP 5.2. In that case, we provide a fallback for autoload.
26
+ * @link http://php.net/manual/en/spl.installation.php
27
+ * @link https://github.com/rilwis/meta-box/issues/810
28
+ */
29
  spl_autoload_register( array( $this, 'autoload' ) );
30
+ if ( ! class_exists( 'RWMB_Core' ) )
31
+ {
32
+ $this->autoload_fallback();
33
+ }
34
+
35
  $this->init();
36
  }
37
 
41
  public function constants()
42
  {
43
  // Script version, used to add version for scripts and styles
44
+ define( 'RWMB_VER', '4.8.6' );
45
 
46
  list( $path, $url ) = self::get_path();
47
 
73
  // Default URL
74
  $url = plugins_url( '', $path . '/' . basename( $path ) . '.php' );
75
 
 
 
 
 
 
76
  // Included into themes
77
+ if (
78
+ 0 !== strpos( $path, wp_normalize_path( WP_PLUGIN_DIR ) )
79
+ && 0 !== strpos( $path, wp_normalize_path( WPMU_PLUGIN_DIR ) )
80
+ && 0 === strpos( $path, $content_dir )
81
+ )
82
  {
 
83
  $content_url = untrailingslashit( dirname( dirname( get_stylesheet_directory_uri() ) ) );
84
  $url = str_replace( $content_dir, $content_url, $path );
85
  }
126
  }
127
  }
128
 
129
+ /**
130
+ * Fallback for autoload in PHP 5.2.
131
+ */
132
+ public function autoload_fallback()
133
+ {
134
+ $files = array(
135
+ // Core
136
+ 'core',
137
+ 'helper',
138
+ 'meta-box',
139
+ 'validation',
140
+
141
+ // Walkers
142
+ 'walkers/walker',
143
+ 'walkers/select-walker',
144
+ 'walkers/select-tree-walker',
145
+ 'walkers/input-list-walker',
146
+
147
+ // Fields
148
+ 'field',
149
+
150
+ 'fields/multiple-values',
151
+ 'fields/autocomplete',
152
+ 'fields/text-list',
153
+
154
+ 'fields/choice',
155
+
156
+ 'fields/select',
157
+ 'fields/select-advanced',
158
+ 'fields/select-tree',
159
+
160
+ 'fields/input-list',
161
+ 'fields/radio',
162
+ 'fields/checkbox-list',
163
+
164
+ 'fields/object-choice',
165
+ 'fields/post',
166
+ 'fields/taxonomy',
167
+ 'fields/taxonomy-advanced',
168
+ 'fields/user',
169
+
170
+ 'fields/input',
171
+
172
+ 'fields/checkbox',
173
+ 'fields/hidden',
174
+ 'fields/number',
175
+ 'fields/range',
176
+
177
+ 'fields/text',
178
+ 'fields/color',
179
+ 'fields/datetime',
180
+ 'fields/date',
181
+ 'fields/time',
182
+ 'fields/email',
183
+ 'fields/fieldset-text',
184
+ 'fields/key-value',
185
+ 'fields/url',
186
+ 'fields/oembed',
187
+ 'fields/password',
188
+
189
+ 'fields/media',
190
+ 'fields/file-advanced',
191
+ 'fields/file-upload',
192
+ 'fields/image-advanced',
193
+ 'fields/image-upload',
194
+ 'fields/plupload-image',
195
+
196
+ 'fields/file-input',
197
+ 'fields/file',
198
+ 'fields/image',
199
+ 'fields/image-select',
200
+ 'fields/thickbox-image',
201
+
202
+ 'fields/button',
203
+ 'fields/custom-html',
204
+ 'fields/divider',
205
+ 'fields/heading',
206
+ 'fields/map',
207
+ 'fields/slider',
208
+ 'fields/textarea',
209
+ 'fields/wysiwyg',
210
+ );
211
+ foreach ( $files as $file )
212
+ {
213
+ require RWMB_INC_DIR . "$file.php";
214
+ }
215
+ }
216
+
217
  /**
218
  * Initialize plugin.
219
  */
inc/templates/media.php CHANGED
@@ -41,7 +41,7 @@
41
 
42
  <script id="tmpl-rwmb-media-status" type="text/html">
43
  <# if ( data.maxFiles > 0 ) { #>
44
- {{{ data.items }}}/{{{ data.maxFiles }}}
45
  <# if ( 1 < data.maxFiles ) { #> {{{ i18nRwmbMedia.multiple }}} <# } else {#> {{{ i18nRwmbMedia.single }}} <# } #>
46
  <# } #>
47
  </script>
41
 
42
  <script id="tmpl-rwmb-media-status" type="text/html">
43
  <# if ( data.maxFiles > 0 ) { #>
44
+ {{{ data.length }}}/{{{ data.maxFiles }}}
45
  <# if ( 1 < data.maxFiles ) { #> {{{ i18nRwmbMedia.multiple }}} <# } else {#> {{{ i18nRwmbMedia.single }}} <# } #>
46
  <# } #>
47
  </script>
inc/validation.php CHANGED
@@ -38,8 +38,16 @@ class RWMB_Validation
38
  {
39
  wp_enqueue_script( 'jquery-validate', RWMB_JS_URL . 'jquery.validate.min.js', array( 'jquery' ), RWMB_VER, true );
40
  wp_enqueue_script( 'rwmb-validate', RWMB_JS_URL . 'validate.js', array( 'jquery-validate' ), RWMB_VER, true );
41
- wp_localize_script( 'rwmb-validate', 'rwmbValidate', array(
42
- 'summaryMessage' => __( 'Please correct the errors highlighted below and try again.', 'meta-box' ),
43
- ) );
 
 
 
 
 
 
 
 
44
  }
45
  }
38
  {
39
  wp_enqueue_script( 'jquery-validate', RWMB_JS_URL . 'jquery.validate.min.js', array( 'jquery' ), RWMB_VER, true );
40
  wp_enqueue_script( 'rwmb-validate', RWMB_JS_URL . 'validate.js', array( 'jquery-validate' ), RWMB_VER, true );
41
+ /**
42
+ * Prevent loading localized string twice.
43
+ * @link https://github.com/rilwis/meta-box/issues/850
44
+ */
45
+ $wp_scripts = wp_scripts();
46
+ if ( ! $wp_scripts->get_data( 'rwmb-validate', 'data' ) )
47
+ {
48
+ wp_localize_script( 'rwmb-validate', 'rwmbValidate', array(
49
+ 'summaryMessage' => __( 'Please correct the errors highlighted below and try again.', 'meta-box' ),
50
+ ) );
51
+ }
52
  }
53
  }
js/clone.js CHANGED
@@ -1,5 +1,4 @@
1
- /* global jQuery, rwmb_cloneable_editors */
2
-
3
  jQuery( function ( $ )
4
  {
5
  'use strict';
@@ -19,7 +18,7 @@ jQuery( function ( $ )
19
 
20
  // Name attribute
21
  var name = $field.attr( 'name' );
22
- if ( name )
23
  {
24
  $field.attr( 'name', cloneIndex.replace( index, name, '[', ']', false ) );
25
  }
@@ -109,10 +108,10 @@ jQuery( function ( $ )
109
  }
110
  else if ( $field.is( 'select' ) )
111
  {
112
- // Reset select to first
113
- $field.prop( 'selectedIndex', 0 )
114
  }
115
- else if ( 'hidden' !== $field.attr( 'type' ) )
116
  {
117
  // Reset value
118
  $field.val( '' );
@@ -121,6 +120,10 @@ jQuery( function ( $ )
121
 
122
  // Insert Clone
123
  $clone.insertAfter( $last );
 
 
 
 
124
  // Set fields index. Must run before trigger clone event.
125
  cloneIndex.set( $clone, nextIndex );
126
 
1
+ /* global jQuery */
 
2
  jQuery( function ( $ )
3
  {
4
  'use strict';
18
 
19
  // Name attribute
20
  var name = $field.attr( 'name' );
21
+ if ( name && !$field.closest( '.rwmb-group-clone' ).length )
22
  {
23
  $field.attr( 'name', cloneIndex.replace( index, name, '[', ']', false ) );
24
  }
108
  }
109
  else if ( $field.is( 'select' ) )
110
  {
111
+ // Reset select
112
+ $field.prop( 'selectedIndex', -1 )
113
  }
114
+ else if ( ! $field.hasClass( 'rwmb-hidden' ) )
115
  {
116
  // Reset value
117
  $field.val( '' );
120
 
121
  // Insert Clone
122
  $clone.insertAfter( $last );
123
+
124
+ // Trigger custom event for the clone instance. Required for Group extension to update sub fields.
125
+ $clone.trigger( 'clone_instance', nextIndex );
126
+
127
  // Set fields index. Must run before trigger clone event.
128
  cloneIndex.set( $clone, nextIndex );
129
 
js/date.js CHANGED
@@ -18,7 +18,7 @@ jQuery( function ( $ )
18
  if ( $timestamp.length )
19
  {
20
  var $picker = $inline.length ? $inline : $this;
21
- options.onSelect = function ()
22
  {
23
  $timestamp.val( getTimestamp( $picker.datepicker( 'getDate' ) ) );
24
  };
@@ -48,6 +48,8 @@ jQuery( function ( $ )
48
  */
49
  function getTimestamp( date )
50
  {
 
 
51
  var milliseconds = Date.UTC( date.getFullYear(), date.getMonth(), date.getDate(), date.getHours(), date.getMinutes(), date.getSeconds() );
52
  return Math.floor( milliseconds / 1000 );
53
  }
18
  if ( $timestamp.length )
19
  {
20
  var $picker = $inline.length ? $inline : $this;
21
+ options.onClose = function ()
22
  {
23
  $timestamp.val( getTimestamp( $picker.datepicker( 'getDate' ) ) );
24
  };
48
  */
49
  function getTimestamp( date )
50
  {
51
+ if(date===null)
52
+ return "";
53
  var milliseconds = Date.UTC( date.getFullYear(), date.getMonth(), date.getDate(), date.getHours(), date.getMinutes(), date.getSeconds() );
54
  return Math.floor( milliseconds / 1000 );
55
  }
js/datetime.js CHANGED
@@ -18,7 +18,7 @@ jQuery( function ( $ )
18
  if ( $timestamp.length )
19
  {
20
  var $picker = $inline.length ? $inline : $this;
21
- options.onSelect = function ()
22
  {
23
  $timestamp.val( getTimestamp( $picker.datetimepicker( 'getDate' ) ) );
24
  };
@@ -48,6 +48,8 @@ jQuery( function ( $ )
48
  */
49
  function getTimestamp( date )
50
  {
 
 
51
  var milliseconds = Date.UTC( date.getFullYear(), date.getMonth(), date.getDate(), date.getHours(), date.getMinutes(), date.getSeconds() );
52
  return Math.floor( milliseconds / 1000 );
53
  }
18
  if ( $timestamp.length )
19
  {
20
  var $picker = $inline.length ? $inline : $this;
21
+ options.onClose = function ()
22
  {
23
  $timestamp.val( getTimestamp( $picker.datetimepicker( 'getDate' ) ) );
24
  };
48
  */
49
  function getTimestamp( date )
50
  {
51
+ if(date===null)
52
+ return "";
53
  var milliseconds = Date.UTC( date.getFullYear(), date.getMonth(), date.getDate(), date.getHours(), date.getMinutes(), date.getSeconds() );
54
  return Math.floor( milliseconds / 1000 );
55
  }
js/file-upload.js CHANGED
@@ -11,7 +11,7 @@ jQuery( function ( $ )
11
  FileUploadField = views.FileUploadField = MediaField.extend( {
12
  createAddButton: function ()
13
  {
14
- this.addButton = new UploadButton( { collection: this.collection, props: this.props } );
15
  }
16
  } );
17
 
@@ -27,7 +27,7 @@ jQuery( function ( $ )
27
 
28
  initialize: function ( options )
29
  {
30
- this.props = options.props;
31
  this.el.id = _.uniqueId( 'rwmb-upload-area-');
32
  this.render();
33
 
@@ -35,24 +35,14 @@ jQuery( function ( $ )
35
  this.dropzone = this.el;
36
  this.browser = this.$('.rwmb-browse-button')[0];
37
 
38
- this.supports = {
39
- upload: wp.Uploader.browser.supported
40
- };
41
-
42
- this.supported = this.supports.upload;
43
-
44
- if ( this.supported ) {
45
  this.initUploader();
46
  }
47
 
48
- this.listenTo( this.collection, 'add remove reset', function ()
 
49
  {
50
- var maxFiles = this.props.get( 'maxFiles' );
51
-
52
- if ( maxFiles > 0 )
53
- {
54
- this.$el.toggle( this.collection.length < maxFiles );
55
- }
56
  } );
57
  },
58
 
@@ -126,7 +116,7 @@ jQuery( function ( $ )
126
  // so listeners to the upload queue can track and display upload progress.
127
  file.attachment = wp.media.model.Attachment.create( attributes );
128
  wp.Uploader.queue.add( file.attachment );
129
- self.collection.add( file.attachment );
130
  });
131
 
132
  up.refresh();
@@ -173,7 +163,7 @@ jQuery( function ( $ )
173
 
174
  getExtensions: function ()
175
  {
176
- var mimeTypes = this.props.get( 'mimeType' ).split(','),
177
  exts = [];
178
 
179
  _.each( mimeTypes, function( current, index )
11
  FileUploadField = views.FileUploadField = MediaField.extend( {
12
  createAddButton: function ()
13
  {
14
+ this.addButton = new UploadButton( { controller: this.controller } );
15
  }
16
  } );
17
 
27
 
28
  initialize: function ( options )
29
  {
30
+ this.controller = options.controller;
31
  this.el.id = _.uniqueId( 'rwmb-upload-area-');
32
  this.render();
33
 
35
  this.dropzone = this.el;
36
  this.browser = this.$('.rwmb-browse-button')[0];
37
 
38
+ if ( wp.Uploader.browser.supported ) {
 
 
 
 
 
 
39
  this.initUploader();
40
  }
41
 
42
+ // Auto hide if you reach the max number of media
43
+ this.listenTo( this.controller, 'change:full', function ()
44
  {
45
+ this.$el.toggle( ! this.controller.get( 'full' ) );
 
 
 
 
 
46
  } );
47
  },
48
 
116
  // so listeners to the upload queue can track and display upload progress.
117
  file.attachment = wp.media.model.Attachment.create( attributes );
118
  wp.Uploader.queue.add( file.attachment );
119
+ self.controller.addItems( [file.attachment] );
120
  });
121
 
122
  up.refresh();
163
 
164
  getExtensions: function ()
165
  {
166
+ var mimeTypes = this.controller.get( 'mimeType' ).split(','),
167
  exts = [];
168
 
169
  _.each( mimeTypes, function( current, index )
js/image-advanced.js CHANGED
@@ -8,20 +8,21 @@ jQuery( function ( $ )
8
  MediaField = views.MediaField,
9
  MediaItem = views.MediaItem,
10
  MediaList = views.MediaList,
11
- ImageField, ImageList, ImageItem;
12
 
13
  ImageField = views.ImageField = MediaField.extend( {
14
  createList: function ()
15
  {
16
- this.list = new MediaList( { collection: this.collection, props: this.props, itemView: ImageItem } );
 
 
 
 
 
 
17
  }
18
  } );
19
 
20
- ImageItem = views.ImageItem = MediaItem.extend( {
21
- className: 'rwmb-image-item',
22
- template : wp.template( 'rwmb-image-item' )
23
- } );
24
-
25
  /**
26
  * Initialize image fields
27
  * @return void
8
  MediaField = views.MediaField,
9
  MediaItem = views.MediaItem,
10
  MediaList = views.MediaList,
11
+ ImageField;
12
 
13
  ImageField = views.ImageField = MediaField.extend( {
14
  createList: function ()
15
  {
16
+ this.list = new MediaList( {
17
+ controller: this.controller,
18
+ itemView: MediaItem.extend( {
19
+ className: 'rwmb-image-item',
20
+ template : wp.template( 'rwmb-image-item' )
21
+ } )
22
+ } );
23
  }
24
  } );
25
 
 
 
 
 
 
26
  /**
27
  * Initialize image fields
28
  * @return void
js/image-upload.js CHANGED
@@ -12,7 +12,7 @@ jQuery( function ( $ )
12
  ImageUploadField = views.ImageUploadField = ImageField.extend( {
13
  createAddButton: function ()
14
  {
15
- this.addButton = new UploadButton( { collection: this.collection, props: this.props } );
16
  }
17
  } );
18
 
@@ -23,7 +23,6 @@ jQuery( function ( $ )
23
  function init()
24
  {
25
  new ImageUploadField( { input: this, el: $( this ).siblings( 'div.rwmb-media-view' ) } );
26
- console.log('win');
27
  }
28
  $( ':input.rwmb-image_upload, :input.rwmb-plupload_image' ).each( init );
29
  $( '.rwmb-input' )
12
  ImageUploadField = views.ImageUploadField = ImageField.extend( {
13
  createAddButton: function ()
14
  {
15
+ this.addButton = new UploadButton( { controller: this.controller } );
16
  }
17
  } );
18
 
23
  function init()
24
  {
25
  new ImageUploadField( { input: this, el: $( this ).siblings( 'div.rwmb-media-view' ) } );
 
26
  }
27
  $( ':input.rwmb-image_upload, :input.rwmb-plupload_image' ).each( init );
28
  $( '.rwmb-input' )
js/jquery.validate.min.js CHANGED
@@ -1,2 +1,4 @@
1
- /*! jQuery Validation Plugin - v1.11.1 - 3/22/2013\n* https://github.com/jzaefferer/jquery-validation
2
- * Copyright (c) 2013 Jörn Zaefferer; Licensed MIT */(function(t){t.extend(t.fn,{validate:function(e){if(!this.length)return e&&e.debug&&window.console&&console.warn("Nothing selected, can't validate, returning nothing."),void 0;var i=t.data(this[0],"validator");return i?i:(this.attr("novalidate","novalidate"),i=new t.validator(e,this[0]),t.data(this[0],"validator",i),i.settings.onsubmit&&(this.validateDelegate(":submit","click",function(e){i.settings.submitHandler&&(i.submitButton=e.target),t(e.target).hasClass("cancel")&&(i.cancelSubmit=!0),void 0!==t(e.target).attr("formnovalidate")&&(i.cancelSubmit=!0)}),this.submit(function(e){function s(){var s;return i.settings.submitHandler?(i.submitButton&&(s=t("<input type='hidden'/>").attr("name",i.submitButton.name).val(t(i.submitButton).val()).appendTo(i.currentForm)),i.settings.submitHandler.call(i,i.currentForm,e),i.submitButton&&s.remove(),!1):!0}return i.settings.debug&&e.preventDefault(),i.cancelSubmit?(i.cancelSubmit=!1,s()):i.form()?i.pendingRequest?(i.formSubmitted=!0,!1):s():(i.focusInvalid(),!1)})),i)},valid:function(){if(t(this[0]).is("form"))return this.validate().form();var e=!0,i=t(this[0].form).validate();return this.each(function(){e=e&&i.element(this)}),e},removeAttrs:function(e){var i={},s=this;return t.each(e.split(/\s/),function(t,e){i[e]=s.attr(e),s.removeAttr(e)}),i},rules:function(e,i){var s=this[0];if(e){var r=t.data(s.form,"validator").settings,n=r.rules,a=t.validator.staticRules(s);switch(e){case"add":t.extend(a,t.validator.normalizeRule(i)),delete a.messages,n[s.name]=a,i.messages&&(r.messages[s.name]=t.extend(r.messages[s.name],i.messages));break;case"remove":if(!i)return delete n[s.name],a;var u={};return t.each(i.split(/\s/),function(t,e){u[e]=a[e],delete a[e]}),u}}var o=t.validator.normalizeRules(t.extend({},t.validator.classRules(s),t.validator.attributeRules(s),t.validator.dataRules(s),t.validator.staticRules(s)),s);if(o.required){var l=o.required;delete o.required,o=t.extend({required:l},o)}return o}}),t.extend(t.expr[":"],{blank:function(e){return!t.trim(""+t(e).val())},filled:function(e){return!!t.trim(""+t(e).val())},unchecked:function(e){return!t(e).prop("checked")}}),t.validator=function(e,i){this.settings=t.extend(!0,{},t.validator.defaults,e),this.currentForm=i,this.init()},t.validator.format=function(e,i){return 1===arguments.length?function(){var i=t.makeArray(arguments);return i.unshift(e),t.validator.format.apply(this,i)}:(arguments.length>2&&i.constructor!==Array&&(i=t.makeArray(arguments).slice(1)),i.constructor!==Array&&(i=[i]),t.each(i,function(t,i){e=e.replace(RegExp("\\{"+t+"\\}","g"),function(){return i})}),e)},t.extend(t.validator,{defaults:{messages:{},groups:{},rules:{},errorClass:"error",validClass:"valid",errorElement:"label",focusInvalid:!0,errorContainer:t([]),errorLabelContainer:t([]),onsubmit:!0,ignore:":hidden",ignoreTitle:!1,onfocusin:function(t){this.lastActive=t,this.settings.focusCleanup&&!this.blockFocusCleanup&&(this.settings.unhighlight&&this.settings.unhighlight.call(this,t,this.settings.errorClass,this.settings.validClass),this.addWrapper(this.errorsFor(t)).hide())},onfocusout:function(t){this.checkable(t)||!(t.name in this.submitted)&&this.optional(t)||this.element(t)},onkeyup:function(t,e){(9!==e.which||""!==this.elementValue(t))&&(t.name in this.submitted||t===this.lastElement)&&this.element(t)},onclick:function(t){t.name in this.submitted?this.element(t):t.parentNode.name in this.submitted&&this.element(t.parentNode)},highlight:function(e,i,s){"radio"===e.type?this.findByName(e.name).addClass(i).removeClass(s):t(e).addClass(i).removeClass(s)},unhighlight:function(e,i,s){"radio"===e.type?this.findByName(e.name).removeClass(i).addClass(s):t(e).removeClass(i).addClass(s)}},setDefaults:function(e){t.extend(t.validator.defaults,e)},messages:{required:"This field is required.",remote:"Please fix this field.",email:"Please enter a valid email address.",url:"Please enter a valid URL.",date:"Please enter a valid date.",dateISO:"Please enter a valid date (ISO).",number:"Please enter a valid number.",digits:"Please enter only digits.",creditcard:"Please enter a valid credit card number.",equalTo:"Please enter the same value again.",maxlength:t.validator.format("Please enter no more than {0} characters."),minlength:t.validator.format("Please enter at least {0} characters."),rangelength:t.validator.format("Please enter a value between {0} and {1} characters long."),range:t.validator.format("Please enter a value between {0} and {1}."),max:t.validator.format("Please enter a value less than or equal to {0}."),min:t.validator.format("Please enter a value greater than or equal to {0}.")},autoCreateRanges:!1,prototype:{init:function(){function e(e){var i=t.data(this[0].form,"validator"),s="on"+e.type.replace(/^validate/,"");i.settings[s]&&i.settings[s].call(i,this[0],e)}this.labelContainer=t(this.settings.errorLabelContainer),this.errorContext=this.labelContainer.length&&this.labelContainer||t(this.currentForm),this.containers=t(this.settings.errorContainer).add(this.settings.errorLabelContainer),this.submitted={},this.valueCache={},this.pendingRequest=0,this.pending={},this.invalid={},this.reset();var i=this.groups={};t.each(this.settings.groups,function(e,s){"string"==typeof s&&(s=s.split(/\s/)),t.each(s,function(t,s){i[s]=e})});var s=this.settings.rules;t.each(s,function(e,i){s[e]=t.validator.normalizeRule(i)}),t(this.currentForm).validateDelegate(":text, [type='password'], [type='file'], select, textarea, [type='number'], [type='search'] ,[type='tel'], [type='url'], [type='email'], [type='datetime'], [type='date'], [type='month'], [type='week'], [type='time'], [type='datetime-local'], [type='range'], [type='color'] ","focusin focusout keyup",e).validateDelegate("[type='radio'], [type='checkbox'], select, option","click",e),this.settings.invalidHandler&&t(this.currentForm).bind("invalid-form.validate",this.settings.invalidHandler)},form:function(){return this.checkForm(),t.extend(this.submitted,this.errorMap),this.invalid=t.extend({},this.errorMap),this.valid()||t(this.currentForm).triggerHandler("invalid-form",[this]),this.showErrors(),this.valid()},checkForm:function(){this.prepareForm();for(var t=0,e=this.currentElements=this.elements();e[t];t++)this.check(e[t]);return this.valid()},element:function(e){e=this.validationTargetFor(this.clean(e)),this.lastElement=e,this.prepareElement(e),this.currentElements=t(e);var i=this.check(e)!==!1;return i?delete this.invalid[e.name]:this.invalid[e.name]=!0,this.numberOfInvalids()||(this.toHide=this.toHide.add(this.containers)),this.showErrors(),i},showErrors:function(e){if(e){t.extend(this.errorMap,e),this.errorList=[];for(var i in e)this.errorList.push({message:e[i],element:this.findByName(i)[0]});this.successList=t.grep(this.successList,function(t){return!(t.name in e)})}this.settings.showErrors?this.settings.showErrors.call(this,this.errorMap,this.errorList):this.defaultShowErrors()},resetForm:function(){t.fn.resetForm&&t(this.currentForm).resetForm(),this.submitted={},this.lastElement=null,this.prepareForm(),this.hideErrors(),this.elements().removeClass(this.settings.errorClass).removeData("previousValue")},numberOfInvalids:function(){return this.objectLength(this.invalid)},objectLength:function(t){var e=0;for(var i in t)e++;return e},hideErrors:function(){this.addWrapper(this.toHide).hide()},valid:function(){return 0===this.size()},size:function(){return this.errorList.length},focusInvalid:function(){if(this.settings.focusInvalid)try{t(this.findLastActive()||this.errorList.length&&this.errorList[0].element||[]).filter(":visible").focus().trigger("focusin")}catch(e){}},findLastActive:function(){var e=this.lastActive;return e&&1===t.grep(this.errorList,function(t){return t.element.name===e.name}).length&&e},elements:function(){var e=this,i={};return t(this.currentForm).find("input, select, textarea").not(":submit, :reset, :image, [disabled]").not(this.settings.ignore).filter(function(){return!this.name&&e.settings.debug&&window.console&&console.error("%o has no name assigned",this),this.name in i||!e.objectLength(t(this).rules())?!1:(i[this.name]=!0,!0)})},clean:function(e){return t(e)[0]},errors:function(){var e=this.settings.errorClass.replace(" ",".");return t(this.settings.errorElement+"."+e,this.errorContext)},reset:function(){this.successList=[],this.errorList=[],this.errorMap={},this.toShow=t([]),this.toHide=t([]),this.currentElements=t([])},prepareForm:function(){this.reset(),this.toHide=this.errors().add(this.containers)},prepareElement:function(t){this.reset(),this.toHide=this.errorsFor(t)},elementValue:function(e){var i=t(e).attr("type"),s=t(e).val();return"radio"===i||"checkbox"===i?t("input[name='"+t(e).attr("name")+"']:checked").val():"string"==typeof s?s.replace(/\r/g,""):s},check:function(e){e=this.validationTargetFor(this.clean(e));var i,s=t(e).rules(),r=!1,n=this.elementValue(e);for(var a in s){var u={method:a,parameters:s[a]};try{if(i=t.validator.methods[a].call(this,n,e,u.parameters),"dependency-mismatch"===i){r=!0;continue}if(r=!1,"pending"===i)return this.toHide=this.toHide.not(this.errorsFor(e)),void 0;if(!i)return this.formatAndAdd(e,u),!1}catch(o){throw this.settings.debug&&window.console&&console.log("Exception occurred when checking element "+e.id+", check the '"+u.method+"' method.",o),o}}return r?void 0:(this.objectLength(s)&&this.successList.push(e),!0)},customDataMessage:function(e,i){return t(e).data("msg-"+i.toLowerCase())||e.attributes&&t(e).attr("data-msg-"+i.toLowerCase())},customMessage:function(t,e){var i=this.settings.messages[t];return i&&(i.constructor===String?i:i[e])},findDefined:function(){for(var t=0;arguments.length>t;t++)if(void 0!==arguments[t])return arguments[t];return void 0},defaultMessage:function(e,i){return this.findDefined(this.customMessage(e.name,i),this.customDataMessage(e,i),!this.settings.ignoreTitle&&e.title||void 0,t.validator.messages[i],"<strong>Warning: No message defined for "+e.name+"</strong>")},formatAndAdd:function(e,i){var s=this.defaultMessage(e,i.method),r=/\$?\{(\d+)\}/g;"function"==typeof s?s=s.call(this,i.parameters,e):r.test(s)&&(s=t.validator.format(s.replace(r,"{$1}"),i.parameters)),this.errorList.push({message:s,element:e}),this.errorMap[e.name]=s,this.submitted[e.name]=s},addWrapper:function(t){return this.settings.wrapper&&(t=t.add(t.parent(this.settings.wrapper))),t},defaultShowErrors:function(){var t,e;for(t=0;this.errorList[t];t++){var i=this.errorList[t];this.settings.highlight&&this.settings.highlight.call(this,i.element,this.settings.errorClass,this.settings.validClass),this.showLabel(i.element,i.message)}if(this.errorList.length&&(this.toShow=this.toShow.add(this.containers)),this.settings.success)for(t=0;this.successList[t];t++)this.showLabel(this.successList[t]);if(this.settings.unhighlight)for(t=0,e=this.validElements();e[t];t++)this.settings.unhighlight.call(this,e[t],this.settings.errorClass,this.settings.validClass);this.toHide=this.toHide.not(this.toShow),this.hideErrors(),this.addWrapper(this.toShow).show()},validElements:function(){return this.currentElements.not(this.invalidElements())},invalidElements:function(){return t(this.errorList).map(function(){return this.element})},showLabel:function(e,i){var s=this.errorsFor(e);s.length?(s.removeClass(this.settings.validClass).addClass(this.settings.errorClass),s.html(i)):(s=t("<"+this.settings.errorElement+">").attr("for",this.idOrName(e)).addClass(this.settings.errorClass).html(i||""),this.settings.wrapper&&(s=s.hide().show().wrap("<"+this.settings.wrapper+"/>").parent()),this.labelContainer.append(s).length||(this.settings.errorPlacement?this.settings.errorPlacement(s,t(e)):s.insertAfter(e))),!i&&this.settings.success&&(s.text(""),"string"==typeof this.settings.success?s.addClass(this.settings.success):this.settings.success(s,e)),this.toShow=this.toShow.add(s)},errorsFor:function(e){var i=this.idOrName(e);return this.errors().filter(function(){return t(this).attr("for")===i})},idOrName:function(t){return this.groups[t.name]||(this.checkable(t)?t.name:t.id||t.name)},validationTargetFor:function(t){return this.checkable(t)&&(t=this.findByName(t.name).not(this.settings.ignore)[0]),t},checkable:function(t){return/radio|checkbox/i.test(t.type)},findByName:function(e){return t(this.currentForm).find("[name='"+e+"']")},getLength:function(e,i){switch(i.nodeName.toLowerCase()){case"select":return t("option:selected",i).length;case"input":if(this.checkable(i))return this.findByName(i.name).filter(":checked").length}return e.length},depend:function(t,e){return this.dependTypes[typeof t]?this.dependTypes[typeof t](t,e):!0},dependTypes:{"boolean":function(t){return t},string:function(e,i){return!!t(e,i.form).length},"function":function(t,e){return t(e)}},optional:function(e){var i=this.elementValue(e);return!t.validator.methods.required.call(this,i,e)&&"dependency-mismatch"},startRequest:function(t){this.pending[t.name]||(this.pendingRequest++,this.pending[t.name]=!0)},stopRequest:function(e,i){this.pendingRequest--,0>this.pendingRequest&&(this.pendingRequest=0),delete this.pending[e.name],i&&0===this.pendingRequest&&this.formSubmitted&&this.form()?(t(this.currentForm).submit(),this.formSubmitted=!1):!i&&0===this.pendingRequest&&this.formSubmitted&&(t(this.currentForm).triggerHandler("invalid-form",[this]),this.formSubmitted=!1)},previousValue:function(e){return t.data(e,"previousValue")||t.data(e,"previousValue",{old:null,valid:!0,message:this.defaultMessage(e,"remote")})}},classRuleSettings:{required:{required:!0},email:{email:!0},url:{url:!0},date:{date:!0},dateISO:{dateISO:!0},number:{number:!0},digits:{digits:!0},creditcard:{creditcard:!0}},addClassRules:function(e,i){e.constructor===String?this.classRuleSettings[e]=i:t.extend(this.classRuleSettings,e)},classRules:function(e){var i={},s=t(e).attr("class");return s&&t.each(s.split(" "),function(){this in t.validator.classRuleSettings&&t.extend(i,t.validator.classRuleSettings[this])}),i},attributeRules:function(e){var i={},s=t(e),r=s[0].getAttribute("type");for(var n in t.validator.methods){var a;"required"===n?(a=s.get(0).getAttribute(n),""===a&&(a=!0),a=!!a):a=s.attr(n),/min|max/.test(n)&&(null===r||/number|range|text/.test(r))&&(a=Number(a)),a?i[n]=a:r===n&&"range"!==r&&(i[n]=!0)}return i.maxlength&&/-1|2147483647|524288/.test(i.maxlength)&&delete i.maxlength,i},dataRules:function(e){var i,s,r={},n=t(e);for(i in t.validator.methods)s=n.data("rule-"+i.toLowerCase()),void 0!==s&&(r[i]=s);return r},staticRules:function(e){var i={},s=t.data(e.form,"validator");return s.settings.rules&&(i=t.validator.normalizeRule(s.settings.rules[e.name])||{}),i},normalizeRules:function(e,i){return t.each(e,function(s,r){if(r===!1)return delete e[s],void 0;if(r.param||r.depends){var n=!0;switch(typeof r.depends){case"string":n=!!t(r.depends,i.form).length;break;case"function":n=r.depends.call(i,i)}n?e[s]=void 0!==r.param?r.param:!0:delete e[s]}}),t.each(e,function(s,r){e[s]=t.isFunction(r)?r(i):r}),t.each(["minlength","maxlength"],function(){e[this]&&(e[this]=Number(e[this]))}),t.each(["rangelength","range"],function(){var i;e[this]&&(t.isArray(e[this])?e[this]=[Number(e[this][0]),Number(e[this][1])]:"string"==typeof e[this]&&(i=e[this].split(/[\s,]+/),e[this]=[Number(i[0]),Number(i[1])]))}),t.validator.autoCreateRanges&&(e.min&&e.max&&(e.range=[e.min,e.max],delete e.min,delete e.max),e.minlength&&e.maxlength&&(e.rangelength=[e.minlength,e.maxlength],delete e.minlength,delete e.maxlength)),e},normalizeRule:function(e){if("string"==typeof e){var i={};t.each(e.split(/\s/),function(){i[this]=!0}),e=i}return e},addMethod:function(e,i,s){t.validator.methods[e]=i,t.validator.messages[e]=void 0!==s?s:t.validator.messages[e],3>i.length&&t.validator.addClassRules(e,t.validator.normalizeRule(e))},methods:{required:function(e,i,s){if(!this.depend(s,i))return"dependency-mismatch";if("select"===i.nodeName.toLowerCase()){var r=t(i).val();return r&&r.length>0}return this.checkable(i)?this.getLength(e,i)>0:t.trim(e).length>0},email:function(t,e){return this.optional(e)||/^((([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+(\.([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+)*)|((\x22)((((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(([\x01-\x08\x0b\x0c\x0e-\x1f\x7f]|\x21|[\x23-\x5b]|[\x5d-\x7e]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(\\([\x01-\x09\x0b\x0c\x0d-\x7f]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]))))*(((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(\x22)))@((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))$/i.test(t)},url:function(t,e){return this.optional(e)||/^(https?|s?ftp):\/\/(((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:)*@)?(((\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5]))|((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.?)(:\d*)?)(\/((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)+(\/(([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)*)*)?)?(\?((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|[\uE000-\uF8FF]|\/|\?)*)?(#((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|\/|\?)*)?$/i.test(t)},date:function(t,e){return this.optional(e)||!/Invalid|NaN/.test(""+new Date(t))},dateISO:function(t,e){return this.optional(e)||/^\d{4}[\/\-]\d{1,2}[\/\-]\d{1,2}$/.test(t)},number:function(t,e){return this.optional(e)||/^-?(?:\d+|\d{1,3}(?:,\d{3})+)?(?:\.\d+)?$/.test(t)},digits:function(t,e){return this.optional(e)||/^\d+$/.test(t)},creditcard:function(t,e){if(this.optional(e))return"dependency-mismatch";if(/[^0-9 \-]+/.test(t))return!1;var i=0,s=0,r=!1;t=t.replace(/\D/g,"");for(var n=t.length-1;n>=0;n--){var a=t.charAt(n);s=parseInt(a,10),r&&(s*=2)>9&&(s-=9),i+=s,r=!r}return 0===i%10},minlength:function(e,i,s){var r=t.isArray(e)?e.length:this.getLength(t.trim(e),i);return this.optional(i)||r>=s},maxlength:function(e,i,s){var r=t.isArray(e)?e.length:this.getLength(t.trim(e),i);return this.optional(i)||s>=r},rangelength:function(e,i,s){var r=t.isArray(e)?e.length:this.getLength(t.trim(e),i);return this.optional(i)||r>=s[0]&&s[1]>=r},min:function(t,e,i){return this.optional(e)||t>=i},max:function(t,e,i){return this.optional(e)||i>=t},range:function(t,e,i){return this.optional(e)||t>=i[0]&&i[1]>=t},equalTo:function(e,i,s){var r=t(s);return this.settings.onfocusout&&r.unbind(".validate-equalTo").bind("blur.validate-equalTo",function(){t(i).valid()}),e===r.val()},remote:function(e,i,s){if(this.optional(i))return"dependency-mismatch";var r=this.previousValue(i);if(this.settings.messages[i.name]||(this.settings.messages[i.name]={}),r.originalMessage=this.settings.messages[i.name].remote,this.settings.messages[i.name].remote=r.message,s="string"==typeof s&&{url:s}||s,r.old===e)return r.valid;r.old=e;var n=this;this.startRequest(i);var a={};return a[i.name]=e,t.ajax(t.extend(!0,{url:s,mode:"abort",port:"validate"+i.name,dataType:"json",data:a,success:function(s){n.settings.messages[i.name].remote=r.originalMessage;var a=s===!0||"true"===s;if(a){var u=n.formSubmitted;n.prepareElement(i),n.formSubmitted=u,n.successList.push(i),delete n.invalid[i.name],n.showErrors()}else{var o={},l=s||n.defaultMessage(i,"remote");o[i.name]=r.message=t.isFunction(l)?l(e):l,n.invalid[i.name]=!0,n.showErrors(o)}r.valid=a,n.stopRequest(i,a)}},s)),"pending"}}}),t.format=t.validator.format})(jQuery),function(t){var e={};if(t.ajaxPrefilter)t.ajaxPrefilter(function(t,i,s){var r=t.port;"abort"===t.mode&&(e[r]&&e[r].abort(),e[r]=s)});else{var i=t.ajax;t.ajax=function(s){var r=("mode"in s?s:t.ajaxSettings).mode,n=("port"in s?s:t.ajaxSettings).port;return"abort"===r?(e[n]&&e[n].abort(),e[n]=i.apply(this,arguments),e[n]):i.apply(this,arguments)}}}(jQuery),function(t){t.extend(t.fn,{validateDelegate:function(e,i,s){return this.bind(i,function(i){var r=t(i.target);return r.is(e)?s.apply(r,arguments):void 0})}})}(jQuery);
 
 
1
+ /*! jQuery Validation Plugin - v1.15.0 - 2/24/2016
2
+ * http://jqueryvalidation.org/
3
+ * Copyright (c) 2016 Jörn Zaefferer; Licensed MIT */
4
+ !function(a){"function"==typeof define&&define.amd?define(["jquery"],a):"object"==typeof module&&module.exports?module.exports=a(require("jquery")):a(jQuery)}(function(a){a.extend(a.fn,{validate:function(b){if(!this.length)return void(b&&b.debug&&window.console&&console.warn("Nothing selected, can't validate, returning nothing."));var c=a.data(this[0],"validator");return c?c:(this.attr("novalidate","novalidate"),c=new a.validator(b,this[0]),a.data(this[0],"validator",c),c.settings.onsubmit&&(this.on("click.validate",":submit",function(b){c.settings.submitHandler&&(c.submitButton=b.target),a(this).hasClass("cancel")&&(c.cancelSubmit=!0),void 0!==a(this).attr("formnovalidate")&&(c.cancelSubmit=!0)}),this.on("submit.validate",function(b){function d(){var d,e;return c.settings.submitHandler?(c.submitButton&&(d=a("<input type='hidden'/>").attr("name",c.submitButton.name).val(a(c.submitButton).val()).appendTo(c.currentForm)),e=c.settings.submitHandler.call(c,c.currentForm,b),c.submitButton&&d.remove(),void 0!==e?e:!1):!0}return c.settings.debug&&b.preventDefault(),c.cancelSubmit?(c.cancelSubmit=!1,d()):c.form()?c.pendingRequest?(c.formSubmitted=!0,!1):d():(c.focusInvalid(),!1)})),c)},valid:function(){var b,c,d;return a(this[0]).is("form")?b=this.validate().form():(d=[],b=!0,c=a(this[0].form).validate(),this.each(function(){b=c.element(this)&&b,b||(d=d.concat(c.errorList))}),c.errorList=d),b},rules:function(b,c){if(this.length){var d,e,f,g,h,i,j=this[0];if(b)switch(d=a.data(j.form,"validator").settings,e=d.rules,f=a.validator.staticRules(j),b){case"add":a.extend(f,a.validator.normalizeRule(c)),delete f.messages,e[j.name]=f,c.messages&&(d.messages[j.name]=a.extend(d.messages[j.name],c.messages));break;case"remove":return c?(i={},a.each(c.split(/\s/),function(b,c){i[c]=f[c],delete f[c],"required"===c&&a(j).removeAttr("aria-required")}),i):(delete e[j.name],f)}return g=a.validator.normalizeRules(a.extend({},a.validator.classRules(j),a.validator.attributeRules(j),a.validator.dataRules(j),a.validator.staticRules(j)),j),g.required&&(h=g.required,delete g.required,g=a.extend({required:h},g),a(j).attr("aria-required","true")),g.remote&&(h=g.remote,delete g.remote,g=a.extend(g,{remote:h})),g}}}),a.extend(a.expr[":"],{blank:function(b){return!a.trim(""+a(b).val())},filled:function(b){var c=a(b).val();return null!==c&&!!a.trim(""+c)},unchecked:function(b){return!a(b).prop("checked")}}),a.validator=function(b,c){this.settings=a.extend(!0,{},a.validator.defaults,b),this.currentForm=c,this.init()},a.validator.format=function(b,c){return 1===arguments.length?function(){var c=a.makeArray(arguments);return c.unshift(b),a.validator.format.apply(this,c)}:void 0===c?b:(arguments.length>2&&c.constructor!==Array&&(c=a.makeArray(arguments).slice(1)),c.constructor!==Array&&(c=[c]),a.each(c,function(a,c){b=b.replace(new RegExp("\\{"+a+"\\}","g"),function(){return c})}),b)},a.extend(a.validator,{defaults:{messages:{},groups:{},rules:{},errorClass:"error",pendingClass:"pending",validClass:"valid",errorElement:"label",focusCleanup:!1,focusInvalid:!0,errorContainer:a([]),errorLabelContainer:a([]),onsubmit:!0,ignore:":hidden",ignoreTitle:!1,onfocusin:function(a){this.lastActive=a,this.settings.focusCleanup&&(this.settings.unhighlight&&this.settings.unhighlight.call(this,a,this.settings.errorClass,this.settings.validClass),this.hideThese(this.errorsFor(a)))},onfocusout:function(a){this.checkable(a)||!(a.name in this.submitted)&&this.optional(a)||this.element(a)},onkeyup:function(b,c){var d=[16,17,18,20,35,36,37,38,39,40,45,144,225];9===c.which&&""===this.elementValue(b)||-1!==a.inArray(c.keyCode,d)||(b.name in this.submitted||b.name in this.invalid)&&this.element(b)},onclick:function(a){a.name in this.submitted?this.element(a):a.parentNode.name in this.submitted&&this.element(a.parentNode)},highlight:function(b,c,d){"radio"===b.type?this.findByName(b.name).addClass(c).removeClass(d):a(b).addClass(c).removeClass(d)},unhighlight:function(b,c,d){"radio"===b.type?this.findByName(b.name).removeClass(c).addClass(d):a(b).removeClass(c).addClass(d)}},setDefaults:function(b){a.extend(a.validator.defaults,b)},messages:{required:"This field is required.",remote:"Please fix this field.",email:"Please enter a valid email address.",url:"Please enter a valid URL.",date:"Please enter a valid date.",dateISO:"Please enter a valid date ( ISO ).",number:"Please enter a valid number.",digits:"Please enter only digits.",equalTo:"Please enter the same value again.",maxlength:a.validator.format("Please enter no more than {0} characters."),minlength:a.validator.format("Please enter at least {0} characters."),rangelength:a.validator.format("Please enter a value between {0} and {1} characters long."),range:a.validator.format("Please enter a value between {0} and {1}."),max:a.validator.format("Please enter a value less than or equal to {0}."),min:a.validator.format("Please enter a value greater than or equal to {0}."),step:a.validator.format("Please enter a multiple of {0}.")},autoCreateRanges:!1,prototype:{init:function(){function b(b){var c=a.data(this.form,"validator"),d="on"+b.type.replace(/^validate/,""),e=c.settings;e[d]&&!a(this).is(e.ignore)&&e[d].call(c,this,b)}this.labelContainer=a(this.settings.errorLabelContainer),this.errorContext=this.labelContainer.length&&this.labelContainer||a(this.currentForm),this.containers=a(this.settings.errorContainer).add(this.settings.errorLabelContainer),this.submitted={},this.valueCache={},this.pendingRequest=0,this.pending={},this.invalid={},this.reset();var c,d=this.groups={};a.each(this.settings.groups,function(b,c){"string"==typeof c&&(c=c.split(/\s/)),a.each(c,function(a,c){d[c]=b})}),c=this.settings.rules,a.each(c,function(b,d){c[b]=a.validator.normalizeRule(d)}),a(this.currentForm).on("focusin.validate focusout.validate keyup.validate",":text, [type='password'], [type='file'], select, textarea, [type='number'], [type='search'], [type='tel'], [type='url'], [type='email'], [type='datetime'], [type='date'], [type='month'], [type='week'], [type='time'], [type='datetime-local'], [type='range'], [type='color'], [type='radio'], [type='checkbox'], [contenteditable]",b).on("click.validate","select, option, [type='radio'], [type='checkbox']",b),this.settings.invalidHandler&&a(this.currentForm).on("invalid-form.validate",this.settings.invalidHandler),a(this.currentForm).find("[required], [data-rule-required], .required").attr("aria-required","true")},form:function(){return this.checkForm(),a.extend(this.submitted,this.errorMap),this.invalid=a.extend({},this.errorMap),this.valid()||a(this.currentForm).triggerHandler("invalid-form",[this]),this.showErrors(),this.valid()},checkForm:function(){this.prepareForm();for(var a=0,b=this.currentElements=this.elements();b[a];a++)this.check(b[a]);return this.valid()},element:function(b){var c,d,e=this.clean(b),f=this.validationTargetFor(e),g=this,h=!0;return void 0===f?delete this.invalid[e.name]:(this.prepareElement(f),this.currentElements=a(f),d=this.groups[f.name],d&&a.each(this.groups,function(a,b){b===d&&a!==f.name&&(e=g.validationTargetFor(g.clean(g.findByName(a))),e&&e.name in g.invalid&&(g.currentElements.push(e),h=h&&g.check(e)))}),c=this.check(f)!==!1,h=h&&c,c?this.invalid[f.name]=!1:this.invalid[f.name]=!0,this.numberOfInvalids()||(this.toHide=this.toHide.add(this.containers)),this.showErrors(),a(b).attr("aria-invalid",!c)),h},showErrors:function(b){if(b){var c=this;a.extend(this.errorMap,b),this.errorList=a.map(this.errorMap,function(a,b){return{message:a,element:c.findByName(b)[0]}}),this.successList=a.grep(this.successList,function(a){return!(a.name in b)})}this.settings.showErrors?this.settings.showErrors.call(this,this.errorMap,this.errorList):this.defaultShowErrors()},resetForm:function(){a.fn.resetForm&&a(this.currentForm).resetForm(),this.invalid={},this.submitted={},this.prepareForm(),this.hideErrors();var b=this.elements().removeData("previousValue").removeAttr("aria-invalid");this.resetElements(b)},resetElements:function(a){var b;if(this.settings.unhighlight)for(b=0;a[b];b++)this.settings.unhighlight.call(this,a[b],this.settings.errorClass,""),this.findByName(a[b].name).removeClass(this.settings.validClass);else a.removeClass(this.settings.errorClass).removeClass(this.settings.validClass)},numberOfInvalids:function(){return this.objectLength(this.invalid)},objectLength:function(a){var b,c=0;for(b in a)a[b]&&c++;return c},hideErrors:function(){this.hideThese(this.toHide)},hideThese:function(a){a.not(this.containers).text(""),this.addWrapper(a).hide()},valid:function(){return 0===this.size()},size:function(){return this.errorList.length},focusInvalid:function(){if(this.settings.focusInvalid)try{a(this.findLastActive()||this.errorList.length&&this.errorList[0].element||[]).filter(":visible").focus().trigger("focusin")}catch(b){}},findLastActive:function(){var b=this.lastActive;return b&&1===a.grep(this.errorList,function(a){return a.element.name===b.name}).length&&b},elements:function(){var b=this,c={};return a(this.currentForm).find("input, select, textarea, [contenteditable]").not(":submit, :reset, :image, :disabled").not(this.settings.ignore).filter(function(){var d=this.name||a(this).attr("name");return!d&&b.settings.debug&&window.console&&console.error("%o has no name assigned",this),this.hasAttribute("contenteditable")&&(this.form=a(this).closest("form")[0]),d in c||!b.objectLength(a(this).rules())?!1:(c[d]=!0,!0)})},clean:function(b){return a(b)[0]},errors:function(){var b=this.settings.errorClass.split(" ").join(".");return a(this.settings.errorElement+"."+b,this.errorContext)},resetInternals:function(){this.successList=[],this.errorList=[],this.errorMap={},this.toShow=a([]),this.toHide=a([])},reset:function(){this.resetInternals(),this.currentElements=a([])},prepareForm:function(){this.reset(),this.toHide=this.errors().add(this.containers)},prepareElement:function(a){this.reset(),this.toHide=this.errorsFor(a)},elementValue:function(b){var c,d,e=a(b),f=b.type;return"radio"===f||"checkbox"===f?this.findByName(b.name).filter(":checked").val():"number"===f&&"undefined"!=typeof b.validity?b.validity.badInput?"NaN":e.val():(c=b.hasAttribute("contenteditable")?e.text():e.val(),"file"===f?"C:\\fakepath\\"===c.substr(0,12)?c.substr(12):(d=c.lastIndexOf("/"),d>=0?c.substr(d+1):(d=c.lastIndexOf("\\"),d>=0?c.substr(d+1):c)):"string"==typeof c?c.replace(/\r/g,""):c)},check:function(b){b=this.validationTargetFor(this.clean(b));var c,d,e,f=a(b).rules(),g=a.map(f,function(a,b){return b}).length,h=!1,i=this.elementValue(b);if("function"==typeof f.normalizer){if(i=f.normalizer.call(b,i),"string"!=typeof i)throw new TypeError("The normalizer should return a string value.");delete f.normalizer}for(d in f){e={method:d,parameters:f[d]};try{if(c=a.validator.methods[d].call(this,i,b,e.parameters),"dependency-mismatch"===c&&1===g){h=!0;continue}if(h=!1,"pending"===c)return void(this.toHide=this.toHide.not(this.errorsFor(b)));if(!c)return this.formatAndAdd(b,e),!1}catch(j){throw this.settings.debug&&window.console&&console.log("Exception occurred when checking element "+b.id+", check the '"+e.method+"' method.",j),j instanceof TypeError&&(j.message+=". Exception occurred when checking element "+b.id+", check the '"+e.method+"' method."),j}}if(!h)return this.objectLength(f)&&this.successList.push(b),!0},customDataMessage:function(b,c){return a(b).data("msg"+c.charAt(0).toUpperCase()+c.substring(1).toLowerCase())||a(b).data("msg")},customMessage:function(a,b){var c=this.settings.messages[a];return c&&(c.constructor===String?c:c[b])},findDefined:function(){for(var a=0;a<arguments.length;a++)if(void 0!==arguments[a])return arguments[a]},defaultMessage:function(b,c){var d=this.findDefined(this.customMessage(b.name,c.method),this.customDataMessage(b,c.method),!this.settings.ignoreTitle&&b.title||void 0,a.validator.messages[c.method],"<strong>Warning: No message defined for "+b.name+"</strong>"),e=/\$?\{(\d+)\}/g;return"function"==typeof d?d=d.call(this,c.parameters,b):e.test(d)&&(d=a.validator.format(d.replace(e,"{$1}"),c.parameters)),d},formatAndAdd:function(a,b){var c=this.defaultMessage(a,b);this.errorList.push({message:c,element:a,method:b.method}),this.errorMap[a.name]=c,this.submitted[a.name]=c},addWrapper:function(a){return this.settings.wrapper&&(a=a.add(a.parent(this.settings.wrapper))),a},defaultShowErrors:function(){var a,b,c;for(a=0;this.errorList[a];a++)c=this.errorList[a],this.settings.highlight&&this.settings.highlight.call(this,c.element,this.settings.errorClass,this.settings.validClass),this.showLabel(c.element,c.message);if(this.errorList.length&&(this.toShow=this.toShow.add(this.containers)),this.settings.success)for(a=0;this.successList[a];a++)this.showLabel(this.successList[a]);if(this.settings.unhighlight)for(a=0,b=this.validElements();b[a];a++)this.settings.unhighlight.call(this,b[a],this.settings.errorClass,this.settings.validClass);this.toHide=this.toHide.not(this.toShow),this.hideErrors(),this.addWrapper(this.toShow).show()},validElements:function(){return this.currentElements.not(this.invalidElements())},invalidElements:function(){return a(this.errorList).map(function(){return this.element})},showLabel:function(b,c){var d,e,f,g,h=this.errorsFor(b),i=this.idOrName(b),j=a(b).attr("aria-describedby");h.length?(h.removeClass(this.settings.validClass).addClass(this.settings.errorClass),h.html(c)):(h=a("<"+this.settings.errorElement+">").attr("id",i+"-error").addClass(this.settings.errorClass).html(c||""),d=h,this.settings.wrapper&&(d=h.hide().show().wrap("<"+this.settings.wrapper+"/>").parent()),this.labelContainer.length?this.labelContainer.append(d):this.settings.errorPlacement?this.settings.errorPlacement(d,a(b)):d.insertAfter(b),h.is("label")?h.attr("for",i):0===h.parents("label[for='"+this.escapeCssMeta(i)+"']").length&&(f=h.attr("id"),j?j.match(new RegExp("\\b"+this.escapeCssMeta(f)+"\\b"))||(j+=" "+f):j=f,a(b).attr("aria-describedby",j),e=this.groups[b.name],e&&(g=this,a.each(g.groups,function(b,c){c===e&&a("[name='"+g.escapeCssMeta(b)+"']",g.currentForm).attr("aria-describedby",h.attr("id"))})))),!c&&this.settings.success&&(h.text(""),"string"==typeof this.settings.success?h.addClass(this.settings.success):this.settings.success(h,b)),this.toShow=this.toShow.add(h)},errorsFor:function(b){var c=this.escapeCssMeta(this.idOrName(b)),d=a(b).attr("aria-describedby"),e="label[for='"+c+"'], label[for='"+c+"'] *";return d&&(e=e+", #"+this.escapeCssMeta(d).replace(/\s+/g,", #")),this.errors().filter(e)},escapeCssMeta:function(a){return a.replace(/([\\!"#$%&'()*+,./:;<=>?@\[\]^`{|}~])/g,"\\$1")},idOrName:function(a){return this.groups[a.name]||(this.checkable(a)?a.name:a.id||a.name)},validationTargetFor:function(b){return this.checkable(b)&&(b=this.findByName(b.name)),a(b).not(this.settings.ignore)[0]},checkable:function(a){return/radio|checkbox/i.test(a.type)},findByName:function(b){return a(this.currentForm).find("[name='"+this.escapeCssMeta(b)+"']")},getLength:function(b,c){switch(c.nodeName.toLowerCase()){case"select":return a("option:selected",c).length;case"input":if(this.checkable(c))return this.findByName(c.name).filter(":checked").length}return b.length},depend:function(a,b){return this.dependTypes[typeof a]?this.dependTypes[typeof a](a,b):!0},dependTypes:{"boolean":function(a){return a},string:function(b,c){return!!a(b,c.form).length},"function":function(a,b){return a(b)}},optional:function(b){var c=this.elementValue(b);return!a.validator.methods.required.call(this,c,b)&&"dependency-mismatch"},startRequest:function(b){this.pending[b.name]||(this.pendingRequest++,a(b).addClass(this.settings.pendingClass),this.pending[b.name]=!0)},stopRequest:function(b,c){this.pendingRequest--,this.pendingRequest<0&&(this.pendingRequest=0),delete this.pending[b.name],a(b).removeClass(this.settings.pendingClass),c&&0===this.pendingRequest&&this.formSubmitted&&this.form()?(a(this.currentForm).submit(),this.formSubmitted=!1):!c&&0===this.pendingRequest&&this.formSubmitted&&(a(this.currentForm).triggerHandler("invalid-form",[this]),this.formSubmitted=!1)},previousValue:function(b,c){return a.data(b,"previousValue")||a.data(b,"previousValue",{old:null,valid:!0,message:this.defaultMessage(b,{method:c})})},destroy:function(){this.resetForm(),a(this.currentForm).off(".validate").removeData("validator").find(".validate-equalTo-blur").off(".validate-equalTo").removeClass("validate-equalTo-blur")}},classRuleSettings:{required:{required:!0},email:{email:!0},url:{url:!0},date:{date:!0},dateISO:{dateISO:!0},number:{number:!0},digits:{digits:!0},creditcard:{creditcard:!0}},addClassRules:function(b,c){b.constructor===String?this.classRuleSettings[b]=c:a.extend(this.classRuleSettings,b)},classRules:function(b){var c={},d=a(b).attr("class");return d&&a.each(d.split(" "),function(){this in a.validator.classRuleSettings&&a.extend(c,a.validator.classRuleSettings[this])}),c},normalizeAttributeRule:function(a,b,c,d){/min|max|step/.test(c)&&(null===b||/number|range|text/.test(b))&&(d=Number(d),isNaN(d)&&(d=void 0)),d||0===d?a[c]=d:b===c&&"range"!==b&&(a[c]=!0)},attributeRules:function(b){var c,d,e={},f=a(b),g=b.getAttribute("type");for(c in a.validator.methods)"required"===c?(d=b.getAttribute(c),""===d&&(d=!0),d=!!d):d=f.attr(c),this.normalizeAttributeRule(e,g,c,d);return e.maxlength&&/-1|2147483647|524288/.test(e.maxlength)&&delete e.maxlength,e},dataRules:function(b){var c,d,e={},f=a(b),g=b.getAttribute("type");for(c in a.validator.methods)d=f.data("rule"+c.charAt(0).toUpperCase()+c.substring(1).toLowerCase()),this.normalizeAttributeRule(e,g,c,d);return e},staticRules:function(b){var c={},d=a.data(b.form,"validator");return d.settings.rules&&(c=a.validator.normalizeRule(d.settings.rules[b.name])||{}),c},normalizeRules:function(b,c){return a.each(b,function(d,e){if(e===!1)return void delete b[d];if(e.param||e.depends){var f=!0;switch(typeof e.depends){case"string":f=!!a(e.depends,c.form).length;break;case"function":f=e.depends.call(c,c)}f?b[d]=void 0!==e.param?e.param:!0:(a.data(c.form,"validator").resetElements(a(c)),delete b[d])}}),a.each(b,function(d,e){b[d]=a.isFunction(e)&&"normalizer"!==d?e(c):e}),a.each(["minlength","maxlength"],function(){b[this]&&(b[this]=Number(b[this]))}),a.each(["rangelength","range"],function(){var c;b[this]&&(a.isArray(b[this])?b[this]=[Number(b[this][0]),Number(b[this][1])]:"string"==typeof b[this]&&(c=b[this].replace(/[\[\]]/g,"").split(/[\s,]+/),b[this]=[Number(c[0]),Number(c[1])]))}),a.validator.autoCreateRanges&&(null!=b.min&&null!=b.max&&(b.range=[b.min,b.max],delete b.min,delete b.max),null!=b.minlength&&null!=b.maxlength&&(b.rangelength=[b.minlength,b.maxlength],delete b.minlength,delete b.maxlength)),b},normalizeRule:function(b){if("string"==typeof b){var c={};a.each(b.split(/\s/),function(){c[this]=!0}),b=c}return b},addMethod:function(b,c,d){a.validator.methods[b]=c,a.validator.messages[b]=void 0!==d?d:a.validator.messages[b],c.length<3&&a.validator.addClassRules(b,a.validator.normalizeRule(b))},methods:{required:function(b,c,d){if(!this.depend(d,c))return"dependency-mismatch";if("select"===c.nodeName.toLowerCase()){var e=a(c).val();return e&&e.length>0}return this.checkable(c)?this.getLength(b,c)>0:b.length>0},email:function(a,b){return this.optional(b)||/^[a-zA-Z0-9.!#$%&'*+\/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$/.test(a)},url:function(a,b){return this.optional(b)||/^(?:(?:(?:https?|ftp):)?\/\/)(?:\S+(?::\S*)?@)?(?:(?!(?:10|127)(?:\.\d{1,3}){3})(?!(?:169\.254|192\.168)(?:\.\d{1,3}){2})(?!172\.(?:1[6-9]|2\d|3[0-1])(?:\.\d{1,3}){2})(?:[1-9]\d?|1\d\d|2[01]\d|22[0-3])(?:\.(?:1?\d{1,2}|2[0-4]\d|25[0-5])){2}(?:\.(?:[1-9]\d?|1\d\d|2[0-4]\d|25[0-4]))|(?:(?:[a-z\u00a1-\uffff0-9]-*)*[a-z\u00a1-\uffff0-9]+)(?:\.(?:[a-z\u00a1-\uffff0-9]-*)*[a-z\u00a1-\uffff0-9]+)*(?:\.(?:[a-z\u00a1-\uffff]{2,})).?)(?::\d{2,5})?(?:[/?#]\S*)?$/i.test(a)},date:function(a,b){return this.optional(b)||!/Invalid|NaN/.test(new Date(a).toString())},dateISO:function(a,b){return this.optional(b)||/^\d{4}[\/\-](0?[1-9]|1[012])[\/\-](0?[1-9]|[12][0-9]|3[01])$/.test(a)},number:function(a,b){return this.optional(b)||/^(?:-?\d+|-?\d{1,3}(?:,\d{3})+)?(?:\.\d+)?$/.test(a)},digits:function(a,b){return this.optional(b)||/^\d+$/.test(a)},minlength:function(b,c,d){var e=a.isArray(b)?b.length:this.getLength(b,c);return this.optional(c)||e>=d},maxlength:function(b,c,d){var e=a.isArray(b)?b.length:this.getLength(b,c);return this.optional(c)||d>=e},rangelength:function(b,c,d){var e=a.isArray(b)?b.length:this.getLength(b,c);return this.optional(c)||e>=d[0]&&e<=d[1]},min:function(a,b,c){return this.optional(b)||a>=c},max:function(a,b,c){return this.optional(b)||c>=a},range:function(a,b,c){return this.optional(b)||a>=c[0]&&a<=c[1]},step:function(b,c,d){var e=a(c).attr("type"),f="Step attribute on input type "+e+" is not supported.",g=["text","number","range"],h=new RegExp("\\b"+e+"\\b"),i=e&&!h.test(g.join());if(i)throw new Error(f);return this.optional(c)||b%d===0},equalTo:function(b,c,d){var e=a(d);return this.settings.onfocusout&&e.not(".validate-equalTo-blur").length&&e.addClass("validate-equalTo-blur").on("blur.validate-equalTo",function(){a(c).valid()}),b===e.val()},remote:function(b,c,d,e){if(this.optional(c))return"dependency-mismatch";e="string"==typeof e&&e||"remote";var f,g,h,i=this.previousValue(c,e);return this.settings.messages[c.name]||(this.settings.messages[c.name]={}),i.originalMessage=i.originalMessage||this.settings.messages[c.name][e],this.settings.messages[c.name][e]=i.message,d="string"==typeof d&&{url:d}||d,h=a.param(a.extend({data:b},d.data)),i.old===h?i.valid:(i.old=h,f=this,this.startRequest(c),g={},g[c.name]=b,a.ajax(a.extend(!0,{mode:"abort",port:"validate"+c.name,dataType:"json",data:g,context:f.currentForm,success:function(a){var d,g,h,j=a===!0||"true"===a;f.settings.messages[c.name][e]=i.originalMessage,j?(h=f.formSubmitted,f.resetInternals(),f.toHide=f.errorsFor(c),f.formSubmitted=h,f.successList.push(c),f.invalid[c.name]=!1,f.showErrors()):(d={},g=a||f.defaultMessage(c,{method:e,parameters:b}),d[c.name]=i.message=g,f.invalid[c.name]=!0,f.showErrors(d)),i.valid=j,f.stopRequest(c,j)}},d)),"pending")}}});var b,c={};a.ajaxPrefilter?a.ajaxPrefilter(function(a,b,d){var e=a.port;"abort"===a.mode&&(c[e]&&c[e].abort(),c[e]=d)}):(b=a.ajax,a.ajax=function(d){var e=("mode"in d?d:a.ajaxSettings).mode,f=("port"in d?d:a.ajaxSettings).port;return"abort"===e?(c[f]&&c[f].abort(),c[f]=b.apply(this,arguments),c[f]):b.apply(this,arguments)})});
js/map-frontend.js CHANGED
@@ -34,6 +34,9 @@ jQuery( function ( $ )
34
  break;
35
  }
36
  mapOptions.center = center;
 
 
 
37
  map = new google.maps.Map( this, mapOptions );
38
 
39
  // Set marker
34
  break;
35
  }
36
  mapOptions.center = center;
37
+
38
+ // Typcast zoom to a number
39
+ mapOptions.zoom *= 1;
40
  map = new google.maps.Map( this, mapOptions );
41
 
42
  // Set marker
js/map.js CHANGED
@@ -11,7 +11,7 @@
11
  // Use prototype for better performance
12
  MapField.prototype = {
13
  // Initialize everything
14
- init : function ()
15
  {
16
  this.initDomElements();
17
  this.initMapElements();
@@ -22,7 +22,7 @@
22
  },
23
 
24
  // Initialize DOM elements
25
- initDomElements : function ()
26
  {
27
  this.canvas = this.$container.find( '.rwmb-map-canvas' )[0];
28
  this.$coordinate = this.$container.find( '.rwmb-map-coordinate' );
@@ -31,7 +31,7 @@
31
  },
32
 
33
  // Initialize map elements
34
- initMapElements : function ()
35
  {
36
  var defaultLoc = $( this.canvas ).data( 'default-loc' ),
37
  latLng;
@@ -73,7 +73,7 @@
73
  },
74
 
75
  // Add event listeners for 'click' & 'drag'
76
- addListeners : function ()
77
  {
78
  var that = this;
79
  google.maps.event.addListener( this.map, 'click', function ( event )
@@ -81,6 +81,12 @@
81
  that.marker.setPosition( event.latLng );
82
  that.updateCoordinate( event.latLng );
83
  } );
 
 
 
 
 
 
84
  google.maps.event.addListener( this.marker, 'drag', function ( event )
85
  {
86
  that.updateCoordinate( event.latLng );
@@ -99,18 +105,24 @@
99
  * @see https://developers.google.com/maps/documentation/javascript/reference
100
  * ('resize' Event)
101
  */
102
- $( window ).on( 'rwmb_map_refresh', function()
103
  {
104
- that.refreshMap();
105
  } );
106
 
107
- //Refresh on meta box hide and show
108
- $( document ).on( 'postbox-toggled', function() {
109
- that.refreshMap();
 
 
 
 
 
 
110
  } );
111
  },
112
 
113
- refreshMap: function()
114
  {
115
  var zoom = this.map.getZoom(),
116
  center = this.map.getCenter();
@@ -124,7 +136,7 @@
124
  },
125
 
126
  // Autocomplete address
127
- autocomplete : function ()
128
  {
129
  var that = this;
130
 
@@ -164,14 +176,14 @@
164
  },
165
 
166
  // Update coordinate to input field
167
- updateCoordinate : function ( latLng )
168
  {
169
- this.$coordinate.val( latLng.lat() + ',' + latLng.lng() );
 
170
  },
171
 
172
  // Find coordinates by address
173
- // Find coordinates by address
174
- geocodeAddress : function ()
175
  {
176
  var address,
177
  addressList = [],
@@ -209,7 +221,6 @@
209
  field.init();
210
 
211
  $( this ).data( 'mapController', field );
212
-
213
  } );
214
 
215
  $( '.rwmb-input' ).on( 'clone', function ()
11
  // Use prototype for better performance
12
  MapField.prototype = {
13
  // Initialize everything
14
+ init: function ()
15
  {
16
  this.initDomElements();
17
  this.initMapElements();
22
  },
23
 
24
  // Initialize DOM elements
25
+ initDomElements: function ()
26
  {
27
  this.canvas = this.$container.find( '.rwmb-map-canvas' )[0];
28
  this.$coordinate = this.$container.find( '.rwmb-map-coordinate' );
31
  },
32
 
33
  // Initialize map elements
34
+ initMapElements: function ()
35
  {
36
  var defaultLoc = $( this.canvas ).data( 'default-loc' ),
37
  latLng;
73
  },
74
 
75
  // Add event listeners for 'click' & 'drag'
76
+ addListeners: function ()
77
  {
78
  var that = this;
79
  google.maps.event.addListener( this.map, 'click', function ( event )
81
  that.marker.setPosition( event.latLng );
82
  that.updateCoordinate( event.latLng );
83
  } );
84
+
85
+ google.maps.event.addListener( this.map, 'zoom_changed', function ( event )
86
+ {
87
+ that.updateCoordinate( that.marker.getPosition() );
88
+ } );
89
+
90
  google.maps.event.addListener( this.marker, 'drag', function ( event )
91
  {
92
  that.updateCoordinate( event.latLng );
105
  * @see https://developers.google.com/maps/documentation/javascript/reference
106
  * ('resize' Event)
107
  */
108
+ $( window ).on( 'rwmb_map_refresh', function ()
109
  {
110
+ that.refresh();
111
  } );
112
 
113
+ // Refresh on meta box hide and show
114
+ $( document ).on( 'postbox-toggled', function ()
115
+ {
116
+ that.refresh();
117
+ } );
118
+ // Refresh on sorting meta boxes
119
+ $( '.meta-box-sortables' ).on( 'sortstop', function ()
120
+ {
121
+ that.refresh();
122
  } );
123
  },
124
 
125
+ refresh: function ()
126
  {
127
  var zoom = this.map.getZoom(),
128
  center = this.map.getCenter();
136
  },
137
 
138
  // Autocomplete address
139
+ autocomplete: function ()
140
  {
141
  var that = this;
142
 
176
  },
177
 
178
  // Update coordinate to input field
179
+ updateCoordinate: function ( latLng )
180
  {
181
+ var zoom = this.map.getZoom();
182
+ this.$coordinate.val( latLng.lat() + ',' + latLng.lng() + ',' + zoom );
183
  },
184
 
185
  // Find coordinates by address
186
+ geocodeAddress: function ()
 
187
  {
188
  var address,
189
  addressList = [],
221
  field.init();
222
 
223
  $( this ).data( 'mapController', field );
 
224
  } );
225
 
226
  $( '.rwmb-input' ).on( 'clone', function ()
js/media.js CHANGED
@@ -5,175 +5,295 @@ jQuery( function ( $ )
5
  'use strict';
6
 
7
  var views = rwmb.views = rwmb.views || {},
8
- MediaField, MediaList, MediaItem, MediaButton, MediaStatus;
9
- rwmb.test = 'spoon';
10
 
11
- MediaList = views.MediaList = Backbone.View.extend( {
12
- tagName : 'ul',
13
- className : 'rwmb-media-list',
14
- addItemView: function ( item )
 
 
 
 
 
 
 
 
 
 
 
 
 
15
  {
16
- if( ! this.itemViews[item.cid] )
 
 
 
 
 
 
 
17
  {
18
- this.itemViews[item.cid] = new this.itemView( {
19
- model : item,
20
- collection: this.collection,
21
- props : this.props
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
22
  } );
 
 
 
 
 
 
 
23
  }
24
- this.$el.append( this.itemViews[item.cid].el );
25
  },
26
 
27
- render: function ()
 
28
  {
29
- this.$el.empty();
30
- this.collection.each( this.addItemView );
 
31
  },
32
 
33
- initialize: function ( options )
 
34
  {
35
- var that = this;
36
- this.itemViews = {};
37
- this.props = options.props;
38
- this.itemView = options.itemView || MediaItem;
 
 
 
 
 
 
 
 
39
 
40
- this.listenTo( this.collection, 'add', this.addItemView );
 
 
 
 
 
 
41
 
42
- this.listenTo( this.collection, 'remove', function ( item, collection )
43
- {
44
- if ( this.itemViews[item.cid] )
45
- {
46
- this.itemViews[item.cid].remove();
47
- delete this.itemViews[item.cid];
48
- }
49
  } );
50
 
51
- //Sort media using sortable
52
- this.initSort();
53
 
54
- this.render();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
55
  },
56
 
57
- initSort: function ()
58
  {
59
- this.$el.sortable( { delay: 150 } );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
60
  }
61
  } );
62
 
 
 
 
 
63
  MediaField = views.MediaField = Backbone.View.extend( {
64
  initialize: function ( options )
65
  {
66
  var that = this;
67
  this.$input = $( options.input );
68
- this.values = this.$input.val().split( ',' );
69
- this.props = new Backbone.Model( this.$el.data() );
70
- this.props.set( 'fieldName', this.$input.attr( 'name' ) );
71
-
72
- //Create collection
73
- this.collection = new wp.media.model.Attachments();
 
74
 
75
- //Create views
76
  this.createList();
77
  this.createAddButton()
78
  this.createStatus();
79
 
80
- //Render
81
  this.render();
82
 
83
- //Limit max files
84
- this.listenTo( this.collection, 'add', function ( item, collection )
85
- {
86
- var maxFiles = this.props.get( 'maxFiles' );
87
- if ( maxFiles > 0 && this.collection.length > maxFiles )
88
- {
89
- this.collection.pop();
90
- }
91
- } );
92
 
93
- //Load initial media
94
- if ( !_.isEmpty( this.values ) )
95
  {
96
- this.collection.props.set( {
97
- query : true,
98
- include: this.values,
99
- orderby: 'post__in',
100
- order : 'ASC',
101
- type : this.props.get( 'mimeType' ),
102
- perPage: this.props.get( 'maxFiles' ) || -1
103
- } );
104
- this.collection.more();
105
- }
106
-
107
- //Listen for destroy event on input
108
- this.$input
109
- .on( 'remove', function(){
110
- if ( that.props.get( 'forceDelete' ) )
111
- {
112
- _.each( _.clone( that.collection.models ), function ( model )
113
- {
114
- model.destroy();
115
- } );
116
- }
117
- } )
118
  },
119
 
 
120
  createList: function ()
121
  {
122
- this.list = new MediaList( { collection: this.collection, props: this.props } );
123
  },
124
 
 
125
  createAddButton: function ()
126
  {
127
- this.addButton = new MediaButton( { collection: this.collection, props: this.props } );
128
  },
129
 
 
130
  createStatus: function ()
131
  {
132
- this.status = new MediaStatus( { collection: this.collection, props: this.props } );
133
  },
134
 
 
135
  render: function ()
136
  {
137
- //Empty then add parts
138
- this.$el
139
- .empty()
140
- .append(
141
- this.list.el,
142
- this.addButton.el,
143
- this.status.el
144
- );
145
  }
146
  } );
147
 
 
 
 
 
148
  MediaStatus = views.MediaStatus = Backbone.View.extend( {
149
  tagName : 'span',
150
  className : 'rwmb-media-status',
151
  template : wp.template( 'rwmb-media-status' ),
 
 
152
  initialize: function ( options )
153
  {
154
- this.props = options.props;
155
- this.listenTo( this.collection, 'add remove reset', this.render );
 
 
 
 
 
 
 
 
156
  this.render();
157
  },
158
 
159
  render: function ()
160
  {
161
- var data = {
162
- items : this.collection.length,
163
- maxFiles: this.props.get( 'maxFiles' )
164
- };
165
- this.$el.html( this.template( data ) );
166
  }
167
  } );
168
 
 
 
 
 
169
  MediaButton = views.MediaButton = Backbone.View.extend( {
170
  className: 'rwmb-add-media button',
171
  tagName : 'a',
172
  events : {
173
  click: function ()
174
  {
175
- var models = this.collection.models;
176
-
177
  // Destroy the previous collection frame.
178
  if ( this._frame )
179
  {
@@ -184,23 +304,23 @@ jQuery( function ( $ )
184
  this._frame = wp.media( {
185
  className: 'media-frame rwmb-media-frame',
186
  multiple : true,
187
- title : 'Select Media',
188
  editing : true,
189
  library : {
190
- type: this.props.get( 'mimeType' )
191
  }
192
  } );
193
-
194
  this._frame.on( 'select', function ()
195
  {
196
  var selection = this._frame.state().get( 'selection' );
197
- this.collection.add( selection.models );
198
  }, this );
199
 
200
  this._frame.open();
201
  }
202
  },
203
- render : function ()
204
  {
205
  this.$el.text( i18nRwmbMedia.add );
206
  return this;
@@ -208,48 +328,74 @@ jQuery( function ( $ )
208
 
209
  initialize: function ( options )
210
  {
211
- this.props = options.props;
212
- this.listenTo( this.collection, 'add remove reset', function ()
213
- {
214
- var maxFiles = this.props.get( 'maxFiles' );
215
 
216
- if ( maxFiles > 0 )
217
- {
218
- this.$el.toggle( this.collection.length < maxFiles );
219
- }
220
  } );
221
 
222
  this.render();
223
  }
224
  } );
225
 
 
 
 
 
226
  MediaItem = views.MediaItem = Backbone.View.extend( {
227
  tagName : 'li',
228
  className : 'rwmb-media-item',
229
  template : wp.template( 'rwmb-media-item' ),
230
  initialize: function ( options )
231
  {
232
- this.props = options.props;
233
  this.render();
234
- this.listenTo( this.model, 'destroy', function ( model )
235
- {
236
- this.collection.remove( this.model );
237
- } )
238
- .listenTo( this.model, 'change', function()
239
  {
240
  this.render();
241
- });
 
 
242
  },
243
 
 
 
244
  events: {
 
245
  'click .rwmb-remove-media': function ( e )
246
  {
247
- this.collection.remove( this.model );
248
- if ( this.props.get( 'forceDelete' ) )
 
 
 
 
 
 
249
  {
250
- this.model.destroy();
 
251
  }
252
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
253
  return false;
254
  }
255
  },
@@ -257,13 +403,12 @@ jQuery( function ( $ )
257
  render: function ()
258
  {
259
  var attrs = _.clone( this.model.attributes );
260
- attrs.fieldName = this.props.get( 'fieldName' );
261
  this.$el.html( this.template( attrs ) );
262
  return this;
263
  }
264
  } );
265
 
266
-
267
  /**
268
  * Initialize media fields
269
  * @return void
5
  'use strict';
6
 
7
  var views = rwmb.views = rwmb.views || {},
8
+ models = rwmb.models = rwmb.models || {},
9
+ Controller, MediaField, MediaList, MediaItem, MediaButton, MediaStatus;
10
 
11
+ /***
12
+ * Controller Model
13
+ * Manages data of media field and media models. Most of the media views will use this to manage the media
14
+ */
15
+ Controller = models.Controller = Backbone.Model.extend( {
16
+ //Default options
17
+ defaults: {
18
+ maxFiles: 0,
19
+ ids: [],
20
+ mimeType: '',
21
+ forceDelete: false,
22
+ showStatus: true,
23
+ length: 0
24
+ },
25
+
26
+ //Initialize Controller model
27
+ initialize: function ( options )
28
  {
29
+ var that = this;
30
+ // All numbers, no 0 ids
31
+ this.set( 'ids', _.without( _.map( this.get( 'ids' ), Number ), 0, -1 ) );
32
+
33
+ // Create items collection
34
+ this.set( 'items', new wp.media.model.Attachments() );
35
+
36
+ this.listenTo( this.get( 'items' ), 'add remove reset', function()
37
  {
38
+ var items = this.get( 'items' ),
39
+ length = items.length,
40
+ max = this.get( 'maxFiles' );
41
+
42
+ this.set( 'length', length );
43
+ this.set( 'full', max > 0 && length >= max );
44
+ } );
45
+
46
+ // Listen for destroy event on controller, delete all models when triggered
47
+ this.on( 'destroy', function ( e )
48
+ {
49
+ if( this.get( 'forceDelete' ) )
50
+ {
51
+ this.get( 'items' ).each( function ( item )
52
+ {
53
+ item.destroy();
54
+ } );
55
+ }
56
+ } );
57
+ },
58
+
59
+
60
+ // Method to load media
61
+ load: function ()
62
+ {
63
+ var that = this;
64
+ // Load initial media
65
+ if ( !_.isEmpty( this.get( 'ids' ) ) )
66
+ {
67
+ this.get( 'items' ).props.set( {
68
+ query : true,
69
+ include: this.get( 'ids' ),
70
+ orderby: 'post__in',
71
+ order : 'ASC',
72
+ type : this.get( 'mimeType' ),
73
+ perPage: this.get( 'maxFiles' ) || -1
74
  } );
75
+ // Get more then trigger ready
76
+ this.get( 'items' ).more();
77
+ }
78
+ else
79
+ {
80
+ // No initial media so ready
81
+ that.trigger( 'ready' );
82
  }
 
83
  },
84
 
85
+ // Method to remove media items
86
+ removeItem: function( item )
87
  {
88
+ this.get( 'items' ).remove( item );
89
+ if( this.get( 'forceDelete' ) )
90
+ item.destroy();
91
  },
92
 
93
+ // Method to add items
94
+ addItems: function ( items )
95
  {
96
+ if( this.get( 'maxFiles' ) )
97
+ {
98
+ var left = this.get( 'maxFiles' ) - this.get( 'items' ).length;
99
+ if( left <= 0 )
100
+ return this;
101
+
102
+ items = _.difference( items, this.get( 'items' ).models );
103
+ items = _.first( items, left );
104
+ }
105
+ this.get( 'items' ).add( items );
106
+ }
107
+ } );
108
 
109
+ /***
110
+ * Media List
111
+ * lists media
112
+ */
113
+ MediaList = views.MediaList = Backbone.View.extend( {
114
+ tagName : 'ul',
115
+ className : 'rwmb-media-list',
116
 
117
+ //Add item view
118
+ addItemView: function ( item )
119
+ {
120
+ var view = this._views[item.cid] = new this.itemView( {
121
+ model : item,
122
+ controller: this.controller
 
123
  } );
124
 
125
+ this.$el.append( view.el );
126
+ },
127
 
128
+ //Remove item view
129
+ removeItemView: function ( item )
130
+ {
131
+ if ( this._views[item.cid] )
132
+ {
133
+ this._views[item.cid].remove();
134
+ delete this._views[item.cid];
135
+ }
136
+ },
137
+
138
+ initialize: function ( options )
139
+ {
140
+ this._views = {};
141
+ this.controller = options.controller;
142
+ this.itemView = options.itemView || MediaItem;
143
+
144
+ this.setEvents();
145
+
146
+ // Sort media using sortable
147
+ this.initSortable();
148
  },
149
 
150
+ setEvents: function()
151
  {
152
+ this.listenTo( this.controller.get( 'items' ), 'add', this.addItemView );
153
+ this.listenTo( this.controller.get( 'items' ), 'remove', this.removeItemView );
154
+ },
155
+
156
+ initSortable: function ()
157
+ {
158
+ var collection = this.controller.get( 'items' );
159
+ this.$el.sortable( {
160
+ // Change the position of the attachment as soon as the
161
+ // mouse pointer overlaps a thumbnail.
162
+ tolerance: 'pointer',
163
+
164
+ // Record the initial `index` of the dragged model.
165
+ start: function( event, ui ) {
166
+ ui.item.data('sortableIndexStart', ui.item.index());
167
+ },
168
+
169
+ // Update the model's index in the collection.
170
+ // Do so silently, as the view is already accurate.
171
+ update: function( event, ui ) {
172
+ var model = collection.at( ui.item.data('sortableIndexStart') );
173
+
174
+ // Silently shift the model to its new index.
175
+ collection.remove( model, {
176
+ silent: true
177
+ });
178
+ collection.add( model, {
179
+ silent: true,
180
+ at: ui.item.index()
181
+ });
182
+
183
+ // Fire the `reset` event to ensure other collections sync.
184
+ collection.trigger( 'reset', collection );
185
+ }
186
+ } );
187
  }
188
  } );
189
 
190
+ /***
191
+ * MediaField
192
+ * Sets up media field view and subviews
193
+ */
194
  MediaField = views.MediaField = Backbone.View.extend( {
195
  initialize: function ( options )
196
  {
197
  var that = this;
198
  this.$input = $( options.input );
199
+ this.controller = new Controller( _.extend(
200
+ {
201
+ fieldName: this.$input.attr( 'name' ) ,
202
+ ids: this.$input.val().split( ',' )
203
+ },
204
+ this.$el.data()
205
+ ) );
206
 
207
+ // Create views
208
  this.createList();
209
  this.createAddButton()
210
  this.createStatus();
211
 
212
+ // Render
213
  this.render();
214
 
215
+ // Load media
216
+ this.controller.load();
 
 
 
 
 
 
 
217
 
218
+ // Listen for destroy event on input
219
+ this.$input.on( 'remove', function()
220
  {
221
+ this.controller.destroy();
222
+ } )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
223
  },
224
 
225
+ // Creates media list
226
  createList: function ()
227
  {
228
+ this.list = new MediaList( { controller: this.controller } );
229
  },
230
 
231
+ // Creates button that adds media
232
  createAddButton: function ()
233
  {
234
+ this.addButton = new MediaButton( { controller: this.controller } );
235
  },
236
 
237
+ // Creates status
238
  createStatus: function ()
239
  {
240
+ this.status = new MediaStatus( { controller: this.controller } );
241
  },
242
 
243
+ // Render field and adds sub fields
244
  render: function ()
245
  {
246
+ // Empty then add parts
247
+ this.$el.empty().append(
248
+ this.list.el,
249
+ this.addButton.el,
250
+ this.status.el
251
+ );
 
 
252
  }
253
  } );
254
 
255
+ /***
256
+ * MediaStatus
257
+ * Tracks status of media field if maxStatus is greater than 0
258
+ */
259
  MediaStatus = views.MediaStatus = Backbone.View.extend( {
260
  tagName : 'span',
261
  className : 'rwmb-media-status',
262
  template : wp.template( 'rwmb-media-status' ),
263
+
264
+ //Initialize
265
  initialize: function ( options )
266
  {
267
+ this.controller = options.controller;
268
+
269
+ //Auto hide if showStatus is false
270
+ if( ! this.controller.get( 'showStatus' ) )
271
+ this.$el.hide();
272
+
273
+ //Rerender if changes happen in controller
274
+ this.listenTo( this.controller, 'change:length', this.render );
275
+
276
+ //Render
277
  this.render();
278
  },
279
 
280
  render: function ()
281
  {
282
+ var attrs = _.clone( this.controller.attributes );
283
+ this.$el.html( this.template( attrs ) );
 
 
 
284
  }
285
  } );
286
 
287
+ /***
288
+ * Media Button
289
+ * Selects and adds ,edia to controller
290
+ */
291
  MediaButton = views.MediaButton = Backbone.View.extend( {
292
  className: 'rwmb-add-media button',
293
  tagName : 'a',
294
  events : {
295
  click: function ()
296
  {
 
 
297
  // Destroy the previous collection frame.
298
  if ( this._frame )
299
  {
304
  this._frame = wp.media( {
305
  className: 'media-frame rwmb-media-frame',
306
  multiple : true,
307
+ title : i18nRwmbMedia.select,
308
  editing : true,
309
  library : {
310
+ type: this.controller.get( 'mimeType' )
311
  }
312
  } );
313
+
314
  this._frame.on( 'select', function ()
315
  {
316
  var selection = this._frame.state().get( 'selection' );
317
+ this.controller.addItems( selection.models );
318
  }, this );
319
 
320
  this._frame.open();
321
  }
322
  },
323
+ render : function ()
324
  {
325
  this.$el.text( i18nRwmbMedia.add );
326
  return this;
328
 
329
  initialize: function ( options )
330
  {
331
+ this.controller = options.controller;
 
 
 
332
 
333
+ // Auto hide if you reach the max number of media
334
+ this.listenTo( this.controller, 'change:full', function ()
335
+ {
336
+ this.$el.toggle( ! this.controller.get( 'full' ) );
337
  } );
338
 
339
  this.render();
340
  }
341
  } );
342
 
343
+ /***
344
+ * MediaItem
345
+ * View for individual media items
346
+ */
347
  MediaItem = views.MediaItem = Backbone.View.extend( {
348
  tagName : 'li',
349
  className : 'rwmb-media-item',
350
  template : wp.template( 'rwmb-media-item' ),
351
  initialize: function ( options )
352
  {
353
+ this.controller = options.controller;
354
  this.render();
355
+ this.listenTo( this.model, 'change', function()
 
 
 
 
356
  {
357
  this.render();
358
+ } );
359
+
360
+ this.$el.data( 'id', this.model.cid);
361
  },
362
 
363
+
364
+
365
  events: {
366
+ // Event when remove button clicked
367
  'click .rwmb-remove-media': function ( e )
368
  {
369
+ this.controller.removeItem( this.model );
370
+ return false;
371
+ },
372
+
373
+ 'click .rwmb-edit-media': function( e )
374
+ {
375
+ // Destroy the previous collection frame.
376
+ if ( this._frame )
377
  {
378
+ //this.stopListening( this._frame );
379
+ this._frame.dispose();
380
  }
381
 
382
+ // Trigger the media frame to open the correct item
383
+ this._frame = wp.media( {
384
+ frame: 'edit-attachments',
385
+ controller:
386
+ {
387
+ // Needed to trick Edit modal to think there is a gridRouter
388
+ gridRouter: {
389
+ navigate: function( destination) {},
390
+ baseUrl: function( url ) {}
391
+ }
392
+ },
393
+ library: this.controller.get( 'items' ),
394
+ model: this.model
395
+ } );
396
+
397
+ this._frame.open();
398
+
399
  return false;
400
  }
401
  },
403
  render: function ()
404
  {
405
  var attrs = _.clone( this.model.attributes );
406
+ attrs.fieldName = this.controller.get( 'fieldName' );
407
  this.$el.html( this.template( attrs ) );
408
  return this;
409
  }
410
  } );
411
 
 
412
  /**
413
  * Initialize media fields
414
  * @return void
js/slider.js CHANGED
@@ -1,6 +1,6 @@
1
  jQuery( function( $ )
2
  {
3
- 'use strict';
4
 
5
  function rwmb_update_slider()
6
  {
@@ -10,6 +10,7 @@ jQuery( function( $ )
10
  value = $input.val(),
11
  options = $slider.data( 'options' );
12
 
 
13
  $slider.html( '' );
14
 
15
  if ( !value )
1
  jQuery( function( $ )
2
  {
3
+ 'use strict';
4
 
5
  function rwmb_update_slider()
6
  {
10
  value = $input.val(),
11
  options = $slider.data( 'options' );
12
 
13
+
14
  $slider.html( '' );
15
 
16
  if ( !value )
js/validate.js CHANGED
@@ -11,17 +11,18 @@ jQuery( function ( $ )
11
  $( '#ajax-loading' ).attr( 'style', '' );
12
  $form.siblings( '#message' ).remove();
13
  $form.before( '<div id="message" class="error"><p>' + rwmbValidate.summaryMessage + '</p></div>' );
14
- }
 
15
  };
16
 
17
  // Gather all validation rules
18
  $( '.rwmb-validation-rules' ).each( function ()
19
  {
20
  var subRules = $( this ).data( 'rules' );
21
- jQuery.extend( true, rules, subRules );
22
 
23
  // Required field styling
24
- $.each( subRules, function ( k, v )
25
  {
26
  if ( v['required'] )
27
  {
11
  $( '#ajax-loading' ).attr( 'style', '' );
12
  $form.siblings( '#message' ).remove();
13
  $form.before( '<div id="message" class="error"><p>' + rwmbValidate.summaryMessage + '</p></div>' );
14
+ },
15
+ ignore: ':not([class|="rwmb"])'
16
  };
17
 
18
  // Gather all validation rules
19
  $( '.rwmb-validation-rules' ).each( function ()
20
  {
21
  var subRules = $( this ).data( 'rules' );
22
+ $.extend( true, rules, subRules );
23
 
24
  // Required field styling
25
+ $.each( subRules.rules, function ( k, v )
26
  {
27
  if ( v['required'] )
28
  {
meta-box.php CHANGED
@@ -3,7 +3,7 @@
3
  * Plugin Name: Meta Box
4
  * Plugin URI: https://metabox.io
5
  * Description: Create custom meta boxes and custom fields for any post type in WordPress.
6
- * Version: 4.8.5
7
  * Author: Rilwis
8
  * Author URI: http://www.deluxeblogtips.com
9
  * License: GPL2+
3
  * Plugin Name: Meta Box
4
  * Plugin URI: https://metabox.io
5
  * Description: Create custom meta boxes and custom fields for any post type in WordPress.
6
+ * Version: 4.8.6
7
  * Author: Rilwis
8
  * Author URI: http://www.deluxeblogtips.com
9
  * License: GPL2+
readme.txt CHANGED
@@ -3,8 +3,8 @@ Contributors: metabox, rilwis, fitwp, f-j-kaiser, funkatronic, PerWiklander, rua
3
  Donate link: http://www.deluxeblogtips.com/donate
4
  Tags: meta-box, custom fields, custom field, meta, meta-boxes, admin, advanced, custom, edit, field, file, image, magic fields, matrix, more fields, Post, repeater, simple fields, text, textarea, type, cms, fields post
5
  Requires at least: 4.1
6
- Tested up to: 4.4.2
7
- Stable tag: 4.8.5
8
  License: GPLv2 or later
9
 
10
  Meta Box plugin is a powerful, professional solution to create custom meta boxes and custom fields for WordPress websites.
@@ -33,6 +33,7 @@ See more documentation [here](https://metabox.io/docs/).
33
 
34
  ### Extensions
35
 
 
36
  - [MB Admin Columns](https://metabox.io/plugins/mb-admin-columns/): Display custom fields in table columns in admin screens for All Posts (types).
37
  - [MB Term Meta](https://metabox.io/plugins/mb-term-meta/): Add meta data to categories, tags or any custom taxonomy with simple syntax.
38
  - [MB Settings Page](https://metabox.io/plugins/mb-settings-page/): Create settings pages for themes, plugins or websites with beautiful syntax.
@@ -78,6 +79,38 @@ To getting started with the plugin API, please read [this tutorial](https://meta
78
 
79
  == Changelog ==
80
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
81
  = 4.8.5 =
82
  * Improvement: Add localization for Select2 library
83
  * Improvement: Range preview output added
3
  Donate link: http://www.deluxeblogtips.com/donate
4
  Tags: meta-box, custom fields, custom field, meta, meta-boxes, admin, advanced, custom, edit, field, file, image, magic fields, matrix, more fields, Post, repeater, simple fields, text, textarea, type, cms, fields post
5
  Requires at least: 4.1
6
+ Tested up to: 4.5.2
7
+ Stable tag: 4.8.6
8
  License: GPLv2 or later
9
 
10
  Meta Box plugin is a powerful, professional solution to create custom meta boxes and custom fields for WordPress websites.
33
 
34
  ### Extensions
35
 
36
+ - [Meta Box Geolocation](https://metabox.io/plugins/meta-box-geolocation/)|Automatically and instantly populate location data with the power of Google Maps Geolocation API.
37
  - [MB Admin Columns](https://metabox.io/plugins/mb-admin-columns/): Display custom fields in table columns in admin screens for All Posts (types).
38
  - [MB Term Meta](https://metabox.io/plugins/mb-term-meta/): Add meta data to categories, tags or any custom taxonomy with simple syntax.
39
  - [MB Settings Page](https://metabox.io/plugins/mb-settings-page/): Create settings pages for themes, plugins or websites with beautiful syntax.
79
 
80
  == Changelog ==
81
 
82
+ = 4.8.6 =
83
+ * Improvement: Edit link on media items now opens edit modal
84
+ * Improvement: Refresh map when sorting meta boxes.
85
+ * Improvement: Wrap checkbox's description into a <label> to make it clickable to activate/deactivate the checkbox.
86
+ * Improvement: Remove Spanish language (ES) as it's already translated on translate.wordpress.org
87
+ * Improvement: Add support for saving zoom in map
88
+ * Improvement: Prevent output localized strings twice.
89
+ * Improvement: Add fallback for autoload in PHP 5.2 in case it's disabled.
90
+ * Improvement: No need to json_encode for custom attributes. User can pass an array to custom attribute
91
+ * Improvement: Add style for `select2` library to match WordPress admin style
92
+ * Improvement: Adds min width to select. @prop ahmadawais
93
+ * Improvement: Added `max_status` option for media type fields. `true` to show status, `false` to hide
94
+ * Improvement: Add attachment meta data to file info
95
+ * Fix: Validation for non-Meta Box fields
96
+ * Fix: advanced_image field after reload page F5 in Firefox
97
+ * Fix: Cannot read property 'getFullYear' of null
98
+ * Fix: Empty date converting to 0
99
+ * Fix: Add missing class for image_select field which prevents setting input's name when cloning.
100
+ * Fix: Fix bug with blank maps on the front end
101
+ * Fix: Fix bug with cloning media fields
102
+ * Fix: Remove empty values in clones and reset index.
103
+ * Fix: Reset of cloned select fields
104
+ * Fix: select_advanced with multiple=true adds empty selected option
105
+ * Fix: No empty option for simple select field
106
+ * Fix: Empty datetime field with timestamp => true returns January 1, 1970
107
+ * Fix: For color picker when using with Columns extension
108
+ * Fix: Fix bug with taxonomy advanced returns all taxonomy items for posts with no meta saved
109
+ * Fix: Fix bug with taxonomy advanced not saving value when field isn't multiple
110
+ * Fix: Make radio inline again
111
+ * Fix: Wrong meta value when using helper function outside the loop
112
+ * Fix: Validation now works for hidden elements in tabs
113
+
114
  = 4.8.5 =
115
  * Improvement: Add localization for Select2 library
116
  * Improvement: Range preview output added